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: /*
 31:     This is the default list used by PETSc with the PetscDLLibrary register routines
 32: */
 33: PetscDLLibrary DLLibrariesLoaded = 0;


 36: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)

 40: static PetscErrorCode  PetscLoadDynamicLibrary(const char *name,PetscTruth *found)
 41: {
 42:   char           libs[PETSC_MAX_PATH_LEN],dlib[PETSC_MAX_PATH_LEN];

 46:   PetscStrcpy(libs,"${PETSC_LIB_DIR}/libpetsc");
 47:   PetscStrcat(libs,name);
 48:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);
 49:   if (*found) {
 50:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,dlib);
 51:   } else {
 52:     PetscStrcpy(libs,"${PETSC_DIR}/${PETSC_ARCH}/lib/libpetsc");
 53:     PetscStrcat(libs,name);
 54:     PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);
 55:     if (*found) {
 56:       PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,dlib);
 57:     }
 58:   }
 59:   return(0);
 60: }

 62: #endif

 66: /*
 67:     PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the 
 68:     search path.
 69: */
 70: PetscErrorCode  PetscInitialize_DynamicLibraries(void)
 71: {
 72:   char           *libname[32];
 74:   PetscInt       nmax,i;
 75: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
 76:   PetscTruth     found;
 77: #endif

 80:   nmax = 32;
 81:   PetscOptionsGetStringArray(PETSC_NULL,"-dll_prepend",libname,&nmax,PETSC_NULL);
 82:   for (i=0; i<nmax; i++) {
 83:     PetscDLLibraryPrepend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
 84:     PetscFree(libname[i]);
 85:   }

 87: #if !defined(PETSC_USE_DYNAMIC_LIBRARIES)
 88:   /*
 89:       This just initializes the most basic PETSc stuff.

 91:     The classes, from PetscDraw to PetscTS, are initialized the first
 92:     time an XXCreate() is called.
 93:   */
 94:   PetscInitializePackage(PETSC_NULL);
 95: #else
 96:   PetscLoadDynamicLibrary("",&found);
 97:   if (!found) SETERRQ(PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
 98:   PetscLoadDynamicLibrary("vec",&found);
 99:   if (!found) SETERRQ(PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Vec dynamic library \n You cannot move the dynamic libraries!");
100:   PetscLoadDynamicLibrary("mat",&found);
101:   if (!found) SETERRQ(PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Mat dynamic library \n You cannot move the dynamic libraries!");
102:   PetscLoadDynamicLibrary("dm",&found);
103:   if (!found) SETERRQ(PETSC_ERR_FILE_OPEN,"Unable to locate PETSc DM dynamic library \n You cannot move the dynamic libraries!");
104:   PetscLoadDynamicLibrary("ksp",&found);
105:   if (!found) SETERRQ(PETSC_ERR_FILE_OPEN,"Unable to locate PETSc KSP dynamic library \n You cannot move the dynamic libraries!");
106:   PetscLoadDynamicLibrary("snes",&found);
107:   if (!found) SETERRQ(PETSC_ERR_FILE_OPEN,"Unable to locate PETSc SNES dynamic library \n You cannot move the dynamic libraries!");
108:   PetscLoadDynamicLibrary("ts",&found);
109:   if (!found) SETERRQ(PETSC_ERR_FILE_OPEN,"Unable to locate PETSc TS dynamic library \n You cannot move the dynamic libraries!");

111:   PetscLoadDynamicLibrary("mesh",&found);
112:   PetscLoadDynamicLibrary("contrib",&found);
113: #endif

115:   nmax = 32;
116:   PetscOptionsGetStringArray(PETSC_NULL,"-dll_append",libname,&nmax,PETSC_NULL);
117:   for (i=0; i<nmax; i++) {
118:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
119:     PetscDLLibraryCCAAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
120:     PetscFree(libname[i]);
121:   }

123:   return(0);
124: }

128: /*
129:      PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
130: */
131: PetscErrorCode PetscFinalize_DynamicLibraries(void)
132: {
134:   PetscTruth     flg;

137:   PetscOptionsHasName(PETSC_NULL,"-dll_view",&flg);
138:   if (flg) { PetscDLLibraryPrintPath(DLLibrariesLoaded); }
139:   PetscDLLibraryClose(DLLibrariesLoaded);
140:   DLLibrariesLoaded = 0;
141:   return(0);
142: }

144: /* ------------------------------------------------------------------------------*/
145: struct _n_PetscFList {
146:   void        (*routine)(void);   /* the routine */
147:   char        *path;              /* path of link library containing routine */
148:   char        *name;              /* string to identify routine */
149:   char        *rname;             /* routine name in dynamic library */
150:   PetscFList  next;               /* next pointer */
151:   PetscFList  next_list;          /* used to maintain list of all lists for freeing */
152: };

154: /*
155:      Keep a linked list of PetscFLists so that we can destroy all the left-over ones.
156: */
157: static PetscFList   dlallhead = 0;

161: /*@C
162:    PetscFListAddDynamic - Given a routine and a string id, saves that routine in the
163:    specified registry.

165:      Not Collective

167:    Input Parameters:
168: +  fl    - pointer registry
169: .  name  - string to identify routine
170: .  rname - routine name in dynamic library
171: -  fnc   - function pointer (optional if using dynamic libraries)

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

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

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

184:    Level: developer

186: .seealso: PetscFListDestroy(), SNESRegisterDynamic(), KSPRegisterDynamic(),
187:           PCRegisterDynamic(), TSRegisterDynamic(), PetscFList
188: @*/
189: PetscErrorCode  PetscFListAdd(PetscFList *fl,const char name[],const char rname[],void (*fnc)(void))
190: {
191:   PetscFList     entry,ne;
193:   char           *fpath,*fname;


197:   if (!*fl) {
198:     PetscNew(struct _n_PetscFList,&entry);
199:     PetscStrallocpy(name,&entry->name);
200:     PetscFListGetPathAndFunction(rname,&fpath,&fname);
201:     entry->path    = fpath;
202:     entry->rname   = fname;
203:     entry->routine = fnc;
204:     entry->next    = 0;
205:     *fl = entry;

207:     /* add this new list to list of all lists */
208:     if (!dlallhead) {
209:       dlallhead        = *fl;
210:       (*fl)->next_list = 0;
211:     } else {
212:       ne               = dlallhead;
213:       dlallhead        = *fl;
214:       (*fl)->next_list = ne;
215:     }
216:   } else {
217:     /* search list to see if it is already there */
218:     ne = *fl;
219:     while (ne) {
220:       PetscTruth founddup;

222:       PetscStrcmp(ne->name,name,&founddup);
223:       if (founddup) { /* found duplicate */
224:         PetscFListGetPathAndFunction(rname,&fpath,&fname);
225:         PetscStrfree(ne->path);
226:         PetscStrfree(ne->rname);
227:         ne->path    = fpath;
228:         ne->rname   = fname;
229:         ne->routine = fnc;
230:         return(0);
231:       }
232:       if (ne->next) ne = ne->next; else break;
233:     }
234:     /* create new entry and add to end of list */
235:     PetscNew(struct _n_PetscFList,&entry);
236:     PetscStrallocpy(name,&entry->name);
237:     PetscFListGetPathAndFunction(rname,&fpath,&fname);
238:     entry->path    = fpath;
239:     entry->rname   = fname;
240:     entry->routine = fnc;
241:     entry->next    = 0;
242:     ne->next       = entry;
243:   }

245:   return(0);
246: }

250: /*@
251:     PetscFListDestroy - Destroys a list of registered routines.

253:     Input Parameter:
254: .   fl  - pointer to list

256:     Level: developer

258: .seealso: PetscFListAddDynamic(), PetscFList
259: @*/
260: PetscErrorCode  PetscFListDestroy(PetscFList *fl)
261: {
262:   PetscFList     next,entry,tmp = dlallhead;

266:   CHKMEMQ;
267:   if (!*fl) return(0);

269:   if (!dlallhead) {
270:     return(0);
271:   }

273:   /*
274:        Remove this entry from the master DL list (if it is in it)
275:   */
276:   if (dlallhead == *fl) {
277:     if (dlallhead->next_list) {
278:       dlallhead = dlallhead->next_list;
279:     } else {
280:       dlallhead = 0;
281:     }
282:   } else {
283:     while (tmp->next_list != *fl) {
284:       tmp = tmp->next_list;
285:       if (!tmp->next_list) break;
286:     }
287:     if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
288:   }

290:   /* free this list */
291:   entry = *fl;
292:   while (entry) {
293:     next = entry->next;
294:     PetscStrfree(entry->path);
295:     PetscFree(entry->name);
296:     PetscFree(entry->rname);
297:     PetscFree(entry);
298:     entry = next;
299:   }
300:   *fl = 0;
301:   return(0);
302: }

304: /*
305:    Destroys all the function lists that anyone has every registered, such as KSPList, VecList, etc.
306: */
309: PetscErrorCode  PetscFListDestroyAll(void)
310: {
311:   PetscFList     tmp2,tmp1 = dlallhead;

315:   while (tmp1) {
316:     tmp2 = tmp1->next_list;
317:     PetscFListDestroy(&tmp1);
318:     tmp1 = tmp2;
319:   }
320:   dlallhead = 0;
321:   return(0);
322: }

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

329:     Input Parameters:
330: +   fl   - pointer to list
331: .   comm - processors looking for routine
332: -   name - name string

334:     Output Parameters:
335: .   r - the routine

337:     Level: developer

339: .seealso: PetscFListAddDynamic(), PetscFList
340: @*/
341: PetscErrorCode  PetscFListFind(PetscFList fl,MPI_Comm comm,const char name[],void (**r)(void))
342: {
343:   PetscFList     entry = fl;
345:   char           *function,*path;
346: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
347:   char           *newpath;
348: #endif
349:   PetscTruth   flg,f1,f2,f3;
350: 
352:   if (!name) SETERRQ(PETSC_ERR_ARG_NULL,"Trying to find routine with null name");

354:   *r = 0;
355:   PetscFListGetPathAndFunction(name,&path,&function);

357:   /*
358:         If path then append it to search libraries
359:   */
360: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
361:   if (path) {
362:     PetscDLLibraryAppend(comm,&DLLibrariesLoaded,path);
363:   }
364: #endif

366:   while (entry) {
367:     flg = PETSC_FALSE;
368:     if (path && entry->path) {
369:       PetscStrcmp(path,entry->path,&f1);
370:       PetscStrcmp(function,entry->rname,&f2);
371:       PetscStrcmp(function,entry->name,&f3);
372:       flg =  (PetscTruth) ((f1 && f2) || (f1 && f3));
373:     } else if (!path) {
374:       PetscStrcmp(function,entry->name,&f1);
375:       PetscStrcmp(function,entry->rname,&f2);
376:       flg =  (PetscTruth) (f1 || f2);
377:     } else {
378:       PetscStrcmp(function,entry->name,&flg);
379:       if (flg) {
380:         PetscFree(function);
381:         PetscStrallocpy(entry->rname,&function);
382:       } else {
383:         PetscStrcmp(function,entry->rname,&flg);
384:       }
385:     }

387:     if (flg) {

389:       if (entry->routine) {
390:         *r   = entry->routine;
391:         PetscStrfree(path);
392:         PetscFree(function);
393:         return(0);
394:       }
395: 
396:       if ((path && entry->path && f3) || (!path && f1)) { /* convert name of function (alias) to actual function name */
397:         PetscFree(function);
398:         PetscStrallocpy(entry->rname,&function);
399:       }

401:       /* it is not yet in memory so load from dynamic library */
402: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
403:       newpath = path;
404:       if (!path) newpath = entry->path;
405:       PetscDLLibrarySym(comm,&DLLibrariesLoaded,newpath,entry->rname,(void **)r);
406:       if (*r) {
407:         entry->routine = *r;
408:         PetscStrfree(path);
409:         PetscFree(function);
410:         return(0);
411:       } else {
412:         PetscErrorPrintf("Unable to find function. Search path:\n");
413:         PetscDLLibraryPrintPath(DLLibrariesLoaded);
414:         SETERRQ1(PETSC_ERR_PLIB,"Unable to find function:%s: either it is mis-spelled or dynamic library is not in path",entry->rname);
415:       }
416: #endif
417:     }
418:     entry = entry->next;
419:   }

421: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
422:   /* Function never registered; try for it anyway */
423:   PetscDLLibrarySym(comm,&DLLibrariesLoaded,path,function,(void **)r);
424:   PetscStrfree(path);
425:   if (*r) {
426:     PetscFListAdd(&fl,name,name,*r);
427:   }
428: #endif
429:   PetscFree(function);
430:   return(0);
431: }

435: /*@
436:    PetscFListView - prints out contents of an PetscFList

438:    Collective over MPI_Comm

440:    Input Parameters:
441: +  list - the list of functions
442: -  viewer - currently ignored

444:    Level: developer

446: .seealso: PetscFListAddDynamic(), PetscFListPrintTypes(), PetscFList
447: @*/
448: PetscErrorCode  PetscFListView(PetscFList list,PetscViewer viewer)
449: {
451:   PetscTruth     iascii;

454:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
457: 
458:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
459:   if (!iascii) SETERRQ(PETSC_ERR_SUP,"Only ASCII viewer supported");

461:   while (list) {
462:     if (list->path) {
463:       PetscViewerASCIIPrintf(viewer," %s %s %s\n",list->path,list->name,list->rname);
464:     } else {
465:       PetscViewerASCIIPrintf(viewer," %s %s\n",list->name,list->rname);
466:     }
467:     list = list->next;
468:   }
469:   PetscViewerASCIIPrintf(viewer,"\n");
470:   return(0);
471: }

475: /*@
476:    PetscFListGet - Gets an array the contains the entries in PetscFList, this is used
477:          by help etc.

479:    Collective over MPI_Comm

481:    Input Parameter:
482: .  list   - list of types

484:    Output Parameter:
485: +  array - array of names
486: -  n - length of array

488:    Notes:
489:        This allocates the array so that must be freed. BUT the individual entries are
490:     not copied so should not be freed.

492:    Level: developer

494: .seealso: PetscFListAddDynamic(), PetscFList
495: @*/
496: PetscErrorCode  PetscFListGet(PetscFList list,char ***array,int *n)
497: {
499:   PetscInt       count = 0;
500:   PetscFList     klist = list;

503:   while (list) {
504:     list = list->next;
505:     count++;
506:   }
507:   PetscMalloc((count+1)*sizeof(char *),array);
508:   count = 0;
509:   while (klist) {
510:     (*array)[count] = klist->name;
511:     klist = klist->next;
512:     count++;
513:   }
514:   (*array)[count] = 0;
515:   *n = count+1;

517:   return(0);
518: }


523: /*@C
524:    PetscFListPrintTypes - Prints the methods available.

526:    Collective over MPI_Comm

528:    Input Parameters:
529: +  comm   - the communicator (usually MPI_COMM_WORLD)
530: .  fd     - file to print to, usually stdout
531: .  prefix - prefix to prepend to name (optional)
532: .  name   - option string (for example, "-ksp_type")
533: .  text - short description of the object (for example, "Krylov solvers")
534: .  man - name of manual page that discusses the object (for example, "KSPCreate")
535: -  list   - list of types

537:    Level: developer

539: .seealso: PetscFListAddDynamic(), PetscFList
540: @*/
541: PetscErrorCode  PetscFListPrintTypes(PetscFList list,MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[])
542: {
544:   PetscInt       count = 0;
545:   char           p[64];

548:   if (!fd) fd = PETSC_STDOUT;

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

554:   while (list) {
555:     PetscFPrintf(comm,fd," %s",list->name);
556:     list = list->next;
557:     count++;
558:     if (count == 8) {PetscFPrintf(comm,fd,"\n     ");}
559:   }
560:   PetscFPrintf(comm,fd," (%s)\n",man);
561:   return(0);
562: }

566: /*@
567:     PetscFListDuplicate - Creates a new list from a given object list.

569:     Input Parameters:
570: .   fl   - pointer to list

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

575:     Level: developer

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

579: @*/
580: PetscErrorCode  PetscFListDuplicate(PetscFList fl,PetscFList *nl)
581: {
583:   char           path[PETSC_MAX_PATH_LEN];

586:   while (fl) {
587:     /* this is silly, rebuild the complete pathname */
588:     if (fl->path) {
589:       PetscStrcpy(path,fl->path);
590:       PetscStrcat(path,":");
591:       PetscStrcat(path,fl->name);
592:     } else {
593:       PetscStrcpy(path,fl->name);
594:     }
595:     PetscFListAdd(nl,path,fl->rname,fl->routine);
596:     fl   = fl->next;
597:   }
598:   return(0);
599: }


604: /*
605:     PetscFListConcat - joins name of a libary, and the path where it is located
606:     into a single string.

608:     Input Parameters:
609: .   path   - path to the library name.
610: .   name   - name of the library

612:     Output Parameters:
613: .   fullname - the name that is the union of the path and the library name,
614:                delimited by a semicolon, i.e., path:name

616:     Notes:
617:     If the path is NULL, assumes that the name, specified also includes
618:     the path as path:name

620: */
621: PetscErrorCode  PetscFListConcat(const char path[],const char name[],char fullname[])
622: {
625:   if (path) {
626:     PetscStrcpy(fullname,path);
627:     PetscStrcat(fullname,":");
628:     PetscStrcat(fullname,name);
629:   } else {
630:     PetscStrcpy(fullname,name);
631:   }
632:   return(0);
633: }