Actual source code: reg.c

  1: #define PETSC_DLL
  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

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

 17:   PetscStrncpy(work,name,256);
 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: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)

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

 39: /*
 40:     PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the 
 41:     search path.
 42: */
 43: PetscErrorCode  PetscInitialize_DynamicLibraries(void)
 44: {
 45:   char           *libname[32],libs[PETSC_MAX_PATH_LEN],dlib[PETSC_MAX_PATH_LEN];
 47:   PetscInt       nmax,i;
 48:   PetscTruth     found;


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

 59:   PetscStrcpy(libs,"${PETSC_LIB_DIR}");
 60:   PetscStrcat(libs,"/libpetsc");
 61:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
 62:   if (found) {
 63:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
 64:   } else {
 65:     SETERRQ1(PETSC_ERR_FILE_OPEN,"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.h\n and rebuild libraries before moving",libs);
 66:   }

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

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

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

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

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

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

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

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

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

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

139:   return(0);
140: }

144: /*
145:      PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
146: */
147: PetscErrorCode PetscFinalize_DynamicLibraries(void)
148: {
150:   PetscTruth     flg;

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

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

165: PetscErrorCode  PetscInitialize_DynamicLibraries(void)
166: {

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

184:   return(0);
185: }
186: #endif

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

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

205: /*@C
206:    PetscFListAddDynamic - Given a routine and a string id, saves that routine in the
207:    specified registry.

209:      Not Collective

211:    Input Parameters:
212: +  fl    - pointer registry
213: .  name  - string to identify routine
214: .  rname - routine name in dynamic library
215: -  fnc   - function pointer (optional if using dynamic libraries)

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

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

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

228:    Level: developer

230: .seealso: PetscFListDestroy(), SNESRegisterDynamic(), KSPRegisterDynamic(),
231:           PCRegisterDynamic(), TSRegisterDynamic(), PetscFList
232: @*/
233: PetscErrorCode  PetscFListAdd(PetscFList *fl,const char name[],const char rname[],void (*fnc)(void))
234: {
235:   PetscFList     entry,ne;
237:   char           *fpath,*fname;


241:   if (!*fl) {
242:     PetscNew(struct _n_PetscFList,&entry);
243:     PetscStrallocpy(name,&entry->name);
244:     PetscFListGetPathAndFunction(rname,&fpath,&fname);
245:     entry->path    = fpath;
246:     entry->rname   = fname;
247:     entry->routine = fnc;
248:     entry->next    = 0;
249:     *fl = entry;

251:     /* add this new list to list of all lists */
252:     if (!dlallhead) {
253:       dlallhead        = *fl;
254:       (*fl)->next_list = 0;
255:     } else {
256:       ne               = dlallhead;
257:       dlallhead        = *fl;
258:       (*fl)->next_list = ne;
259:     }
260:   } else {
261:     /* search list to see if it is already there */
262:     ne = *fl;
263:     while (ne) {
264:       PetscTruth founddup;

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

289:   return(0);
290: }

294: /*@
295:     PetscFListDestroy - Destroys a list of registered routines.

297:     Input Parameter:
298: .   fl  - pointer to list

300:     Level: developer

302: .seealso: PetscFListAddDynamic(), PetscFList
303: @*/
304: PetscErrorCode  PetscFListDestroy(PetscFList *fl)
305: {
306:   PetscFList     next,entry,tmp = dlallhead;

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

312:   if (!dlallhead) {
313:     return(0);
314:   }

316:   /*
317:        Remove this entry from the master DL list (if it is in it)
318:   */
319:   if (dlallhead == *fl) {
320:     if (dlallhead->next_list) {
321:       dlallhead = dlallhead->next_list;
322:     } else {
323:       dlallhead = 0;
324:     }
325:   } else {
326:     while (tmp->next_list != *fl) {
327:       tmp = tmp->next_list;
328:       if (!tmp->next_list) break;
329:     }
330:     if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
331:   }

333:   /* free this list */
334:   entry = *fl;
335:   while (entry) {
336:     next = entry->next;
337:     PetscStrfree(entry->path);
338:     PetscFree(entry->name);
339:     PetscFree(entry->rname);
340:     PetscFree(entry);
341:     entry = next;
342:   }
343:   *fl = 0;
344:   return(0);
345: }

347: /*
348:    Destroys all the function lists that anyone has every registered, such as KSPList, VecList, etc.
349: */
352: PetscErrorCode  PetscFListDestroyAll(void)
353: {
354:   PetscFList     tmp2,tmp1 = dlallhead;

358:   while (tmp1) {
359:     tmp2 = tmp1->next_list;
360:     PetscFListDestroy(&tmp1);
361:     tmp1 = tmp2;
362:   }
363:   dlallhead = 0;
364:   return(0);
365: }

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

372:     Input Parameters:
373: +   comm - processors looking for routine
374: .   fl   - pointer to list
375: -   name - name string

377:     Output Parameters:
378: .   r - the routine

380:     Level: developer

382: .seealso: PetscFListAddDynamic(), PetscFList
383: @*/
384: PetscErrorCode  PetscFListFind(MPI_Comm comm,PetscFList fl,const char name[],void (**r)(void))
385: {
386:   PetscFList     entry = fl;
388:   char           *function,*path;
389: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
390:   char           *newpath;
391: #endif
392:   PetscTruth   flg,f1,f2,f3;
393: 
395:   if (!name) SETERRQ(PETSC_ERR_ARG_NULL,"Trying to find routine with null name");

397:   *r = 0;
398:   PetscFListGetPathAndFunction(name,&path,&function);

400:   /*
401:         If path then append it to search libraries
402:   */
403: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
404:   if (path) {
405:     PetscDLLibraryAppend(comm,&DLLibrariesLoaded,path);
406:   }
407: #endif

409:   while (entry) {
410:     flg = PETSC_FALSE;
411:     if (path && entry->path) {
412:       PetscStrcmp(path,entry->path,&f1);
413:       PetscStrcmp(function,entry->rname,&f2);
414:       PetscStrcmp(function,entry->name,&f3);
415:       flg =  (PetscTruth) ((f1 && f2) || (f1 && f3));
416:     } else if (!path) {
417:       PetscStrcmp(function,entry->name,&f1);
418:       PetscStrcmp(function,entry->rname,&f2);
419:       flg =  (PetscTruth) (f1 || f2);
420:     } else {
421:       PetscStrcmp(function,entry->name,&flg);
422:       if (flg) {
423:         PetscFree(function);
424:         PetscStrallocpy(entry->rname,&function);
425:       } else {
426:         PetscStrcmp(function,entry->rname,&flg);
427:       }
428:     }

430:     if (flg) {

432:       if (entry->routine) {
433:         *r   = entry->routine;
434:         PetscStrfree(path);
435:         PetscFree(function);
436:         return(0);
437:       }
438: 
439:       if ((path && entry->path && f3) || (!path && f1)) { /* convert name of function (alias) to actual function name */
440:         PetscFree(function);
441:         PetscStrallocpy(entry->rname,&function);
442:       }

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

464: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
465:   /* Function never registered; try for it anyway */
466:   PetscDLLibrarySym(comm,&DLLibrariesLoaded,path,function,(void **)r);
467:   PetscStrfree(path);
468:   if (*r) {
469:     PetscFListAdd(&fl,name,name,*r);
470:   }
471: #endif
472:   PetscFree(function);
473:   return(0);
474: }

478: /*@
479:    PetscFListView - prints out contents of an PetscFList

481:    Collective over MPI_Comm

483:    Input Parameters:
484: +  list - the list of functions
485: -  viewer - currently ignored

487:    Level: developer

489: .seealso: PetscFListAddDynamic(), PetscFListPrintTypes(), PetscFList
490: @*/
491: PetscErrorCode  PetscFListView(PetscFList list,PetscViewer viewer)
492: {
494:   PetscTruth     iascii;

497:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
500: 
501:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
502:   if (!iascii) SETERRQ(PETSC_ERR_SUP,"Only ASCII viewer supported");

504:   while (list) {
505:     if (list->path) {
506:       PetscViewerASCIIPrintf(viewer," %s %s %s\n",list->path,list->name,list->rname);
507:     } else {
508:       PetscViewerASCIIPrintf(viewer," %s %s\n",list->name,list->rname);
509:     }
510:     list = list->next;
511:   }
512:   PetscViewerASCIIPrintf(viewer,"\n");
513:   return(0);
514: }

518: /*@
519:    PetscFListGet - Gets an array the contains the entries in PetscFList, this is used
520:          by help etc.

522:    Collective over MPI_Comm

524:    Input Parameter:
525: .  list   - list of types

527:    Output Parameter:
528: +  array - array of names
529: -  n - length of array

531:    Notes:
532:        This allocates the array so that must be freed. BUT the individual entries are
533:     not copied so should not be freed.

535:    Level: developer

537: .seealso: PetscFListAddDynamic(), PetscFList
538: @*/
539: PetscErrorCode  PetscFListGet(PetscFList list,char ***array,int *n)
540: {
542:   PetscInt       count = 0;
543:   PetscFList     klist = list;

546:   while (list) {
547:     list = list->next;
548:     count++;
549:   }
550:   PetscMalloc((count+1)*sizeof(char *),array);
551:   count = 0;
552:   while (klist) {
553:     (*array)[count] = klist->name;
554:     klist = klist->next;
555:     count++;
556:   }
557:   (*array)[count] = 0;
558:   *n = count+1;

560:   return(0);
561: }


566: /*@C
567:    PetscFListPrintTypes - Prints the methods available.

569:    Collective over MPI_Comm

571:    Input Parameters:
572: +  comm   - the communicator (usually MPI_COMM_WORLD)
573: .  fd     - file to print to, usually stdout
574: .  prefix - prefix to prepend to name (optional)
575: .  name   - option string (for example, "-ksp_type")
576: .  text - short description of the object (for example, "Krylov solvers")
577: .  man - name of manual page that discusses the object (for example, "KSPCreate")
578: -  list   - list of types

580:    Level: developer

582: .seealso: PetscFListAddDynamic(), PetscFList
583: @*/
584: PetscErrorCode  PetscFListPrintTypes(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[],PetscFList list)
585: {
587:   PetscInt       count = 0;
588:   char           p[64];

591:   if (!fd) fd = stdout;

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

597:   while (list) {
598:     PetscFPrintf(comm,fd," %s",list->name);
599:     list = list->next;
600:     count++;
601:     if (count == 8) {PetscFPrintf(comm,fd,"\n     ");}
602:   }
603:   PetscFPrintf(comm,fd," (%s)\n",man);
604:   return(0);
605: }

609: /*@
610:     PetscFListDuplicate - Creates a new list from a given object list.

612:     Input Parameters:
613: .   fl   - pointer to list

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

618:     Level: developer

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

622: @*/
623: PetscErrorCode  PetscFListDuplicate(PetscFList fl,PetscFList *nl)
624: {
626:   char           path[PETSC_MAX_PATH_LEN];

629:   while (fl) {
630:     /* this is silly, rebuild the complete pathname */
631:     if (fl->path) {
632:       PetscStrcpy(path,fl->path);
633:       PetscStrcat(path,":");
634:       PetscStrcat(path,fl->name);
635:     } else {
636:       PetscStrcpy(path,fl->name);
637:     }
638:     PetscFListAdd(nl,path,fl->rname,fl->routine);
639:     fl   = fl->next;
640:   }
641:   return(0);
642: }


647: /*
648:     PetscFListConcat - joins name of a libary, and the path where it is located
649:     into a single string.

651:     Input Parameters:
652: .   path   - path to the library name.
653: .   name   - name of the library

655:     Output Parameters:
656: .   fullname - the name that is the union of the path and the library name,
657:                delimited by a semicolon, i.e., path:name

659:     Notes:
660:     If the path is NULL, assumes that the name, specified also includes
661:     the path as path:name

663: */
664: PetscErrorCode  PetscFListConcat(const char path[],const char name[],char fullname[])
665: {
668:   if (path) {
669:     PetscStrcpy(fullname,path);
670:     PetscStrcat(fullname,":");
671:     PetscStrcat(fullname,name);
672:   } else {
673:     PetscStrcpy(fullname,name);
674:   }
675:   return(0);
676: }