Actual source code: reg.c


  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/private/petscimpl.h>
  7: #include <petscviewer.h>

  9: /*
 10:     This is the default list used by PETSc with the PetscDLLibrary register routines
 11: */
 12: PetscDLLibrary PetscDLLibrariesLoaded = NULL;

 14: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES)

 16: static PetscErrorCode  PetscLoadDynamicLibrary(const char *name,PetscBool  *found)
 17: {
 18:   char           libs[PETSC_MAX_PATH_LEN],dlib[PETSC_MAX_PATH_LEN];

 22:   PetscStrncpy(libs,"${PETSC_LIB_DIR}/libpetsc",sizeof(libs));
 23:   PetscStrlcat(libs,name,sizeof(libs));
 24:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);
 25:   if (*found) {
 26:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,dlib);
 27:   } else {
 28:     PetscStrncpy(libs,"${PETSC_DIR}/${PETSC_ARCH}/lib/libpetsc",sizeof(libs));
 29:     PetscStrlcat(libs,name,sizeof(libs));
 30:     PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);
 31:     if (*found) {
 32:       PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,dlib);
 33:     }
 34:   }
 35:   return(0);
 36: }
 37: #endif

 39: #if defined(PETSC_USE_SINGLE_LIBRARY) && !(defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES))
 40: PETSC_EXTERN PetscErrorCode AOInitializePackage(void);
 41: PETSC_EXTERN PetscErrorCode PetscSFInitializePackage(void);
 42: #if !defined(PETSC_USE_COMPLEX)
 43: PETSC_EXTERN PetscErrorCode CharacteristicInitializePackage(void);
 44: #endif
 45: PETSC_EXTERN PetscErrorCode ISInitializePackage(void);
 46: PETSC_EXTERN PetscErrorCode VecInitializePackage(void);
 47: PETSC_EXTERN PetscErrorCode MatInitializePackage(void);
 48: PETSC_EXTERN PetscErrorCode DMInitializePackage(void);
 49: PETSC_EXTERN PetscErrorCode PCInitializePackage(void);
 50: PETSC_EXTERN PetscErrorCode KSPInitializePackage(void);
 51: PETSC_EXTERN PetscErrorCode SNESInitializePackage(void);
 52: PETSC_EXTERN PetscErrorCode TSInitializePackage(void);
 53: PETSC_EXTERN PetscErrorCode TaoInitializePackage(void);
 54: #endif
 55: #if defined(PETSC_HAVE_THREADSAFETY)
 56: static MPI_Comm PETSC_COMM_WORLD_INNER = 0,PETSC_COMM_SELF_INNER = 0;
 57: #endif

 59: /*
 60:     PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
 61:     search path.
 62: */
 63: PETSC_INTERN PetscErrorCode PetscInitialize_DynamicLibraries(void)
 64: {
 65:   char           *libname[32];
 67:   PetscInt       nmax,i;
 68:   PetscBool      preload = PETSC_FALSE;
 69: #if defined(PETSC_HAVE_ELEMENTAL)
 70:   PetscBool      PetscInitialized = PetscInitializeCalled;
 71: #endif

 74: #if defined(PETSC_HAVE_THREADSAFETY)
 75:   /* These must be all initialized here because it is not safe for individual threads to call these initialize routines */
 76:   preload = PETSC_TRUE;
 77: #endif

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

 86:   PetscOptionsGetBool(NULL,NULL,"-library_preload",&preload,NULL);
 87:   if (!preload) {
 88:     PetscSysInitializePackage();
 89:   } else {
 90: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES)
 91:     PetscBool found;
 92: #if defined(PETSC_USE_SINGLE_LIBRARY)
 93:     PetscLoadDynamicLibrary("",&found);
 94:     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
 95: #else
 96:     PetscLoadDynamicLibrary("sys",&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:     PetscLoadDynamicLibrary("vec",&found);
 99:     if (!found) SETERRQ(PETSC_COMM_SELF,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_COMM_SELF,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_COMM_SELF,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_COMM_SELF,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_COMM_SELF,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_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc TS dynamic library \n You cannot move the dynamic libraries!");
110:     PetscLoadDynamicLibrary("tao",&found);
111:     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate Tao dynamic library \n You cannot move the dynamic libraries!");
112: #endif
113: #else /* defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) */
114: #if defined(PETSC_USE_SINGLE_LIBRARY)
115:   AOInitializePackage();
116:   PetscSFInitializePackage();
117: #if !defined(PETSC_USE_COMPLEX)
118:   CharacteristicInitializePackage();
119: #endif
120:   ISInitializePackage();
121:   VecInitializePackage();
122:   MatInitializePackage();
123:   DMInitializePackage();
124:   PCInitializePackage();
125:   KSPInitializePackage();
126:   SNESInitializePackage();
127:   TSInitializePackage();
128:   TaoInitializePackage();
129: #else
130:   SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"Cannot use -library_preload with multiple static PETSc libraries");
131: #endif
132: #endif /* defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) */
133:   }

135: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) && defined(PETSC_HAVE_BAMG)
136:   {
137:     PetscBool found;
138:     PetscLoadDynamicLibrary("bamg",&found);
139:     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc BAMG dynamic library \n You cannot move the dynamic libraries!");
140:   }
141: #endif

