Actual source code: reg.c

petsc-3.3-p7 2013-05-11
  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>           /*I "petscsys.h" I*/

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

 16:   PetscStrncpy(work,name,sizeof work);
 17:   work[sizeof work - 1] = 0;
 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 PetscDLLibrariesLoaded = 0;

 35: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)

 39: static PetscErrorCode  PetscLoadDynamicLibrary(const char *name,PetscBool  *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,&PetscDLLibrariesLoaded,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,&PetscDLLibrariesLoaded,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:   PetscBool      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,&PetscDLLibrariesLoaded,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:   PetscSysInitializePackage(PETSC_NULL);
 94: #else
 95: #if defined(PETSC_USE_SINGLE_LIBRARY)
 96:   PetscLoadDynamicLibrary("",&found);
 97:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
 98: #else 
 99:   PetscLoadDynamicLibrary("sys",&found);
100:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
101:   PetscLoadDynamicLibrary("vec",&found);
102:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Vec dynamic library \n You cannot move the dynamic libraries!");
103:   PetscLoadDynamicLibrary("mat",&found);
104:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Mat dynamic library \n You cannot move the dynamic libraries!");
105:   PetscLoadDynamicLibrary("dm",&found);
106:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc DM dynamic library \n You cannot move the dynamic libraries!");
107:   PetscLoadDynamicLibrary("characteristic",&found);
108:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Characteristic dynamic library \n You cannot move the dynamic libraries!");
109:   PetscLoadDynamicLibrary("ksp",&found);
110:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc KSP dynamic library \n You cannot move the dynamic libraries!");
111:   PetscLoadDynamicLibrary("snes",&found);
112:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc SNES dynamic library \n You cannot move the dynamic libraries!");
113:   PetscLoadDynamicLibrary("ts",&found);
114:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc TS dynamic library \n You cannot move the dynamic libraries!");
115: #endif

117:   PetscLoadDynamicLibrary("mesh",&found);
118:   PetscLoadDynamicLibrary("contrib",&found);
119: #endif

121:   nmax = 32;
122:   PetscOptionsGetStringArray(PETSC_NULL,"-dll_append",libname,&nmax,PETSC_NULL);
123:   for (i=0; i<nmax; i++) {
124:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);
125:     PetscFree(libname[i]);
126:   }

128:   return(0);
129: }

133: /*
134:      PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
135: */
136: PetscErrorCode PetscFinalize_DynamicLibraries(void)
137: {
139:   PetscBool      flg = PETSC_FALSE;

142:   PetscOptionsGetBool(PETSC_NULL,"-dll_view",&flg,PETSC_NULL);
143:   if (flg) { PetscDLLibraryPrintPath(PetscDLLibrariesLoaded); }
144:   PetscDLLibraryClose(PetscDLLibrariesLoaded);
145:   PetscDLLibrariesLoaded = 0;
146:   return(0);
147: }



151: /* ------------------------------------------------------------------------------*/
152: struct _n_PetscFList {
153:   void        (*routine)(void);   /* the routine */
154:   char        *path;              /* path of link library containing routine */
155:   char        *name;              /* string to identify routine */
156:   char        *rname;             /* routine name in dynamic library */
157:   PetscFList  next;               /* next pointer */
158:   PetscFList  next_list;          /* used to maintain list of all lists for freeing */
159: };

161: /*
162:      Keep a linked list of PetscFLists so that we can destroy all the left-over ones.
163: */
164: static PetscFList   dlallhead = 0;

