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 petscsys.h

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

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

 29: /*
 30:     This is the default list used by PETSc with the PetscDLLibrary register routines
 31: */
 32: PetscDLLibrary DLLibrariesLoaded = 0;


 35: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)

 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: }

 61: #endif

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

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

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

 90:     The classes, from PetscDraw to PetscTS, are initialized the first
 91:     time an XXCreate() is called.
 92:   */
 93:   PetscInitializePackage(PETSC_NULL);
 94: #else
 95:   PetscLoadDynamicLibrary("",&found);
 96:   if (!found) SETERRQ(PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
 97: #if !defined(PETSC_USE_SINGLE_LIBRARY)
 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!");
110: #endif

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

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

124:   return(0);
125: }

129: /*
130:      PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
131: */
132: PetscErrorCode PetscFinalize_DynamicLibraries(void)
133: {
135:   PetscTruth     flg = PETSC_FALSE;

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

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

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

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

166:      Not Collective

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

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

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

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

185:    Level: developer

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


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

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

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

246:   return(0);
247: }

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

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

257:     Level: developer

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

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

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

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

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

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

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

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

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

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

338:     Level: developer

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

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

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

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

388:     if (flg) {

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

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

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

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

439:    Collective over MPI_Comm

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

445:    Level: developer

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

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

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

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

480:    Collective over MPI_Comm

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

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

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

493:    Level: developer

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

504:   while (list) {
505:     list = list->next;
506:     count++;
507:   }
508:   PetscMalloc((count+1)*sizeof(char *),array);
509:   count = 0;
510:   while (klist) {
511:     (*array)[count] = klist->name;
512:     klist = klist->next;
513:     count++;
514:   }
515:   (*array)[count] = 0;
516:   *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
536: -  def - default (current) value

538:    Level: developer

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

549:   if (!fd) fd = PETSC_STDOUT;

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

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

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

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

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

576:     Level: developer

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

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

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


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

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

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

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

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