Actual source code: reg.c

petsc-3.7.3 2016-08-01
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: extern PetscErrorCode CharacteristicInitializePackage(void);
 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

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

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

 80: #if !defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
 81:   /*
 82:       This just initializes the most basic PETSc stuff.

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

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

122: #if defined(PETSC_HAVE_THREADSAFETY)
123:   /* These must be done here because it is not safe for individual threads to call these initialize routines */
124:   AOInitializePackage();
125:   PetscSFInitializePackage();
126:   CharacteristicInitializePackage();
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: }

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

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

156: #if defined(PETSC_HAVE_THREADSAFETY)
157:   PetscCommDestroy(&PETSC_COMM_SELF_INNER);
158:   PetscCommDestroy(&PETSC_COMM_WORLD_INNER);
159: #endif

161:   PetscDLLibrariesLoaded = 0;
162:   return(0);
163: }



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

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

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

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

188:    Not Collective

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

195:    Notes:
196:    To remove a registered routine, pass in a NULL fptr.

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

203:     Level: developer

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

216:   if (!*fl) {
217:     PetscNew(&entry);
218:     PetscStrallocpy(name,&entry->name);
219:     entry->routine = fnc;
220:     entry->next    = 0;
221:     *fl            = entry;

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

235:   } else {
236:     /* search list to see if it is already there */
237:     ne = *fl;
238:     while (ne) {
239:       PetscBool founddup;

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

261: /*@
262:     PetscFunctionListDestroy - Destroys a list of registered routines.

264:     Input Parameter:
265: .   fl  - pointer to list

267:     Level: developer

269: .seealso: PetscFunctionListAdd(), PetscFunctionList
270: @*/
271: PetscErrorCode  PetscFunctionListDestroy(PetscFunctionList *fl)
272: {
273:   PetscFunctionList next,entry,tmp = dlallhead;
274:   PetscErrorCode    ierr;

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

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

293:   /* free this list */
294:   entry = *fl;
295:   while (entry) {
296:     next  = entry->next;
297:     PetscFree(entry->name);
298:     PetscFree(entry);
299:     entry = next;
300:   }
301:   *fl = 0;
302:   return(0);
303: }

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

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

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

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

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

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

340:     Level: developer

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

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

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

369: /*@
370:    PetscFunctionListView - prints out contents of an PetscFunctionList

372:    Collective over MPI_Comm

374:    Input Parameters:
375: +  list - the list of functions
376: -  viewer - currently ignored

378:    Level: developer

380: .seealso: PetscFunctionListAdd(), PetscFunctionListPrintTypes(), PetscFunctionList
381: @*/
382: PetscErrorCode  PetscFunctionListView(PetscFunctionList list,PetscViewer viewer)
383: {
385:   PetscBool      iascii;

388:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;

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

395:   while (list) {
396:     PetscViewerASCIIPrintf(viewer," %s\n",list->name);
397:     list = list->next;
398:   }
399:   PetscViewerASCIIPrintf(viewer,"\n");
400:   return(0);
401: }

405: /*@C
406:    PetscFunctionListGet - Gets an array the contains the entries in PetscFunctionList, this is used
407:          by help etc.

409:    Not Collective

411:    Input Parameter:
412: .  list   - list of types

414:    Output Parameter:
415: +  array - array of names
416: -  n - length of array

418:    Notes:
419:        This allocates the array so that must be freed. BUT the individual entries are
420:     not copied so should not be freed.

422:    Level: developer

424: .seealso: PetscFunctionListAdd(), PetscFunctionList
425: @*/
426: PetscErrorCode  PetscFunctionListGet(PetscFunctionList list,const char ***array,int *n)
427: {
428:   PetscErrorCode    ierr;
429:   PetscInt          count = 0;
430:   PetscFunctionList klist = list;

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


452: /*@C
453:    PetscFunctionListPrintTypes - Prints the methods available.

455:    Collective over MPI_Comm

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

467:    Level: developer

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

477:   if (!fd) fd = PETSC_STDOUT;

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

483:   while (list) {
484:     PetscFPrintf(comm,fd," %s",list->name);
485:     list = list->next;
486:   }
487:   PetscFPrintf(comm,fd," (%s)\n",man);
488:   return(0);
489: }

493: /*@
494:     PetscFunctionListDuplicate - Creates a new list from a given object list.

496:     Input Parameters:
497: .   fl   - pointer to list

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

502:     Level: developer

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

506: @*/
507: PetscErrorCode  PetscFunctionListDuplicate(PetscFunctionList fl,PetscFunctionList *nl)
508: {

512:   while (fl) {
513:     PetscFunctionListAdd(nl,fl->name,fl->routine);
514:     fl   = fl->next;
515:   }
516:   return(0);
517: }