143:   nmax = 32;
144:   PetscOptionsGetStringArray(NULL,NULL,"-dll_append",libname,&nmax,NULL);
145:   for (i=0; i<nmax; i++) {
146:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);
147:     PetscFree(libname[i]);
148:   }

150: #if defined(PETSC_HAVE_THREADSAFETY)
151:   PetscCommDuplicate(PETSC_COMM_SELF,&PETSC_COMM_SELF_INNER,NULL);
152:   PetscCommDuplicate(PETSC_COMM_WORLD,&PETSC_COMM_WORLD_INNER,NULL);
153: #endif
154: #if defined(PETSC_HAVE_ELEMENTAL)
155:   /* in Fortran, PetscInitializeCalled is set to PETSC_TRUE before PetscInitialize_DynamicLibraries() */
156:   /* in C, it is not the case, but the value is forced to PETSC_TRUE so that PetscRegisterFinalize() is called */
157:   PetscInitializeCalled = PETSC_TRUE;
158:   PetscElementalInitializePackage();
159:   PetscInitializeCalled = PetscInitialized;
160: #endif
161:   return(0);
162: }

164: /*
165:      PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
166: */
167: PETSC_INTERN PetscErrorCode PetscFinalize_DynamicLibraries(void)
168: {
170:   PetscBool      flg = PETSC_FALSE;

173:   PetscOptionsGetBool(NULL,NULL,"-dll_view",&flg,NULL);
174:   if (flg) { PetscDLLibraryPrintPath(PetscDLLibrariesLoaded); }
175:   PetscDLLibraryClose(PetscDLLibrariesLoaded);

177: #if defined(PETSC_HAVE_THREADSAFETY)
178:   PetscCommDestroy(&PETSC_COMM_SELF_INNER);
179:   PetscCommDestroy(&PETSC_COMM_WORLD_INNER);
180: #endif

182:   PetscDLLibrariesLoaded = NULL;
183:   return(0);
184: }



188: /* ------------------------------------------------------------------------------*/
189: struct _n_PetscFunctionList {
190:   void              (*routine)(void);    /* the routine */
191:   char              *name;               /* string to identify routine */
192:   PetscFunctionList next;                /* next pointer */
193:   PetscFunctionList next_list;           /* used to maintain list of all lists for freeing */
194: };

196: /*
197:      Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones.
198: */
199: static PetscFunctionList dlallhead = NULL;

