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];

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

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

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

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

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

 82:   PetscOptionsGetBool(NULL,NULL,"-library_preload",&preload,NULL);
 83:   if (!preload) {
 84:     PetscSysInitializePackage();
 85:   } else {
 86: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES)
 87:     PetscBool found;
 88: #if defined(PETSC_USE_SINGLE_LIBRARY)
 89:     PetscLoadDynamicLibrary("",&found);
 91: #else
 92:     PetscLoadDynamicLibrary("sys",&found);
 94:     PetscLoadDynamicLibrary("vec",&found);
 96:     PetscLoadDynamicLibrary("mat",&found);
 98:     PetscLoadDynamicLibrary("dm",&found);
100:     PetscLoadDynamicLibrary("ksp",&found);
102:     PetscLoadDynamicLibrary("snes",&found);
104:     PetscLoadDynamicLibrary("ts",&found);
106:     PetscLoadDynamicLibrary("tao",&found);
108: #endif
109: #else /* defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) */
110: #if defined(PETSC_USE_SINGLE_LIBRARY)
111:   AOInitializePackage();
112:   PetscSFInitializePackage();
113: #if !defined(PETSC_USE_COMPLEX)
114:   CharacteristicInitializePackage();
115: #endif
116:   ISInitializePackage();
117:   VecInitializePackage();
118:   MatInitializePackage();
119:   DMInitializePackage();
120:   PCInitializePackage();
121:   KSPInitializePackage();
122:   SNESInitializePackage();
123:   TSInitializePackage();
124:   TaoInitializePackage();
125: #else
126:   SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"Cannot use -library_preload with multiple static PETSc libraries");
127: #endif
128: #endif /* defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) */
129:   }

131: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) && defined(PETSC_HAVE_BAMG)
132:   {
133:     PetscBool found;
134:     PetscLoadDynamicLibrary("bamg",&found);
136:   }
137: #endif

139:   nmax = 32;
140:   PetscOptionsGetStringArray(NULL,NULL,"-dll_append",libname,&nmax,NULL);
141:   for (i=0; i<nmax; i++) {
142:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);
143:     PetscFree(libname[i]);
144:   }

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

160: /*
161:      PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
162: */
163: PETSC_INTERN PetscErrorCode PetscFinalize_DynamicLibraries(void)
164: {
165:   PetscBool      flg = PETSC_FALSE;

167:   PetscOptionsGetBool(NULL,NULL,"-dll_view",&flg,NULL);
168:   if (flg) PetscDLLibraryPrintPath(PetscDLLibrariesLoaded);
169:   PetscDLLibraryClose(PetscDLLibrariesLoaded);

171: #if defined(PETSC_HAVE_THREADSAFETY)
172:   PetscCommDestroy(&PETSC_COMM_SELF_INNER);
173:   PetscCommDestroy(&PETSC_COMM_WORLD_INNER);
174: #endif

176:   PetscDLLibrariesLoaded = NULL;
177:   return 0;
178: }

180: /* ------------------------------------------------------------------------------*/
181: struct _n_PetscFunctionList {
182:   void              (*routine)(void);    /* the routine */
183:   char              *name;               /* string to identify routine */
184:   PetscFunctionList next;                /* next pointer */
185:   PetscFunctionList next_list;           /* used to maintain list of all lists for freeing */
186: };

188: /*
189:      Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones.
190: */
191: static PetscFunctionList dlallhead = NULL;

