Actual source code: reg.c

petsc-3.9.4 2018-09-11
Report Typos and Errors

  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 = 0;

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

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

 38: #endif

 40: #if defined(PETSC_HAVE_THREADSAFETY)
 41: extern PetscErrorCode AOInitializePackage(void);
 42: extern PetscErrorCode PetscSFInitializePackage(void);
 43: #if !defined(PETSC_USE_COMPLEX)
 44: extern PetscErrorCode CharacteristicInitializePackage(void);
 45: #endif
 46: extern PetscErrorCode ISInitializePackage(void);
 47: extern PetscErrorCode VecInitializePackage(void);
 48: extern PetscErrorCode MatInitializePackage(void);
 49: extern PetscErrorCode DMInitializePackage(void);
 50: extern PetscErrorCode PCInitializePackage(void);
 51: extern PetscErrorCode KSPInitializePackage(void);
 52: extern PetscErrorCode SNESInitializePackage(void);
 53: extern PetscErrorCode TSInitializePackage(void);
 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: PetscErrorCode  PetscInitialize_DynamicLibraries(void)
 62: {
 63:   char           *libname[32];
 65:   PetscInt       nmax,i;
 66: #if defined(PETSC_USE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES)
 67:   PetscBool      preload;
 68: #endif

 71:   nmax = 32;
 72:   PetscOptionsGetStringArray(NULL,NULL,"-dll_prepend",libname,&nmax,NULL);
 73:   for (i=0; i<nmax; i++) {
 74:     PetscDLLibraryPrepend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);
 75:     PetscFree(libname[i]);
 76:   }

 78: #if !defined(PETSC_USE_DYNAMIC_LIBRARIES) || !defined(PETSC_USE_SHARED_LIBRARIES)
 79:   /*
 80:       This just initializes the most basic PETSc stuff.

 82:     The classes, from PetscDraw to PetscTS, are initialized the first
 83:     time an XXCreate() is called.
 84:   */
 85:   PetscSysInitializePackage();
 86: #else
 87:   preload = PETSC_FALSE;
 88:   PetscOptionsGetBool(NULL,NULL,"-dynamic_library_preload",&preload,NULL);
 89:   if (preload) {
 90:     PetscBool found;
 91: #if defined(PETSC_USE_SINGLE_LIBRARY)
 92:     PetscLoadDynamicLibrary("",&found);
 93:     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
 94: #else
 95:     PetscLoadDynamicLibrary("sys",&found);
 96:     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
 97:     PetscLoadDynamicLibrary("vec",&found);
 98:     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Vec dynamic library \n You cannot move the dynamic libraries!");
 99:     PetscLoadDynamicLibrary("mat",&found);
100:     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Mat dynamic library \n You cannot move the dynamic libraries!");
101:     PetscLoadDynamicLibrary("dm",&found);
102:     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc DM dynamic library \n You cannot move the dynamic libraries!");
103:     PetscLoadDynamicLibrary("ksp",&found);
104:     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc KSP dynamic library \n You cannot move the dynamic libraries!");
105:     PetscLoadDynamicLibrary("snes",&found);
106:     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc SNES dynamic library \n You cannot move the dynamic libraries!");
107:     PetscLoadDynamicLibrary("ts",&found);
108:     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc TS dynamic library \n You cannot move the dynamic libraries!");
109: #endif
110:   }
111: #endif

113:   nmax = 32;
114:   PetscOptionsGetStringArray(NULL,NULL,"-dll_append",libname,&nmax,NULL);
115:   for (i=0; i<nmax; i++) {
116:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);
117:     PetscFree(libname[i]);
118:   }

120: #if defined(PETSC_HAVE_THREADSAFETY)
121:   /* These must be done here because it is not safe for individual threads to call these initialize routines */
122:   AOInitializePackage();
123:   PetscSFInitializePackage();
124: #if !defined(PETSC_USE_COMPLEX)
125:   CharacteristicInitializePackage();
126: #endif
127:   ISInitializePackage();
128:   VecInitializePackage();
129:   MatInitializePackage();
130:   DMInitializePackage();
131:   PCInitializePackage();
132:   KSPInitializePackage();
133:   SNESInitializePackage();
134:   TSInitializePackage();
135:   PetscCommDuplicate(PETSC_COMM_SELF,&PETSC_COMM_SELF_INNER,NULL);
136:   PetscCommDuplicate(PETSC_COMM_WORLD,&PETSC_COMM_WORLD_INNER,NULL);
137: #endif
138:   return(0);
139: }

