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: static PetscErrorCode  PetscLoadDynamicLibrary(const char *name,PetscTruth *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: }

 63: /*
 64:     PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the 
 65:     search path.
 66: */
 67: PetscErrorCode  PetscInitialize_DynamicLibraries(void)
 68: {
 69:   char           *libname[32];
 71:   PetscInt       nmax,i;
 72:   PetscTruth     found;


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

 83:   PetscLoadDynamicLibrary("",&found);
 84:   if (!found) SETERRQ(PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
 85:   PetscLoadDynamicLibrary("vec",&found);
 86:   if (!found) SETERRQ(PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
 87:   PetscLoadDynamicLibrary("mat",&found);
 88:   if (!found) SETERRQ(PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
 89:   PetscLoadDynamicLibrary("dm",&found);
 90:   if (!found) SETERRQ(PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
 91:   PetscLoadDynamicLibrary("ksp",&found);
 92:   if (!found) SETERRQ(PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
 93:   PetscLoadDynamicLibrary("snes",&found);
 94:   if (!found) SETERRQ(PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
 95:   PetscLoadDynamicLibrary("ts",&found);
 96:   if (!found) SETERRQ(PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");

 98:   PetscLoadDynamicLibrary("mesh",&found);
 99:   PetscLoadDynamicLibrary("contrib",&found);

101:   nmax = 32;
102:   PetscOptionsGetStringArray(PETSC_NULL,"-dll_append",libname,&nmax,PETSC_NULL);
103:   for (i=0; i<nmax; i++) {
104:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
105:     PetscDLLibraryCCAAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
106:     PetscFree(libname[i]);
107:   }
108:   return(0);
109: }

113: /*
114:      PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
115: */
116: PetscErrorCode PetscFinalize_DynamicLibraries(void)
117: {
119:   PetscTruth     flg;

122:   PetscOptionsHasName(PETSC_NULL,"-dll_view",&flg);
123:   if (flg) {
124:     PetscDLLibraryPrintPath();
125:   }
126:   PetscDLLibraryClose(DLLibrariesLoaded);
127:   return(0);
128: }

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

134: PetscErrorCode  PetscInitialize_DynamicLibraries(void)
135: {

139:   /*
140:       This just initializes the draw and viewer methods, since those
141:     are ALWAYS available. The other classes are initialized the first
142:     time an XXSetType() is called.
143:   */
144:   PetscInitializePackage(PETSC_NULL);
145:   return(0);
146: }
149: PetscErrorCode PetscFinalize_DynamicLibraries(void)
150: {

153:   return(0);
154: }
155: #endif

157: /* ------------------------------------------------------------------------------*/
158: struct _n_PetscFList {
159:   void        (*routine)(void);   /* the routine */
160:   char        *path;              /* path of link library containing routine */
161:   char        *name;              /* string to identify routine */
162:   char        *rname;             /* routine name in dynamic library */
163:   PetscFList  next;               /* next pointer */
164:   PetscFList  next_list;          /* used to maintain list of all lists for freeing */
165: };

167: /*
168:      Keep a linked list of PetscFLists so that we can destroy all the left-over ones.
169: */
170: static PetscFList   dlallhead = 0;

174: /*@C
175:    PetscFListAddDynamic - Given a routine and a string id, saves that routine in the
176:    specified registry.

178:      Not Collective

180:    Input Parameters:
181: +  fl    - pointer registry
182: .  name  - string to identify routine
183: .  rname - routine name in dynamic library
184: -  fnc   - function pointer (optional if using dynamic libraries)

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

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

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

197:    Level: developer

199: .seealso: PetscFListDestroy(), SNESRegisterDynamic(), KSPRegisterDynamic(),
200:           PCRegisterDynamic(), TSRegisterDynamic(), PetscFList
201: @*/
202: PetscErrorCode  PetscFListAdd(PetscFList *fl,const char name[],const char rname[],void (*fnc)(void))
203: {
204:   PetscFList     entry,ne;
206:   char           *fpath,*fname;


210:   if (!*fl) {
211:     PetscNew(struct _n_PetscFList,&entry);
212:     PetscStrallocpy(name,&entry->name);
213:     PetscFListGetPathAndFunction(rname,&fpath,&fname);
214:     entry->path    = fpath;
215:     entry->rname   = fname;
216:     entry->routine = fnc;
217:     entry->next    = 0;
218:     *fl = entry;

220:     /* add this new list to list of all lists */
221:     if (!dlallhead) {
222:       dlallhead        = *fl;
223:       (*fl)->next_list = 0;
224:     } else {
225:       ne               = dlallhead;
226:       dlallhead        = *fl;
227:       (*fl)->next_list = ne;
228:     }
229:   } else {
230:     /* search list to see if it is already there */
231:     ne = *fl;
232:     while (ne) {
233:       PetscTruth founddup;

235:       PetscStrcmp(ne->name,name,&founddup);
236:       if (founddup) { /* found duplicate */
237:         PetscFListGetPathAndFunction(rname,&fpath,&fname);
238:         PetscStrfree(ne->path);
239:         PetscStrfree(ne->rname);
240:         ne->path    = fpath;
241:         ne->rname   = fname;
242:         ne->routine = fnc;
243:         return(0);
244:       }
245:       if (ne->next) ne = ne->next; else break;
246:     }
247:     /* create new entry and add to end of list */
248:     PetscNew(struct _n_PetscFList,&entry);
249:     PetscStrallocpy(name,&entry->name);
250:     PetscFListGetPathAndFunction(rname,&fpath,&fname);
251:     entry->path    = fpath;
252:     entry->rname   = fname;
253:     entry->routine = fnc;
254:     entry->next    = 0;
255:     ne->next       = entry;
256:   }

258:   return(0);
259: }

263: /*@
264:     PetscFListDestroy - Destroys a list of registered routines.

266:     Input Parameter:
267: .   fl  - pointer to list

269:     Level: developer

271: .seealso: PetscFListAddDynamic(), PetscFList
272: @*/
273: PetscErrorCode  PetscFListDestroy(PetscFList *fl)
274: {
275:   PetscFList     next,entry,tmp = dlallhead;

279:   CHKMEMQ;
280:   if (!*fl) return(0);

282:   if (!dlallhead) {
283:     return(0);
284:   }

286:   /*
287:        Remove this entry from the master DL list (if it is in it)
288:   */
289:   if (dlallhead == *fl) {
290:     if (dlallhead->next_list) {
291:       dlallhead = dlallhead->next_list;
292:     } else {
293:       dlallhead = 0;
294:     }
295:   } else {
296:     while (tmp->next_list != *fl) {
297:       tmp = tmp->next_list;
298:       if (!tmp->next_list) break;
299:     }
300:     if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
301:   }

303:   /* free this list */
304:   entry = *fl;
305:   while (entry) {
306:     next = entry->next;
307:     PetscStrfree(entry->path);
308:     PetscFree(entry->name);
309:     PetscFree(entry->rname);
310:     PetscFree(entry);
311:     entry = next;
312:   }
313:   *fl = 0;
314:   return(0);
315: }

317: /*
318:    Destroys all the function lists that anyone has every registered, such as KSPList, VecList, etc.
319: */
322: PetscErrorCode  PetscFListDestroyAll(void)
323: {
324:   PetscFList     tmp2,tmp1 = dlallhead;

328:   while (tmp1) {
329:     tmp2 = tmp1->next_list;
330:     PetscFListDestroy(&tmp1);
331:     tmp1 = tmp2;
332:   }
333:   dlallhead = 0;
334:   return(0);
335: }

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

342:     Input Parameters:
343: +   fl   - pointer to list
344: .   comm - processors looking for routine
345: -   name - name string

347:     Output Parameters:
348: .   r - the routine

350:     Level: developer

352: .seealso: PetscFListAddDynamic(), PetscFList
353: @*/
354: PetscErrorCode  PetscFListFind(PetscFList fl,MPI_Comm comm,const char name[],void (**r)(void))
355: {
356:   PetscFList     entry = fl;
358:   char           *function,*path;
359: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
360:   char           *newpath;
361: #endif
362:   PetscTruth   flg,f1,f2,f3;
363: 
365:   if (!name) SETERRQ(PETSC_ERR_ARG_NULL,"Trying to find routine with null name");

367:   *r = 0;
368:   PetscFListGetPathAndFunction(name,&path,&function);

370:   /*
371:         If path then append it to search libraries
372:   */
373: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
374:   if (path) {
375:     PetscDLLibraryAppend(comm,&DLLibrariesLoaded,path);
376:   }
377: #endif

379:   while (entry) {
380:     flg = PETSC_FALSE;
381:     if (path && entry->path) {
382:       PetscStrcmp(path,entry->path,&f1);
383:       PetscStrcmp(function,entry->rname,&f2);
384:       PetscStrcmp(function,entry->name,&f3);
385:       flg =  (PetscTruth) ((f1 && f2) || (f1 && f3));
386:     } else if (!path) {
387:       PetscStrcmp(function,entry->name,&f1);
388:       PetscStrcmp(function,entry->rname,&f2);
389:       flg =  (PetscTruth) (f1 || f2);
390:     } else {
391:       PetscStrcmp(function,entry->name,&flg);
392:       if (flg) {
393:         PetscFree(function);
394:         PetscStrallocpy(entry->rname,&function);
395:       } else {
396:         PetscStrcmp(function,entry->rname,&flg);
397:       }
398:     }

400:     if (flg) {

402:       if (entry->routine) {
403:         *r   = entry->routine;
404:         PetscStrfree(path);
405:         PetscFree(function);
406:         return(0);
407:       }
408: 
409:       if ((path && entry->path && f3) || (!path && f1)) { /* convert name of function (alias) to actual function name */
410:         PetscFree(function);
411:         PetscStrallocpy(entry->rname,&function);
412:       }

414:       /* it is not yet in memory so load from dynamic library */
415: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
416:       newpath = path;
417:       if (!path) newpath = entry->path;
418:       PetscDLLibrarySym(comm,&DLLibrariesLoaded,newpath,entry->rname,(void **)r);
419:       if (*r) {
420:         entry->routine = *r;
421:         PetscStrfree(path);
422:         PetscFree(function);
423:         return(0);
424:       } else {
425:         (*PetscErrorPrintf)("Unable to find function. Search path:\n");
426:         PetscDLLibraryPrintPath();
427:         SETERRQ1(PETSC_ERR_PLIB,"Unable to find function:%s: either it is mis-spelled or dynamic library is not in path",entry->rname);
428:       }
429: #endif
430:     }
431:     entry = entry->next;
432:   }

434: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
435:   /* Function never registered; try for it anyway */
436:   PetscDLLibrarySym(comm,&DLLibrariesLoaded,path,function,(void **)r);
437:   PetscStrfree(path);
438:   if (*r) {
439:     PetscFListAdd(&fl,name,name,*r);
440:   }
441: #endif
442:   PetscFree(function);
443:   return(0);
444: }

448: /*@
449:    PetscFListView - prints out contents of an PetscFList

451:    Collective over MPI_Comm

453:    Input Parameters:
454: +  list - the list of functions
455: -  viewer - currently ignored

457:    Level: developer

459: .seealso: PetscFListAddDynamic(), PetscFListPrintTypes(), PetscFList
460: @*/
461: PetscErrorCode  PetscFListView(PetscFList list,PetscViewer viewer)
462: {
464:   PetscTruth     iascii;

467:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
470: 
471:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
472:   if (!iascii) SETERRQ(PETSC_ERR_SUP,"Only ASCII viewer supported");

474:   while (list) {
475:     if (list->path) {
476:       PetscViewerASCIIPrintf(viewer," %s %s %s\n",list->path,list->name,list->rname);
477:     } else {
478:       PetscViewerASCIIPrintf(viewer," %s %s\n",list->name,list->rname);
479:     }
480:     list = list->next;
481:   }
482:   PetscViewerASCIIPrintf(viewer,"\n");
483:   return(0);
484: }

488: /*@
489:    PetscFListGet - Gets an array the contains the entries in PetscFList, this is used
490:          by help etc.

492:    Collective over MPI_Comm

494:    Input Parameter:
495: .  list   - list of types

497:    Output Parameter:
498: +  array - array of names
499: -  n - length of array

501:    Notes:
502:        This allocates the array so that must be freed. BUT the individual entries are
503:     not copied so should not be freed.

505:    Level: developer

507: .seealso: PetscFListAddDynamic(), PetscFList
508: @*/
509: PetscErrorCode  PetscFListGet(PetscFList list,char ***array,int *n)
510: {
512:   PetscInt       count = 0;
513:   PetscFList     klist = list;

516:   while (list) {
517:     list = list->next;
518:     count++;
519:   }
520:   PetscMalloc((count+1)*sizeof(char *),array);
521:   count = 0;
522:   while (klist) {
523:     (*array)[count] = klist->name;
524:     klist = klist->next;
525:     count++;
526:   }
527:   (*array)[count] = 0;
528:   *n = count+1;

530:   return(0);
531: }


536: /*@C
537:    PetscFListPrintTypes - Prints the methods available.

539:    Collective over MPI_Comm

541:    Input Parameters:
542: +  comm   - the communicator (usually MPI_COMM_WORLD)
543: .  fd     - file to print to, usually stdout
544: .  prefix - prefix to prepend to name (optional)
545: .  name   - option string (for example, "-ksp_type")
546: .  text - short description of the object (for example, "Krylov solvers")
547: .  man - name of manual page that discusses the object (for example, "KSPCreate")
548: -  list   - list of types

550:    Level: developer

552: .seealso: PetscFListAddDynamic(), PetscFList
553: @*/
554: PetscErrorCode  PetscFListPrintTypes(PetscFList list,MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[])
555: {
557:   PetscInt       count = 0;
558:   char           p[64];

561:   if (!fd) fd = PETSC_STDOUT;

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

567:   while (list) {
568:     PetscFPrintf(comm,fd," %s",list->name);
569:     list = list->next;
570:     count++;
571:     if (count == 8) {PetscFPrintf(comm,fd,"\n     ");}
572:   }
573:   PetscFPrintf(comm,fd," (%s)\n",man);
574:   return(0);
575: }

579: /*@
580:     PetscFListDuplicate - Creates a new list from a given object list.

582:     Input Parameters:
583: .   fl   - pointer to list

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

588:     Level: developer

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

592: @*/
593: PetscErrorCode  PetscFListDuplicate(PetscFList fl,PetscFList *nl)
594: {
596:   char           path[PETSC_MAX_PATH_LEN];

599:   while (fl) {
600:     /* this is silly, rebuild the complete pathname */
601:     if (fl->path) {
602:       PetscStrcpy(path,fl->path);
603:       PetscStrcat(path,":");
604:       PetscStrcat(path,fl->name);
605:     } else {
606:       PetscStrcpy(path,fl->name);
607:     }
608:     PetscFListAdd(nl,path,fl->rname,fl->routine);
609:     fl   = fl->next;
610:   }
611:   return(0);
612: }


617: /*
618:     PetscFListConcat - joins name of a libary, and the path where it is located
619:     into a single string.

621:     Input Parameters:
622: .   path   - path to the library name.
623: .   name   - name of the library

625:     Output Parameters:
626: .   fullname - the name that is the union of the path and the library name,
627:                delimited by a semicolon, i.e., path:name

629:     Notes:
630:     If the path is NULL, assumes that the name, specified also includes
631:     the path as path:name

633: */
634: PetscErrorCode  PetscFListConcat(const char path[],const char name[],char fullname[])
635: {
638:   if (path) {
639:     PetscStrcpy(fullname,path);
640:     PetscStrcat(fullname,":");
641:     PetscStrcat(fullname,name);
642:   } else {
643:     PetscStrcpy(fullname,name);
644:   }
645:   return(0);
646: }