201: /*MC
202:    PetscFunctionListAdd - Given a routine and a string id, saves that routine in the
203:    specified registry.

205:    Synopsis:
206: #include <petscsys.h>
207:    PetscErrorCode PetscFunctionListAdd(PetscFunctionList *flist,const char name[],void (*fptr)(void))

209:    Not Collective

211:    Input Parameters:
212: +  flist - pointer to function list object
213: .  name - string to identify routine
214: -  fptr - function pointer

216:    Notes:
217:    To remove a registered routine, pass in a NULL fptr.

219:    Users who wish to register new classes for use by a particular PETSc
220:    component (e.g., SNES) should generally call the registration routine
221:    for that particular component (e.g., SNESRegister()) instead of
222:    calling PetscFunctionListAdd() directly.

224:     Level: developer

226: .seealso: PetscFunctionListDestroy(), SNESRegister(), KSPRegister(),
227:           PCRegister(), TSRegister(), PetscFunctionList, PetscObjectComposeFunction()
228: M*/
229: PETSC_EXTERN PetscErrorCode PetscFunctionListAdd_Private(PetscFunctionList *fl,const char name[],void (*fnc)(void))
230: {
231:   PetscFunctionList entry,ne;
232:   PetscErrorCode    ierr;

235:   if (!*fl) {
236:     PetscNew(&entry);
237:     PetscStrallocpy(name,&entry->name);
238:     entry->routine = fnc;
239:     entry->next    = NULL;
240:     *fl            = entry;

242:     if (PetscDefined(USE_DEBUG)) {
243:       /* add this new list to list of all lists */
244:       if (!dlallhead) {
245:         dlallhead        = *fl;
246:         (*fl)->next_list = NULL;
247:       } else {
248:         ne               = dlallhead;
249:         dlallhead        = *fl;
250:         (*fl)->next_list = ne;
251:       }
252:     }

254:   } else {
255:     /* search list to see if it is already there */
256:     ne = *fl;
257:     while (ne) {
258:       PetscBool founddup;

260:       PetscStrcmp(ne->name,name,&founddup);
261:       if (founddup) { /* found duplicate */
262:         ne->routine = fnc;
263:         return(0);
264:       }
265:       if (ne->next) ne = ne->next;
266:       else break;
267:     }
268:     /* create new entry and add to end of list */
269:     PetscNew(&entry);
270:     PetscStrallocpy(name,&entry->name);
271:     entry->routine = fnc;
272:     entry->next    = NULL;
273:     ne->next       = entry;
274:   }
275:   return(0);
276: }

278: /*@
279:     PetscFunctionListDestroy - Destroys a list of registered routines.

281:     Input Parameter:
282: .   fl  - pointer to list

284:     Level: developer

286: .seealso: PetscFunctionListAdd(), PetscFunctionList
287: @*/
288: PetscErrorCode  PetscFunctionListDestroy(PetscFunctionList *fl)
289: {
290:   PetscFunctionList next,entry,tmp = dlallhead;
291:   PetscErrorCode    ierr;

294:   if (!*fl) return(0);

296:   /*
297:        Remove this entry from the main DL list (if it is in it)
298:   */
299:   if (dlallhead == *fl) {
300:     if (dlallhead->next_list) dlallhead = dlallhead->next_list;
301:     else dlallhead = NULL;
302:   } else if (tmp) {
303:     while (tmp->next_list != *fl) {
304:       tmp = tmp->next_list;
305:       if (!tmp->next_list) break;
306:     }
307:     if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
308:   }

310:   /* free this list */
311:   entry = *fl;
312:   while (entry) {
313:     next  = entry->next;
314:     PetscFree(entry->name);
315:     PetscFree(entry);
316:     entry = next;
317:   }
318:   *fl = NULL;
319:   return(0);
320: }

322: /*
323:    Print any PetscFunctionLists that have not be destroyed
324: */
325: PetscErrorCode  PetscFunctionListPrintAll(void)
326: {
327:   PetscFunctionList tmp = dlallhead;
328:   PetscErrorCode    ierr;

331:   if (tmp) {
332:     PetscPrintf(PETSC_COMM_WORLD,"The following PetscFunctionLists were not destroyed\n");
333:   }
334:   while (tmp) {
335:     PetscPrintf(PETSC_COMM_WORLD,"%s \n",tmp->name);
336:     tmp = tmp->next_list;
337:   }
338:   return(0);
339: }

