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: int PetscFListGetPathAndFunction(const char name[],char *path[],char *function[])
 10: {
 11:   char work[256],*lfunction,ierr;

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

 27: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)

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

 34: /*
 35:     PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the 
 36:     search path.
 37: */
 38: int PetscInitialize_DynamicLibraries(void)
 39: {
 40:   char       *libname[32],libs[256],dlib[1024];
 41:   int        nmax,i,ierr;
 42:   PetscTruth found;


 46:   nmax = 32;
 47:   PetscOptionsGetStringArray(PETSC_NULL,"-dll_prepend",libname,&nmax,PETSC_NULL);
 48:   for (i=0; i<nmax; i++) {
 49:     PetscDLLibraryPrepend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
 50:     PetscFree(libname[i]);
 51:   }

 53:   PetscStrcpy(libs,PETSC_LIB_DIR);
 54:   PetscStrcat(libs,"/libpetsc");
 55:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
 56:   if (found) {
 57:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
 58:   } else {
 59:     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);
 60:   }

 62:   PetscStrcpy(libs,PETSC_LIB_DIR);
 63:   PetscStrcat(libs,"/libpetscvec");
 64:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
 65:   if (found) {
 66:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
 67:   }

 69:   PetscStrcpy(libs,PETSC_LIB_DIR);
 70:   PetscStrcat(libs,"/libpetscmat");
 71:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
 72:   if (found) {
 73:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
 74:   }

 76:   PetscStrcpy(libs,PETSC_LIB_DIR);
 77:   PetscStrcat(libs,"/libpetscdm");
 78:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
 79:   if (found) {
 80:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
 81:   }

 83:   PetscStrcpy(libs,PETSC_LIB_DIR);
 84:   PetscStrcat(libs,"/libpetscsles");
 85:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
 86:   if (found) {
 87:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
 88:   }

 90:   PetscStrcpy(libs,PETSC_LIB_DIR);
 91:   PetscStrcat(libs,"/libpetscsnes");
 92:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
 93:   if (found) {
 94:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
 95:   }

 97:   PetscStrcpy(libs,PETSC_LIB_DIR);
 98:   PetscStrcat(libs,"/libpetscts");
 99:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
100:   if (found) {
101:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
102:   }

104:   PetscStrcpy(libs,PETSC_LIB_DIR);
105:   PetscStrcat(libs,"/libpetscdm");
106:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
107:   if (found) {
108:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
109:   }

111:   PetscStrcpy(libs,PETSC_LIB_DIR);
112:   PetscStrcat(libs,"/libpetscmesh");
113:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
114:   if (found) {
115:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
116:   }

118:   PetscStrcpy(libs,PETSC_LIB_DIR);
119:   PetscStrcat(libs,"/libpetscgrid");
120:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
121:   if (found) {
122:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
123:   }

125:   PetscStrcpy(libs,PETSC_LIB_DIR);
126:   PetscStrcat(libs,"/libpetscgsolver");
127:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
128:   if (found) {
129:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
130:   }

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

140:   return(0);
141: }

143: /*
144:      PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
145: */
146: int PetscFinalize_DynamicLibraries(void)
147: {
148:   int        ierr;
149:   PetscTruth flg;

152:   PetscOptionsHasName(PETSC_NULL,"-dll_view",&flg);
153:   if (flg) {
154:     PetscDLLibraryPrintPath();
155:   }
156:   PetscDLLibraryClose(DLLibrariesLoaded);
157:   return(0);
158: }

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

162: EXTERN int PetscInitializePackage(char *);

164: int PetscInitialize_DynamicLibraries(void)
165: {

169:   /*
170:       This just initializes the draw and viewer methods, since those
171:     are ALWAYS available. The other classes are initialized the first
172:     time an XXSetType() is called.
173:   */
174:   PetscInitializePackage(PETSC_NULL);
175:   return(0);
176: }
177: int PetscFinalize_DynamicLibraries(void)
178: {

181:   return(0);
182: }
183: #endif

185: /* ------------------------------------------------------------------------------*/
186: struct _PetscFList {
187:   void        (*routine)(void);   /* the routine */
188:   char        *path;              /* path of link library containing routine */
189:   char        *name;              /* string to identify routine */
190:   char        *rname;             /* routine name in dynamic library */
191:   PetscFList  next;               /* next pointer */
192:   PetscFList  next_list;          /* used to maintain list of all lists for freeing */
193: };

195: /*
196:      Keep a linked list of PetscFLists so that we can destroy all the left-over ones.
197: */
198: static PetscFList   dlallhead = 0;