168: /*@C
169:    PetscFListAdd - Given a routine and a string id, saves that routine in the
170:    specified registry.

172:      Not Collective

174:    Input Parameters:
175: +  fl    - pointer registry
176: .  name  - string to identify routine
177: .  rname - routine name in dynamic library
178: -  fnc   - function pointer (optional if using dynamic libraries)

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

183:    Users who wish to register new classes for use by a particular PETSc
184:    component (e.g., SNES) should generally call the registration routine
185:    for that particular component (e.g., SNESRegisterDynamic()) instead of
186:    calling PetscFListAdd() directly.

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

191:    Level: developer

193: .seealso: PetscFListDestroy(), SNESRegisterDynamic(), KSPRegisterDynamic(),
194:           PCRegisterDynamic(), TSRegisterDynamic(), PetscFList
195: @*/
196: PetscErrorCode  PetscFListAdd(PetscFList *fl,const char name[],const char rname[],void (*fnc)(void))
197: {
198:   PetscFList     entry,ne;
200:   char           *fpath,*fname;

203:   if (!*fl) {
204:     PetscNew(struct _n_PetscFList,&entry);
205:     PetscStrallocpy(name,&entry->name);
206:     PetscFListGetPathAndFunction(rname,&fpath,&fname);
207:     entry->path    = fpath;
208:     entry->rname   = fname;
209:     entry->routine = fnc;
210:     entry->next    = 0;
211:     *fl = entry;

213:     /* add this new list to list of all lists */
214:     if (!dlallhead) {
215:       dlallhead        = *fl;
216:       (*fl)->next_list = 0;
217:     } else {
218:       ne               = dlallhead;
219:       dlallhead        = *fl;
220:       (*fl)->next_list = ne;
221:     }
222:   } else {
223:     /* search list to see if it is already there */
224:     ne = *fl;
225:     while (ne) {
226:       PetscBool  founddup;

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

255: /*@
256:     PetscFListDestroy - Destroys a list of registered routines.

258:     Input Parameter:
259: .   fl  - pointer to list

261:     Level: developer

263: .seealso: PetscFListAddDynamic(), PetscFList
264: @*/
265: PetscErrorCode  PetscFListDestroy(PetscFList *fl)
266: {
267:   PetscFList     next,entry,tmp = dlallhead;

271:   if (!*fl) return(0);
272:   if (!dlallhead) return(0);

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:     PetscFree(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
334: -   searchlibraries - if not found in the list then search the dynamic libraries and executable for the symbol

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

339:     Level: developer

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

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

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

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

389:     if (flg) {
390:       if (entry->routine) {
391:         *r   = entry->routine;
392:         PetscFree(path);
393:         PetscFree(function);
394:         return(0);
395:       }
396:       if (!(entry->rname && entry->rname[0])) { /* The entry has been cleared */
397:         PetscFree(function);
398:         return(0);
399:       }
400:       if ((path && entry->path && f3) || (!path && f1)) { /* convert name of function (alias) to actual function name */
401:         PetscFree(function);
402:         PetscStrallocpy(entry->rname,&function);
403:       }

405:       /* it is not yet in memory so load from dynamic library */
406: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
407:       newpath = path;
408:       if (!path) newpath = entry->path;
409:       PetscDLLibrarySym(comm,&PetscDLLibrariesLoaded,newpath,entry->rname,(void **)r);
410:       if (*r) {
411:         entry->routine = *r;
412:         PetscFree(path);
413:         PetscFree(function);
414:         return(0);
415:       }
416: #endif
417:     }
418:     entry = entry->next;
419:   }

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

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

440:    Collective over MPI_Comm

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

446:    Level: developer

448: .seealso: PetscFListAddDynamic(), PetscFListPrintTypes(), PetscFList
449: @*/
450: PetscErrorCode  PetscFListView(PetscFList list,PetscViewer viewer)
451: {
453:   PetscBool      iascii;

456:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
459: 
460:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
461:   if (!iascii) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ASCII viewer supported");

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

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

481:    Collective over MPI_Comm

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

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

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

494:    Level: developer

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

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


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

527:    Collective over MPI_Comm

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

539:    Level: developer

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

550:   if (!fd) fd = PETSC_STDOUT;

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

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

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

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

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

577:     Level: developer

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

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

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


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

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

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

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

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



639: /* ------------------------------------------------------------------------------*/
640: struct _n_PetscOpFList {
641:   char                 *op;                /* op name */
642:   PetscInt             numArgs;            /* number of arguments to the operation */
643:   char                 **argTypes;         /* list of argument types */
644:   PetscVoidFunction    routine;            /* the routine */
645:   char                 *url;               /* url naming the link library and the routine */
646:   char                 *path;              /* path of link library containing routine */
647:   char                 *name;              /* routine name in dynamic library */
648:   PetscOpFList         next;              /* next pointer */
649:   PetscOpFList         next_list;         /* used to maintain list of all lists for freeing */
650: };

652: /*
653:      Keep a linked list of PetscOfFLists so that we can destroy all the left-over ones.
654: */
655: static PetscOpFList   opallhead = 0;

659: /*@C
660:    PetscOpFListAdd - Given a routine and a string id, saves that routine in the
661:    specified registry.

663:    Formally collective on comm.

665:    Input Parameters:
666: +  comm     - processors adding the op
667: .  fl       - list of known ops
668: .  url      - routine locator  (optional, if not using dynamic libraries and a nonempty fnc)
669: .  fnc      - function pointer (optional, if using dynamic libraries and a nonempty url)
670: .  op       - operation name
671: .  numArgs  - number of op arguments
672: -  argTypes - list of argument type names (const char*)

674:    Notes:
675:    To remove a registered routine, pass in a PETSC_NULL url and fnc().

677:    url can be of the form  [/path/libname[.so.1.0]:]functionname[()]  where items in [] denote optional 

679:    ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, or ${any environment variable}
680:    occuring in url will be replaced with appropriate values.

682:    Level: developer

684: .seealso: PetscOpFListDestroy(),PetscOpFList,  PetscFListAdd(), PetscFList
685: @*/
686: PetscErrorCode  PetscOpFListAdd(MPI_Comm comm, PetscOpFList *fl,const char url[],PetscVoidFunction fnc,const char op[], PetscInt numArgs, char* argTypes[])
687: {
688:   PetscOpFList   entry,e,ne;
690:   char           *fpath,*fname;
691:   PetscInt       i;

694:   if (!*fl) {
695:     PetscNew(struct _n_PetscOpFList,&entry);
696:     PetscStrallocpy(op,&entry->op);
697:     PetscStrallocpy(url,&(entry->url));
698:     PetscFListGetPathAndFunction(url,&fpath,&fname);
699:     entry->path    = fpath;
700:     entry->name    = fname;
701:     entry->routine = fnc;
702:     entry->numArgs = numArgs;
703:     if(numArgs) {
704:       PetscMalloc(sizeof(char*)*numArgs, &(entry->argTypes));
705:       for(i = 0; i < numArgs; ++i) {
706:         PetscStrallocpy(argTypes[i], &(entry->argTypes[i]));
707:       }
708:     }
709:     entry->next    = 0;
710:     *fl = entry;

712:     /* add this new list to list of all lists */
713:     if (!opallhead) {
714:       opallhead       = *fl;
715:       (*fl)->next_list = 0;
716:     } else {
717:       ne               = opallhead;
718:       opallhead        = *fl;
719:       (*fl)->next_list = ne;
720:     }
721:   } else {
722:     /* search list to see if it is already there */
723:     e  = PETSC_NULL;
724:     ne = *fl;
725:     while (ne) {
726:       PetscBool  match;
727:       PetscStrcmp(ne->op,op,&match);
728:       if(!match) goto next;
729:       if(numArgs == ne->numArgs)
730:         match = PETSC_TRUE;
731:       else
732:         match = PETSC_FALSE;
733:       if(!match) goto next;
734:       if(numArgs) {
735:         for(i = 0; i < numArgs; ++i) {
736:           PetscStrcmp(argTypes[i], ne->argTypes[i], &match);
737:           if(!match) goto next;
738:         }
739:       }
740:       if(!url && !fnc) {
741:         /* remove this record */
742:         if(e) e->next = ne->next;
743:         PetscFree(ne->op);
744:         PetscFree(ne->url);
745:         PetscFree(ne->path);
746:         PetscFree(ne->name);
747:         if(numArgs) {
748:           for(i = 0; i < numArgs; ++i) {
749:             PetscFree(ne->argTypes[i]);
750:           }
751:           PetscFree(ne->argTypes);
752:         }
753:         PetscFree(ne);
754:       }
755:       else {
756:         /* Replace url, fpath, fname and fnc. */
757:         PetscStrallocpy(url, &(ne->url));
758:         PetscFListGetPathAndFunction(url,&fpath,&fname);
759:         PetscFree(ne->path);
760:         PetscFree(ne->name);
761:         ne->path    = fpath;
762:         ne->name    = fname;
763:         ne->routine = fnc;
764:       }
765:       return(0);
766:       next: {e = ne; ne = ne->next;}
767:     }
768:     /* create new entry and add to end of list */
769:     PetscNew(struct _n_PetscOpFList,&entry);
770:     PetscStrallocpy(op,&entry->op);
771:     entry->numArgs = numArgs;
772:     if(numArgs) {
773:       PetscMalloc(sizeof(char*)*numArgs, &(entry->argTypes));
774:       for(i = 0; i < numArgs; ++i) {
775:         PetscStrallocpy(argTypes[i], &(entry->argTypes[i]));
776:       }
777:     }
778:     PetscStrallocpy(url, &(entry->url));
779:     PetscFListGetPathAndFunction(url,&fpath,&fname);
780:     entry->path    = fpath;
781:     entry->name    = fname;
782:     entry->routine = fnc;
783:     entry->next    = 0;
784:     ne->next       = entry;
785:   }
786:   return(0);
787: }

791: /*@C
792:     PetscOpFListDestroy - Destroys a list of registered op routines.

794:     Input Parameter:
795: .   fl  - pointer to list

797:     Level: developer

799: .seealso: PetscOpFListAdd(), PetscOpFList
800: @*/
801: PetscErrorCode  PetscOpFListDestroy(PetscOpFList *fl)
802: {
803:   PetscOpFList     next,entry,tmp;
804:   PetscErrorCode   ierr;
805:   PetscInt         i;

808:   if (!*fl) return(0);
809:   if (!opallhead) return(0);

811:   /*
812:        Remove this entry from the master Op list (if it is in it)
813:   */
814:   if (opallhead == *fl) {
815:     if (opallhead->next_list) {
816:       opallhead = opallhead->next_list;
817:     } else {
818:       opallhead = 0;
819:     }
820:   } else {
821:     tmp = opallhead;
822:     while (tmp->next_list != *fl) {
823:       tmp = tmp->next_list;
824:       if (!tmp->next_list) break;
825:     }
826:     if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
827:   }

829:   /* free this list */
830:   entry = *fl;
831:   while (entry) {
832:     next = entry->next;
833:     PetscFree(entry->op);
834:     for(i = 0; i < entry->numArgs; ++i) {
835:       PetscFree(entry->argTypes[i]);
836:     }
837:     PetscFree(entry->argTypes);
838:     PetscFree(entry->url);
839:     PetscFree(entry->path);
840:     PetscFree(entry->name);
841:     PetscFree(entry);
842:     entry = next;
843:   }
844:   *fl = 0;
845:   return(0);
846: }

848: /*
849:    Destroys all the function lists that anyone has every registered, such as MatOpList, etc.
850: */
853: PetscErrorCode  PetscOpFListDestroyAll(void)
854: {
855:   PetscOpFList     tmp2,tmp1 = opallhead;

859:   while (tmp1) {
860:     tmp2 = tmp1->next_list;
861:     PetscOpFListDestroy(&tmp1);
862:     tmp1 = tmp2;
863:   }
864:   opallhead = 0;
865:   return(0);
866: }

870: /*@C
871:     PetscOpFListFind - Given a name, finds the matching op routine.
872:     Formally collective on comm.

874:     Input Parameters:
875: +   comm     - processes looking for the op
876: .   fl       - pointer to list of known ops
877: .   op       - operation name
878: .   numArgs  - number of op arguments
879: -   argTypes - list of argument type names 


882:     Output Parameters:
883: .   r       - routine implementing op with the given arg types

885:     Level: developer

887: .seealso: PetscOpFListAdd(), PetscOpFList
888: @*/
889: PetscErrorCode  PetscOpFListFind(MPI_Comm comm, PetscOpFList fl,PetscVoidFunction *r, const char* op, PetscInt numArgs, char* argTypes[])
890: {
891:   PetscOpFList   entry;
893:   PetscBool      match;
894:   PetscInt       i;
895: 
898:   if (!op) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Attempting to find operation with null name");
899:   *r = PETSC_NULL;
900:   match = PETSC_FALSE;
901:   entry = fl;
902:   while (entry) {
903:     PetscStrcmp(entry->op,op,&match);
904:     if(!match) goto next;
905:     if(numArgs == entry->numArgs)
906:       match = PETSC_TRUE;
907:     else
908:       match = PETSC_FALSE;
909:     if(!match) goto next;
910:     if(numArgs) {
911:       for(i = 0; i < numArgs; ++i) {
912:         PetscStrcmp(argTypes[i], entry->argTypes[i], &match);
913:         if(!match) goto next;
914:       }
915:     }
916:     break;
917:     next: entry = entry->next;
918:   }
919:   if (match) {
920:     if (entry->routine) {
921:       *r   = entry->routine;
922:     }
923: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
924:     else {
925:       /* it is not yet in memory so load from dynamic library */
926:       PetscDLLibrarySym(comm,&PetscDLLibrariesLoaded,entry->path,entry->name,(void **)r);
927:       if (*r) {
928:         entry->routine = *r;
929:       }
930:     }
931: #endif
932:   }

934:   return(0);
935: }

939: /*@C
940:    PetscOpFListView - prints out contents of a PetscOpFList

942:    Collective on viewer

944:    Input Parameters:
945: +  list   - the list of functions
946: -  viewer - ASCII viewer   Level: developer

948: .seealso: PetscOpFListAdd(), PetscOpFList
949: @*/
950: PetscErrorCode  PetscOpFListView(PetscOpFList list,PetscViewer viewer)
951: {
953:   PetscBool      iascii;
954:   PetscInt       i;

957:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
960: 
961:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
962:   if (!iascii) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ASCII viewer supported");

964:   while (list) {
965:     if (list->url) {
966:       PetscViewerASCIIPrintf(viewer," %s: ",list->url);
967:     }
968:     PetscViewerASCIIPrintf(viewer, "%s(", list->op);
969:     for(i = 0; i < list->numArgs;++i) {
970:       if(i > 0) {
971:         PetscViewerASCIIPrintf(viewer, ", ");
972:       }
973:       PetscViewerASCIIPrintf(viewer, "%s", list->argTypes[i]);
974:     }
975:     PetscViewerASCIIPrintf(viewer, ")\n");
976:     list = list->next;
977:   }
978:   return(0);
979: }