141: /*
142:      PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
143: */
144: PetscErrorCode PetscFinalize_DynamicLibraries(void)
145: {
147:   PetscBool      flg = PETSC_FALSE;

150:   PetscOptionsGetBool(NULL,NULL,"-dll_view",&flg,NULL);
151:   if (flg) { PetscDLLibraryPrintPath(PetscDLLibrariesLoaded); }
152:   PetscDLLibraryClose(PetscDLLibrariesLoaded);

154: #if defined(PETSC_HAVE_THREADSAFETY)
155:   PetscCommDestroy(&PETSC_COMM_SELF_INNER);
156:   PetscCommDestroy(&PETSC_COMM_WORLD_INNER);
157: #endif

159:   PetscDLLibrariesLoaded = 0;
160:   return(0);
161: }



165: /* ------------------------------------------------------------------------------*/
166: struct _n_PetscFunctionList {
167:   void              (*routine)(void);    /* the routine */
168:   char              *name;               /* string to identify routine */
169:   PetscFunctionList next;                /* next pointer */
170:   PetscFunctionList next_list;           /* used to maintain list of all lists for freeing */
171: };

173: /*
174:      Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones.
175: */
176: static PetscFunctionList dlallhead = 0;

178: /*MC
179:    PetscFunctionListAdd - Given a routine and a string id, saves that routine in the
180:    specified registry.

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

186:    Not Collective

188:    Input Parameters:
189: +  flist - pointer to function list object
190: .  name - string to identify routine
191: -  fptr - function pointer

193:    Notes:
194:    To remove a registered routine, pass in a NULL fptr.

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

201:     Level: developer

203: .seealso: PetscFunctionListDestroy(), SNESRegister(), KSPRegister(),
204:           PCRegister(), TSRegister(), PetscFunctionList, PetscObjectComposeFunction()
205: M*/
206: PETSC_EXTERN PetscErrorCode PetscFunctionListAdd_Private(PetscFunctionList *fl,const char name[],void (*fnc)(void))
207: {
208:   PetscFunctionList entry,ne;
209:   PetscErrorCode    ierr;

212:   if (!*fl) {
213:     PetscNew(&entry);
214:     PetscStrallocpy(name,&entry->name);
215:     entry->routine = fnc;
216:     entry->next    = 0;
217:     *fl            = entry;

219: #if defined(PETSC_USE_DEBUG)
220:     /* add this new list to list of all lists */
221:     if (!dlallhead) {
222:       dlallhead        = *fl;
223:       (*fl)->next_list = 0;
224:     } else {
225:       ne               = dlallhead;
226:       dlallhead        = *fl;
227:       (*fl)->next_list = ne;
228:     }
229: #endif

231:   } else {
232:     /* search list to see if it is already there */
233:     ne = *fl;
234:     while (ne) {
235:       PetscBool founddup;

237:       PetscStrcmp(ne->name,name,&founddup);
238:       if (founddup) { /* found duplicate */
239:         ne->routine = fnc;
240:         return(0);
241:       }
242:       if (ne->next) ne = ne->next;
243:       else break;
244:     }
245:     /* create new entry and add to end of list */
246:     PetscNew(&entry);
247:     PetscStrallocpy(name,&entry->name);
248:     entry->routine = fnc;
249:     entry->next    = 0;
250:     ne->next       = entry;
251:   }
252:   return(0);
253: }

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

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

261:     Level: developer

263: .seealso: PetscFunctionListAdd(), PetscFunctionList
264: @*/
265: PetscErrorCode  PetscFunctionListDestroy(PetscFunctionList *fl)
266: {
267:   PetscFunctionList next,entry,tmp = dlallhead;
268:   PetscErrorCode    ierr;

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

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) dlallhead = dlallhead->next_list;
278:     else dlallhead = NULL;
279:   } else if (tmp) {
280:     while (tmp->next_list != *fl) {
281:       tmp = tmp->next_list;
282:       if (!tmp->next_list) break;
283:     }
284:     if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
285:   }