200: /*@C
201:    PetscFListAddDynamic - Given a routine and a string id, saves that routine in the
202:    specified registry.

204:    Synopsis:
205:    int PetscFListAddDynamic(PetscFList *fl,char *name,char *rname,int (*fnc)(void *))

207:    Input Parameters:
208: +  fl    - pointer registry
209: .  name  - string to identify routine
210: .  rname - routine name in dynamic library
211: -  fnc   - function pointer (optional if using dynamic libraries)

213:    Notes:
214:    Users who wish to register new methods for use by a particular PETSc
215:    component (e.g., SNES) should generally call the registration routine
216:    for that particular component (e.g., SNESRegisterDynamic()) instead of
217:    calling PetscFListAddDynamic() directly.

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

222:    Level: developer

224: .seealso: PetscFListDestroy(), SNESRegisterDynamic(), KSPRegisterDynamic(),
225:           PCRegisterDynamic(), TSRegisterDynamic(), PetscFList
226: @*/
227: int PetscFListAdd(PetscFList *fl,const char name[],const char rname[],void (*fnc)(void))
228: {
229:   PetscFList entry,ne;
230:   int        ierr;
231:   char       *fpath,*fname;


235:   if (!*fl) {
236:     ierr           = PetscNew(struct _PetscFList,&entry);
237:     ierr           = PetscStrallocpy(name,&entry->name);
238:     ierr           = PetscFListGetPathAndFunction(rname,&fpath,&fname);
239:     entry->path    = fpath;
240:     entry->rname   = fname;
241:     entry->routine = fnc;
242:     entry->next    = 0;
243:     *fl = entry;

245:     /* add this new list to list of all lists */
246:     if (!dlallhead) {
247:       dlallhead        = *fl;
248:       (*fl)->next_list = 0;
249:     } else {
250:       ne               = dlallhead;
251:       dlallhead        = *fl;
252:       (*fl)->next_list = ne;
253:     }
254:   } else {
255:     /* search list to see if it is already there */
256:     ne = *fl;
257:     while (ne) {
258:       PetscTruth founddup;

260:       PetscStrcmp(ne->name,name,&founddup);
261:       if (founddup) { /* found duplicate */
262:         PetscFListGetPathAndFunction(rname,&fpath,&fname);
263:         PetscStrfree(ne->path);
264:         PetscStrfree(ne->rname);
265:         ne->path    = fpath;
266:         ne->rname   = fname;
267:         ne->routine = fnc;
268:         return(0);
269:       }
270:       if (ne->next) ne = ne->next; else break;
271:     }
272:     /* create new entry and add to end of list */
273:     ierr           = PetscNew(struct _PetscFList,&entry);
274:     ierr           = PetscStrallocpy(name,&entry->name);
275:     ierr           = PetscFListGetPathAndFunction(rname,&fpath,&fname);
276:     entry->path    = fpath;
277:     entry->rname   = fname;
278:     entry->routine = fnc;
279:     entry->next    = 0;
280:     ne->next       = entry;
281:   }

283:   return(0);
284: }

286: /*@
287:     PetscFListDestroy - Destroys a list of registered routines.

289:     Input Parameter:
290: .   fl  - pointer to list

292:     Level: developer

294: .seealso: PetscFListAddDynamic(), PetscFList
295: @*/
296: int PetscFListDestroy(PetscFList *fl)
297: {
298:   PetscFList next,entry,tmp = dlallhead;
299:   int        ierr;

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

304:   if (!dlallhead) {
305:     return(0);
306:   }

308:   /*
309:        Remove this entry from the master DL list (if it is in it)
310:   */
311:   if (dlallhead == *fl) {
312:     if (dlallhead->next_list) {
313:       dlallhead = dlallhead->next_list;
314:     } else {
315:       dlallhead = 0;
316:     }
317:   } else {
318:     while (tmp->next_list != *fl) {
319:       tmp = tmp->next_list;
320:       if (!tmp->next_list) break;
321:     }
322:     if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
323:   }

325:   /* free this list */
326:   entry = *fl;
327:   while (entry) {
328:     next = entry->next;
329:     PetscStrfree(entry->path);
330:     PetscFree(entry->name);
331:     PetscFree(entry->rname);
332:     PetscFree(entry);
333:     entry = next;
334:   }
335:   *fl = 0;
336:   return(0);
337: }

