Actual source code: reg.c

petsc-3.7.7 2017-09-25
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>           /*I "petscsys.h" I*/
  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)

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

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

 40: #endif

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

 61: /*
 62:     PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
 63:     search path.
 64: */
 65: PetscErrorCode  PetscInitialize_DynamicLibraries(void)
 66: {
 67:   char           *libname[32];
 69:   PetscInt       nmax,i;
 70: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
 71:   PetscBool      preload;
 72: #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: #if !defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
 83:   /*
 84:       This just initializes the most basic PETSc stuff.

 86:     The classes, from PetscDraw to PetscTS, are initialized the first
 87:     time an XXCreate() is called.
 88:   */
 89:   PetscSysInitializePackage();
 90: #else
 91:   preload = PETSC_FALSE;
 92:   PetscOptionsGetBool(NULL,NULL,"-dynamic_library_preload",&preload,NULL);
 93:   if (preload) {
 94:     PetscBool found;
 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("ksp",&found);
108:     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc KSP dynamic library \n You cannot move the dynamic libraries!");
109:     PetscLoadDynamicLibrary("snes",&found);
110:     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc SNES dynamic library \n You cannot move the dynamic libraries!");
111:     PetscLoadDynamicLibrary("ts",&found);
112:     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc TS dynamic library \n You cannot move the dynamic libraries!");
113: #endif
114:   }
115: #endif

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

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

147: /*
148:      PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
149: */
150: PetscErrorCode PetscFinalize_DynamicLibraries(void)
151: {
153:   PetscBool      flg = PETSC_FALSE;

156:   PetscOptionsGetBool(NULL,NULL,"-dll_view",&flg,NULL);
157:   if (flg) { PetscDLLibraryPrintPath(PetscDLLibrariesLoaded); }
158:   PetscDLLibraryClose(PetscDLLibrariesLoaded);

160: #if defined(PETSC_HAVE_THREADSAFETY)
161:   PetscCommDestroy(&PETSC_COMM_SELF_INNER);
162:   PetscCommDestroy(&PETSC_COMM_WORLD_INNER);
163: #endif

165:   PetscDLLibrariesLoaded = 0;
166:   return(0);
167: }



171: /* ------------------------------------------------------------------------------*/
172: struct _n_PetscFunctionList {
173:   void              (*routine)(void);    /* the routine */
174:   char              *name;               /* string to identify routine */
175:   PetscFunctionList next;                /* next pointer */
176:   PetscFunctionList next_list;           /* used to maintain list of all lists for freeing */
177: };

179: /*
180:      Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones.
181: */
182: static PetscFunctionList dlallhead = 0;

184: /*MC
185:    PetscFunctionListAdd - Given a routine and a string id, saves that routine in the
186:    specified registry.

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

192:    Not Collective

194:    Input Parameters:
195: +  flist - pointer to function list object
196: .  name - string to identify routine
197: -  fptr - function pointer

199:    Notes:
200:    To remove a registered routine, pass in a NULL fptr.

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

207:     Level: developer

209: .seealso: PetscFunctionListDestroy(), SNESRegister(), KSPRegister(),
210:           PCRegister(), TSRegister(), PetscFunctionList, PetscObjectComposeFunction()
211: M*/
214: PETSC_EXTERN PetscErrorCode PetscFunctionListAdd_Private(PetscFunctionList *fl,const char name[],void (*fnc)(void))
215: {
216:   PetscFunctionList entry,ne;
217:   PetscErrorCode    ierr;

220:   if (!*fl) {
221:     PetscNew(&entry);
222:     PetscStrallocpy(name,&entry->name);
223:     entry->routine = fnc;
224:     entry->next    = 0;
225:     *fl            = entry;

227: #if defined(PETSC_USE_DEBUG)
228:     /* add this new list to list of all lists */
229:     if (!dlallhead) {
230:       dlallhead        = *fl;
231:       (*fl)->next_list = 0;
232:     } else {
233:       ne               = dlallhead;
234:       dlallhead        = *fl;
235:       (*fl)->next_list = ne;
236:     }
237: #endif

239:   } else {
240:     /* search list to see if it is already there */
241:     ne = *fl;
242:     while (ne) {
243:       PetscBool founddup;

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

265: /*@
266:     PetscFunctionListDestroy - Destroys a list of registered routines.

268:     Input Parameter:
269: .   fl  - pointer to list

271:     Level: developer

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

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

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

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

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

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

330: /*MC
331:     PetscFunctionListFind - Find function registered under given name

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

337:     Input Parameters:
338: +   flist   - pointer to list
339: -   name - name registered for the function

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

344:     Level: developer

346: .seealso: PetscFunctionListAdd(), PetscFunctionList, PetscObjectQueryFunction()
347: M*/
350: PETSC_EXTERN PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl,const char name[],void (**r)(void))
351: {
352:   PetscFunctionList entry = fl;
353:   PetscErrorCode    ierr;
354:   PetscBool         flg;

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

359:   *r = 0;
360:   while (entry) {
361:     PetscStrcmp(name,entry->name,&flg);
362:     if (flg) {
363:       *r   = entry->routine;
364:       return(0);
365:     }
366:     entry = entry->next;
367:   }
368:   return(0);
369: }

373: /*@
374:    PetscFunctionListView - prints out contents of an PetscFunctionList

376:    Collective over MPI_Comm

378:    Input Parameters:
379: +  list - the list of functions
380: -  viewer - currently ignored

382:    Level: developer

384: .seealso: PetscFunctionListAdd(), PetscFunctionListPrintTypes(), PetscFunctionList
385: @*/
386: PetscErrorCode  PetscFunctionListView(PetscFunctionList list,PetscViewer viewer)
387: {
389:   PetscBool      iascii;

392:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;

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

399:   while (list) {
400:     PetscViewerASCIIPrintf(viewer," %s\n",list->name);
401:     list = list->next;
402:   }
403:   PetscViewerASCIIPrintf(viewer,"\n");
404:   return(0);
405: }

409: /*@C
410:    PetscFunctionListGet - Gets an array the contains the entries in PetscFunctionList, this is used
411:          by help etc.

413:    Not Collective

415:    Input Parameter:
416: .  list   - list of types

418:    Output Parameter:
419: +  array - array of names
420: -  n - length of array

422:    Notes:
423:        This allocates the array so that must be freed. BUT the individual entries are
424:     not copied so should not be freed.

426:    Level: developer

428: .seealso: PetscFunctionListAdd(), PetscFunctionList
429: @*/
430: PetscErrorCode  PetscFunctionListGet(PetscFunctionList list,const char ***array,int *n)
431: {
432:   PetscErrorCode    ierr;
433:   PetscInt          count = 0;
434:   PetscFunctionList klist = list;

437:   while (list) {
438:     list = list->next;
439:     count++;
440:   }
441:   PetscMalloc1(count+1,array);
442:   count = 0;
443:   while (klist) {
444:     (*array)[count] = klist->name;
445:     klist           = klist->next;
446:     count++;
447:   }
448:   (*array)[count] = 0;
449:   *n              = count+1;
450:   return(0);
451: }


456: /*@C
457:    PetscFunctionListPrintTypes - Prints the methods available.

459:    Collective over MPI_Comm

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

471:    Level: developer

473: .seealso: PetscFunctionListAdd(), PetscFunctionList
474: @*/
475:  PetscErrorCode  PetscFunctionListPrintTypes(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[],PetscFunctionList list,const char def[])
476: {
478:   char           p[64];

481:   if (!fd) fd = PETSC_STDOUT;

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

487:   while (list) {
488:     PetscFPrintf(comm,fd," %s",list->name);
489:     list = list->next;
490:   }
491:   PetscFPrintf(comm,fd," (%s)\n",man);
492:   return(0);
493: }

497: /*@
498:     PetscFunctionListDuplicate - Creates a new list from a given object list.

500:     Input Parameters:
501: .   fl   - pointer to list

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

506:     Level: developer

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

510: @*/
511: PetscErrorCode  PetscFunctionListDuplicate(PetscFunctionList fl,PetscFunctionList *nl)
512: {

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