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: PetscDLLibrary 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:   CHKMEMQ;
311:   if (!*fl) return(0);

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

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

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

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

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

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

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

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

381:     Level: developer

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

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

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

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

431:     if (flg) {

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

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

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

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

482:    Collective over MPI_Comm

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

488:    Level: developer

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

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

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

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

523:    Collective over MPI_Comm

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

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

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

536:    Level: developer

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

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

561:   return(0);
562: }


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

570:    Collective over MPI_Comm

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

581:    Level: developer

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

592:   if (!fd) fd = stdout;

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

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

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

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

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

619:     Level: developer

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

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

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


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

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

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

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

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