339: /*
340:    Destroys all the function lists that anyone has every registered, such as KSPList, VecList, etc.
341: */
342: int PetscFListDestroyAll(void)
343: {
344:   PetscFList tmp2,tmp1 = dlallhead;
345:   int        ierr;

348:   while (tmp1) {
349:     tmp2 = tmp1->next_list;
350:     PetscFListDestroy(&tmp1);
351:     tmp1 = tmp2;
352:   }
353:   dlallhead = 0;
354:   return(0);
355: }

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

360:     Input Parameters:
361: +   comm - processors looking for routine
362: .   fl   - pointer to list
363: -   name - name string

365:     Output Parameters:
366: .   r - the routine

368:     Level: developer

370: .seealso: PetscFListAddDynamic(), PetscFList
371: @*/
372: int PetscFListFind(MPI_Comm comm,PetscFList fl,const char name[],void (**r)(void))
373: {
374:   PetscFList   entry = fl;
375:   int          ierr;
376:   char         *function,*path;
377: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
378:   char         *newpath;
379: #endif
380:   PetscTruth   flg,f1,f2,f3;
381: 
383:   if (!name) SETERRQ(1,"Trying to find routine with null name");

385:   *r = 0;
386:   PetscFListGetPathAndFunction(name,&path,&function);

388:   /*
389:         If path then append it to search libraries
390:   */
391: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
392:   if (path) {
393:     PetscDLLibraryAppend(comm,&DLLibrariesLoaded,path);
394:   }
395: #endif

397:   while (entry) {
398:     flg = PETSC_FALSE;
399:     if (path && entry->path) {
400:       PetscStrcmp(path,entry->path,&f1);
401:       PetscStrcmp(function,entry->rname,&f2);
402:       PetscStrcmp(function,entry->name,&f3);
403:       flg =  (PetscTruth) ((f1 && f2) || (f1 && f3));
404:     } else if (!path) {
405:       PetscStrcmp(function,entry->name,&f1);
406:       PetscStrcmp(function,entry->rname,&f2);
407:       flg =  (PetscTruth) (f1 || f2);
408:     } else {
409:       PetscStrcmp(function,entry->name,&flg);
410:       if (flg) {
411:         PetscFree(function);
412:         PetscStrallocpy(entry->rname,&function);
413:       } else {
414:         PetscStrcmp(function,entry->rname,&flg);
415:       }
416:     }

418:     if (flg) {

420:       if (entry->routine) {
421:         *r   = entry->routine;
422:         PetscStrfree(path);
423:         PetscFree(function);
424:         return(0);
425:       }
426: 
427:       if ((path && entry->path && f3) || (!path && f1)) { /* convert name of function (alias) to actual function name */
428:         PetscFree(function);
429:         PetscStrallocpy(entry->rname,&function);
430:       }

432:       /* it is not yet in memory so load from dynamic library */
433: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
434:       newpath = path;
435:       if (!path) newpath = entry->path;
436:       PetscDLLibrarySym(comm,&DLLibrariesLoaded,newpath,entry->rname,(void **)r);
437:       if (*r) {
438:         entry->routine = *r;
439:         PetscStrfree(path);
440:         PetscFree(function);
441:         return(0);
442:       } else {
443:         PetscErrorPrintf("Unable to find function. Search path:n");
444:         PetscDLLibraryPrintPath();
445:         SETERRQ1(1,"Unable to find function:%s: either it is mis-spelled or dynamic library is not in path",entry->rname);
446:       }
447: #endif
448:     }
449:     entry = entry->next;
450:   }

452: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
453:   /* Function never registered; try for it anyway */
454:   PetscDLLibrarySym(comm,&DLLibrariesLoaded,path,function,(void **)r);
455:   PetscStrfree(path);
456:   if (*r) {
457:     PetscFListAddDynamic(&fl,name,name,r);
458:   }
459: #endif

461:   /*
462:        Do not generate error, just end
463:   PetscErrorPrintf("Function name: %sn",function);
464:   PetscDLLibraryPrintPath();
465:   SETERRQ(1,"Unable to find function: either it is mis-spelled or dynamic library is not in path");
466:   */

468:   PetscFree(function);
469:   return(0);
470: }