193: /*MC
194:    PetscFunctionListAdd - Given a routine and a string id, saves that routine in the
195:    specified registry.

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

201:    Not Collective

203:    Input Parameters:
204: +  flist - pointer to function list object
205: .  name - string to identify routine
206: -  fptr - function pointer

208:    Notes:
209:    To remove a registered routine, pass in a NULL fptr.

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

216:     Level: developer

218: .seealso: PetscFunctionListDestroy(), SNESRegister(), KSPRegister(),
219:           PCRegister(), TSRegister(), PetscFunctionList, PetscObjectComposeFunction()
220: M*/
221: PETSC_EXTERN PetscErrorCode PetscFunctionListAdd_Private(PetscFunctionList *fl,const char name[],void (*fnc)(void))
222: {
223:   PetscFunctionList entry,ne;

225:   if (!*fl) {
226:     PetscNew(&entry);
227:     PetscStrallocpy(name,&entry->name);
228:     entry->routine = fnc;
229:     entry->next    = NULL;
230:     *fl            = entry;

232:     if (PetscDefined(USE_DEBUG)) {
233:       /* add this new list to list of all lists */
234:       if (!dlallhead) {
235:         dlallhead        = *fl;
236:         (*fl)->next_list = NULL;
237:       } else {
238:         ne               = dlallhead;
239:         dlallhead        = *fl;
240:         (*fl)->next_list = ne;
241:       }
242:     }

244:   } else {
245:     /* search list to see if it is already there */
246:     ne = *fl;
247:     while (ne) {
248:       PetscBool founddup;

250:       PetscStrcmp(ne->name,name,&founddup);
251:       if (founddup) { /* found duplicate */
252:         ne->routine = fnc;
253:         return 0;
254:       }
255:       if (ne->next) ne = ne->next;
256:       else break;
257:     }
258:     /* create new entry and add to end of list */
259:     PetscNew(&entry);
260:     PetscStrallocpy(name,&entry->name);
261:     entry->routine = fnc;
262:     entry->next    = NULL;
263:     ne->next       = entry;
264:   }
265:   return 0;
266: }

268: /*@
269:     PetscFunctionListDestroy - Destroys a list of registered routines.

271:     Input Parameter:
272: .   fl  - pointer to list

274:     Level: developer

276: .seealso: PetscFunctionListAdd(), PetscFunctionList
277: @*/
278: PetscErrorCode  PetscFunctionListDestroy(PetscFunctionList *fl)
279: {
280:   PetscFunctionList next,entry,tmp = dlallhead;

282:   if (!*fl) return 0;

284:   /*
285:        Remove this entry from the main DL list (if it is in it)
286:   */
287:   if (dlallhead == *fl) {
288:     if (dlallhead->next_list) dlallhead = dlallhead->next_list;
289:     else dlallhead = NULL;
290:   } else if (tmp) {
291:     while (tmp->next_list != *fl) {
292:       tmp = tmp->next_list;
293:       if (!tmp->next_list) break;
294:     }
295:     if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
296:   }

298:   /* free this list */
299:   entry = *fl;
300:   while (entry) {
301:     next  = entry->next;
302:     PetscFree(entry->name);
303:     PetscFree(entry);
304:     entry = next;
305:   }
306:   *fl = NULL;
307:   return 0;
308: }

310: /*
311:    Print any PetscFunctionLists that have not be destroyed
312: */
313: PetscErrorCode  PetscFunctionListPrintAll(void)
314: {
315:   PetscFunctionList tmp = dlallhead;

317:   if (tmp) {
318:     PetscPrintf(PETSC_COMM_WORLD,"The following PetscFunctionLists were not destroyed\n");
319:   }
320:   while (tmp) {
321:     PetscPrintf(PETSC_COMM_WORLD,"%s \n",tmp->name);
322:     tmp = tmp->next_list;
323:   }
324:   return 0;
325: }

327: /*MC
328:     PetscFunctionListFind - Find function registered under given name

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

334:     Input Parameters:
335: +   flist   - pointer to list
336: -   name - name registered for the function

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

341:     Level: developer

343: .seealso: PetscFunctionListAdd(), PetscFunctionList, PetscObjectQueryFunction()
344: M*/
345: PETSC_EXTERN PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl,const char name[],void (**r)(void))
346: {
347:   PetscFunctionList entry = fl;
348:   PetscBool         flg;


352:   *r = NULL;
353:   while (entry) {
354:     PetscStrcmp(name,entry->name,&flg);
355:     if (flg) {
356:       *r   = entry->routine;
357:       return 0;
358:     }
359:     entry = entry->next;
360:   }
361:   return 0;
362: }