287:   /* free this list */
288:   entry = *fl;
289:   while (entry) {
290:     next  = entry->next;
291:     PetscFree(entry->name);
292:     PetscFree(entry);
293:     entry = next;
294:   }
295:   *fl = 0;
296:   return(0);
297: }

299: /*
300:    Print any PetscFunctionLists that have not be destroyed
301: */
302: PetscErrorCode  PetscFunctionListPrintAll(void)
303: {
304:   PetscFunctionList tmp = dlallhead;
305:   PetscErrorCode    ierr;

308:   if (tmp) {
309:     PetscPrintf(PETSC_COMM_WORLD,"The following PetscFunctionLists were not destroyed\n");
310:   }
311:   while (tmp) {
312:     PetscPrintf(PETSC_COMM_WORLD,"%s \n",tmp->name);
313:     tmp = tmp->next_list;
314:   }
315:   return(0);
316: }

318: /*MC
319:     PetscFunctionListFind - Find function registered under given name

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

325:     Input Parameters:
326: +   flist   - pointer to list
327: -   name - name registered for the function

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

332:     Level: developer

334: .seealso: PetscFunctionListAdd(), PetscFunctionList, PetscObjectQueryFunction()
335: M*/
336: PETSC_EXTERN PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl,const char name[],void (**r)(void))
337: {
338:   PetscFunctionList entry = fl;
339:   PetscErrorCode    ierr;
340:   PetscBool         flg;

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

345:   *r = 0;
346:   while (entry) {
347:     PetscStrcmp(name,entry->name,&flg);
348:     if (flg) {
349:       *r   = entry->routine;
350:       return(0);
351:     }
352:     entry = entry->next;
353:   }
354:   return(0);
355: }

357: /*@
358:    PetscFunctionListView - prints out contents of an PetscFunctionList

360:    Collective over MPI_Comm

362:    Input Parameters:
363: +  list - the list of functions
364: -  viewer - currently ignored

366:    Level: developer

368: .seealso: PetscFunctionListAdd(), PetscFunctionListPrintTypes(), PetscFunctionList
369: @*/
370: PetscErrorCode  PetscFunctionListView(PetscFunctionList list,PetscViewer viewer)
371: {
373:   PetscBool      iascii;

376:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;

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

383:   while (list) {
384:     PetscViewerASCIIPrintf(viewer," %s\n",list->name);
385:     list = list->next;
386:   }
387:   PetscViewerASCIIPrintf(viewer,"\n");
388:   return(0);
389: }

391: /*@C
392:    PetscFunctionListGet - Gets an array the contains the entries in PetscFunctionList, this is used
393:          by help etc.

395:    Not Collective

397:    Input Parameter:
398: .  list   - list of types

400:    Output Parameter:
401: +  array - array of names
402: -  n - length of array

404:    Notes:
405:        This allocates the array so that must be freed. BUT the individual entries are
406:     not copied so should not be freed.

408:    Level: developer

410: .seealso: PetscFunctionListAdd(), PetscFunctionList
411: @*/
412: PetscErrorCode  PetscFunctionListGet(PetscFunctionList list,const char ***array,int *n)
413: {
414:   PetscErrorCode    ierr;
415:   PetscInt          count = 0;
416:   PetscFunctionList klist = list;

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


436: /*@C
437:    PetscFunctionListPrintTypes - Prints the methods available.

439:    Collective over MPI_Comm

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

451:    Level: developer

453: .seealso: PetscFunctionListAdd(), PetscFunctionList
454: @*/
455:  PetscErrorCode  PetscFunctionListPrintTypes(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[],PetscFunctionList list,const char def[])
456: {
458:   char           p[64];

461:   if (!fd) fd = PETSC_STDOUT;

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

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

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

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

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

484:     Level: developer

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

488: @*/
489: PetscErrorCode  PetscFunctionListDuplicate(PetscFunctionList fl,PetscFunctionList *nl)
490: {

494:   while (fl) {
495:     PetscFunctionListAdd(nl,fl->name,fl->routine);
496:     fl   = fl->next;
497:   }
498:   return(0);
499: }