472: /*@
473:    PetscFListView - prints out contents of an PetscFList

475:    Collective over MPI_Comm

477:    Input Parameters:
478: +  list - the list of functions
479: -  viewer - currently ignored

481:    Level: developer

483: .seealso: PetscFListAddDynamic(), PetscFListPrintTypes(), PetscFList
484: @*/
485: int PetscFListView(PetscFList list,PetscViewer viewer)
486: {
487:   int        ierr;
488:   PetscTruth isascii;

491:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
494: 
495:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
496:   if (!isascii) SETERRQ(1,"Only ASCII viewer supported");

498:   while (list) {
499:     if (list->path) {
500:       PetscViewerASCIIPrintf(viewer," %s %s %sn",list->path,list->name,list->rname);
501:     } else {
502:       PetscViewerASCIIPrintf(viewer," %s %sn",list->name,list->rname);
503:     }
504:     list = list->next;
505:   }
506:   PetscViewerASCIIPrintf(viewer,"n");
507:   return(0);
508: }

510: /*@
511:    PetscFListGet - Gets an array the contains the entries in PetscFList, this is used
512:          by help etc.

514:    Collective over MPI_Comm

516:    Input Parameter:
517: .  list   - list of types

519:    Output Parameter:
520: +  array - array of names
521: -  n - length of array

523:    Notes:
524:        This allocates the array so that must be freed. BUT the individual entries are
525:     not copied so should not be freed.

527:    Level: developer

529: .seealso: PetscFListAddDynamic(), PetscFList
530: @*/
531: int PetscFListGet(PetscFList list,char ***array,int *n)
532: {
533:   int        count = 0,ierr;
534:   PetscFList klist = list;

537:   while (list) {
538:     list = list->next;
539:     count++;
540:   }
541:   ierr  = PetscMalloc((count+1)*sizeof(char *),array);
542:   count = 0;
543:   while (klist) {
544:     (*array)[count] = klist->name;
545:     klist = klist->next;
546:     count++;
547:   }
548:   (*array)[count] = 0;
549:   *n = count+1;

551:   return(0);
552: }


555: /*@C
556:    PetscFListPrintTypes - Prints the methods available.

558:    Collective over MPI_Comm

560:    Input Parameters:
561: +  comm   - the communicator (usually MPI_COMM_WORLD)
562: .  fd     - file to print to, usually stdout
563: .  prefix - prefix to prepend to name (optional)
564: .  name   - option string (for example, "-ksp_type")
565: .  text - short description of the object (for example, "Krylov solvers")
566: .  man - name of manual page that discusses the object (for example, "KSPCreate")
567: -  list   - list of types

569:    Level: developer

571: .seealso: PetscFListAddDynamic(), PetscFList
572: @*/
573: int PetscFListPrintTypes(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],char *text,char *man,PetscFList list)
574: {
575:   int      ierr,count = 0;
576:   char     p[64];

579:   if (!fd) fd = stdout;

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

585:   while (list) {
586:     PetscFPrintf(comm,fd," %s",list->name);
587:     list = list->next;
588:     count++;
589:     if (count == 8) {PetscFPrintf(comm,fd,"n     ");}
590:   }
591:   PetscFPrintf(comm,fd," (see manual page %s)n",man);
592:   return(0);
593: }

595: /*@
596:     PetscFListDuplicate - Creates a new list from a given object list.

598:     Input Parameters:
599: .   fl   - pointer to list

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

604:     Level: developer

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

608: @*/
609: int PetscFListDuplicate(PetscFList fl,PetscFList *nl)
610: {
611:   int  ierr;
612:   char path[1024];

615:   while (fl) {
616:     /* this is silly, rebuild the complete pathname */
617:     if (fl->path) {
618:       PetscStrcpy(path,fl->path);
619:       PetscStrcat(path,":");
620:       PetscStrcat(path,fl->name);
621:     } else {
622:       PetscStrcpy(path,fl->name);
623:     }
624:     PetscFListAddDynamic(nl,path,fl->rname,fl->routine);
625:     fl   = fl->next;
626:   }
627:   return(0);
628: }


631: /*
632:     PetscFListConcat - joins name of a libary, and the path where it is located
633:     into a single string.

635:     Input Parameters:
636: .   path   - path to the library name.
637: .   name   - name of the library

639:     Output Parameters:
640: .   fullname - the name that is the union of the path and the library name,
641:                delimited by a semicolon, i.e., path:name

643:     Notes:
644:     If the path is NULL, assumes that the name, specified also includes
645:     the path as path:name

647: */
648: int PetscFListConcat(const char path[],const char name[],char fullname[])
649: {
652:   if (path) {
653:     PetscStrcpy(fullname,path);
654:     PetscStrcat(fullname,":");
655:     PetscStrcat(fullname,name);
656:   } else {
657:     PetscStrcpy(fullname,name);
658:   }
659:   return(0);
660: }