364: /*@
365:    PetscFunctionListView - prints out contents of an PetscFunctionList

367:    Collective over MPI_Comm

369:    Input Parameters:
370: +  list - the list of functions
371: -  viewer - currently ignored

373:    Level: developer

375: .seealso: PetscFunctionListAdd(), PetscFunctionListPrintTypes(), PetscFunctionList
376: @*/
377: PetscErrorCode  PetscFunctionListView(PetscFunctionList list,PetscViewer viewer)
378: {
379:   PetscBool      iascii;

381:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;

385:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);

388:   while (list) {
389:     PetscViewerASCIIPrintf(viewer," %s\n",list->name);
390:     list = list->next;
391:   }
392:   PetscViewerASCIIPrintf(viewer,"\n");
393:   return 0;
394: }

396: /*@C
397:    PetscFunctionListGet - Gets an array the contains the entries in PetscFunctionList, this is used
398:          by help etc.

400:    Not Collective

402:    Input Parameter:
403: .  list   - list of types

405:    Output Parameters:
406: +  array - array of names
407: -  n - length of array

409:    Notes:
410:        This allocates the array so that must be freed. BUT the individual entries are
411:     not copied so should not be freed.

413:    Level: developer

415: .seealso: PetscFunctionListAdd(), PetscFunctionList
416: @*/
417: PetscErrorCode  PetscFunctionListGet(PetscFunctionList list,const char ***array,int *n)
418: {
419:   PetscInt          count = 0;
420:   PetscFunctionList klist = list;

422:   while (list) {
423:     list = list->next;
424:     count++;
425:   }
426:   PetscMalloc1(count+1,(char***)array);
427:   count = 0;
428:   while (klist) {
429:     (*array)[count] = klist->name;
430:     klist           = klist->next;
431:     count++;
432:   }
433:   (*array)[count] = NULL;
434:   *n              = count+1;
435:   return 0;
436: }

438: /*@C
439:    PetscFunctionListPrintTypes - Prints the methods available.

441:    Collective over MPI_Comm

443:    Input Parameters:
444: +  comm   - the communicator (usually MPI_COMM_WORLD)
445: .  fd     - file to print to, usually stdout
446: .  prefix - prefix to prepend to name (optional)
447: .  name   - option string (for example, "-ksp_type")
448: .  text - short description of the object (for example, "Krylov solvers")
449: .  man - name of manual page that discusses the object (for example, "KSPCreate")
450: .  list   - list of types
451: .  def - default (current) value
452: -  newv - new value

454:    Level: developer

456: .seealso: PetscFunctionListAdd(), PetscFunctionList
457: @*/
458: 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[])
459: {
460:   char           p[64];

462:   if (!fd) fd = PETSC_STDOUT;

464:   PetscStrncpy(p,"-",sizeof(p));
465:   if (prefix) PetscStrlcat(p,prefix,sizeof(p));
466:   PetscFPrintf(comm,fd,"  %s%s <now %s : formerly %s>: %s (one of)",p,name+1,newv,def,text);

468:   while (list) {
469:     PetscFPrintf(comm,fd," %s",list->name);
470:     list = list->next;
471:   }
472:   PetscFPrintf(comm,fd," (%s)\n",man);
473:   return 0;
474: }

476: /*@
477:     PetscFunctionListDuplicate - Creates a new list from a given object list.

479:     Input Parameters:
480: .   fl   - pointer to list

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

485:     Level: developer

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

489: @*/
490: PetscErrorCode  PetscFunctionListDuplicate(PetscFunctionList fl,PetscFunctionList *nl)
491: {
492:   while (fl) {
493:     PetscFunctionListAdd(nl,fl->name,fl->routine);
494:     fl   = fl->next;
495:   }
496:   return 0;
497: }