341: /*MC
342:     PetscFunctionListFind - Find function registered under given name

344:     Synopsis:
345: #include <petscsys.h>
346:     PetscErrorCode PetscFunctionListFind(PetscFunctionList flist,const char name[],void (**fptr)(void))

348:     Input Parameters:
349: +   flist   - pointer to list
350: -   name - name registered for the function

352:     Output Parameters:
353: .   fptr - the function pointer if name was found, else NULL

355:     Level: developer

357: .seealso: PetscFunctionListAdd(), PetscFunctionList, PetscObjectQueryFunction()
358: M*/
359: PETSC_EXTERN PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl,const char name[],void (**r)(void))
360: {
361:   PetscFunctionList entry = fl;
362:   PetscErrorCode    ierr;
363:   PetscBool         flg;

366:   if (!name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Trying to find routine with null name");

368:   *r = NULL;
369:   while (entry) {
370:     PetscStrcmp(name,entry->name,&flg);
371:     if (flg) {
372:       *r   = entry->routine;
373:       return(0);
374:     }
375:     entry = entry->next;
376:   }
377:   return(0);
378: }

380: /*@
381:    PetscFunctionListView - prints out contents of an PetscFunctionList

383:    Collective over MPI_Comm

385:    Input Parameters:
386: +  list - the list of functions
387: -  viewer - currently ignored

389:    Level: developer

391: .seealso: PetscFunctionListAdd(), PetscFunctionListPrintTypes(), PetscFunctionList
392: @*/
393: PetscErrorCode  PetscFunctionListView(PetscFunctionList list,PetscViewer viewer)
394: {
396:   PetscBool      iascii;

399:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;

403:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
404:   if (!iascii) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ASCII viewer supported");

406:   while (list) {
407:     PetscViewerASCIIPrintf(viewer," %s\n",list->name);
408:     list = list->next;
409:   }
410:   PetscViewerASCIIPrintf(viewer,"\n");
411:   return(0);
412: }

414: /*@C
415:    PetscFunctionListGet - Gets an array the contains the entries in PetscFunctionList, this is used
416:          by help etc.

418:    Not Collective

420:    Input Parameter:
421: .  list   - list of types

423:    Output Parameter:
424: +  array - array of names
425: -  n - length of array

427:    Notes:
428:        This allocates the array so that must be freed. BUT the individual entries are
429:     not copied so should not be freed.

431:    Level: developer

433: .seealso: PetscFunctionListAdd(), PetscFunctionList
434: @*/
435: PetscErrorCode  PetscFunctionListGet(PetscFunctionList list,const char ***array,int *n)
436: {
437:   PetscErrorCode    ierr;
438:   PetscInt          count = 0;
439:   PetscFunctionList klist = list;

442:   while (list) {
443:     list = list->next;
444:     count++;
445:   }
446:   PetscMalloc1(count+1,(char***)array);
447:   count = 0;
448:   while (klist) {
449:     (*array)[count] = klist->name;
450:     klist           = klist->next;
451:     count++;
452:   }
453:   (*array)[count] = NULL;
454:   *n              = count+1;
455:   return(0);
456: }


459: /*@C
460:    PetscFunctionListPrintTypes - Prints the methods available.

462:    Collective over MPI_Comm

464:    Input Parameters:
465: +  comm   - the communicator (usually MPI_COMM_WORLD)
466: .  fd     - file to print to, usually stdout
467: .  prefix - prefix to prepend to name (optional)
468: .  name   - option string (for example, "-ksp_type")
469: .  text - short description of the object (for example, "Krylov solvers")
470: .  man - name of manual page that discusses the object (for example, "KSPCreate")
471: .  list   - list of types
472: .  def - default (current) value
473: -  newv - new value

475:    Level: developer

477: .seealso: PetscFunctionListAdd(), PetscFunctionList
478: @*/
479: PetscErrorCode  PetscFunctionListPrintTypes(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[],PetscFunctionList list,const char def[],const char newv[])
480: {
482:   char           p[64];

485:   if (!fd) fd = PETSC_STDOUT;

487:   PetscStrncpy(p,"-",sizeof(p));
488:   if (prefix) {PetscStrlcat(p,prefix,sizeof(p));}
489:   PetscFPrintf(comm,fd,"  %s%s <now %s : formerly %s>: %s (one of)",p,name+1,newv,def,text);

491:   while (list) {
492:     PetscFPrintf(comm,fd," %s",list->name);
493:     list = list->next;
494:   }
495:   PetscFPrintf(comm,fd," (%s)\n",man);
496:   return(0);
497: }

499: /*@
500:     PetscFunctionListDuplicate - Creates a new list from a given object list.

502:     Input Parameters:
503: .   fl   - pointer to list

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

508:     Level: developer

510: .seealso: PetscFunctionList, PetscFunctionListAdd(), PetscFlistDestroy()

512: @*/
513: PetscErrorCode  PetscFunctionListDuplicate(PetscFunctionList fl,PetscFunctionList *nl)
514: {

518:   while (fl) {
519:     PetscFunctionListAdd(nl,fl->name,fl->routine);
520:     fl   = fl->next;
521:   }
522:   return(0);
523: }