Actual source code: reg.c

petsc-3.4.4 2014-03-13
  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_USE_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

 44: /*
 45:     PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
 46:     search path.
 47: */
 48: PetscErrorCode  PetscInitialize_DynamicLibraries(void)
 49: {
 50:   char           *libname[32];
 52:   PetscInt       nmax,i;
 53: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
 54:   PetscBool      found;
 55: #endif

 58:   nmax = 32;
 59:   PetscOptionsGetStringArray(NULL,"-dll_prepend",libname,&nmax,NULL);
 60:   for (i=0; i<nmax; i++) {
 61:     PetscDLLibraryPrepend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);
 62:     PetscFree(libname[i]);
 63:   }

 65: #if !defined(PETSC_USE_DYNAMIC_LIBRARIES)
 66:   /*
 67:       This just initializes the most basic PETSc stuff.

 69:     The classes, from PetscDraw to PetscTS, are initialized the first
 70:     time an XXCreate() is called.
 71:   */
 72:   PetscSysInitializePackage();
 73: #else
 74: #if defined(PETSC_USE_SINGLE_LIBRARY)
 75:   PetscLoadDynamicLibrary("",&found);
 76:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
 77: #else
 78:   PetscLoadDynamicLibrary("sys",&found);
 79:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
 80:   PetscLoadDynamicLibrary("vec",&found);
 81:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Vec dynamic library \n You cannot move the dynamic libraries!");
 82:   PetscLoadDynamicLibrary("mat",&found);
 83:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Mat dynamic library \n You cannot move the dynamic libraries!");
 84:   PetscLoadDynamicLibrary("dm",&found);
 85:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc DM dynamic library \n You cannot move the dynamic libraries!");
 86:   PetscLoadDynamicLibrary("ksp",&found);
 87:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc KSP dynamic library \n You cannot move the dynamic libraries!");
 88:   PetscLoadDynamicLibrary("snes",&found);
 89:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc SNES dynamic library \n You cannot move the dynamic libraries!");
 90:   PetscLoadDynamicLibrary("ts",&found);
 91:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc TS dynamic library \n You cannot move the dynamic libraries!");
 92: #endif
 93: #endif

 95:   nmax = 32;
 96:   PetscOptionsGetStringArray(NULL,"-dll_append",libname,&nmax,NULL);
 97:   for (i=0; i<nmax; i++) {
 98:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);
 99:     PetscFree(libname[i]);
100:   }
101:   return(0);
102: }

106: /*
107:      PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
108: */
109: PetscErrorCode PetscFinalize_DynamicLibraries(void)
110: {
112:   PetscBool      flg = PETSC_FALSE;

115:   PetscOptionsGetBool(NULL,"-dll_view",&flg,NULL);
116:   if (flg) { PetscDLLibraryPrintPath(PetscDLLibrariesLoaded); }
117:   PetscDLLibraryClose(PetscDLLibrariesLoaded);

119:   PetscDLLibrariesLoaded = 0;
120:   return(0);
121: }



125: /* ------------------------------------------------------------------------------*/
126: struct _n_PetscFunctionList {
127:   void              (*routine)(void);    /* the routine */
128:   char              *name;               /* string to identify routine */
129:   PetscFunctionList next;                /* next pointer */
130:   PetscFunctionList next_list;           /* used to maintain list of all lists for freeing */
131: };

133: /*
134:      Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones.
135: */
136: static PetscFunctionList dlallhead = 0;

138: /*MC
139:    PetscFunctionListAdd - Given a routine and a string id, saves that routine in the
140:    specified registry.

142:    Synopsis:
143:    #include "petscsys.h"
144:    PetscErrorCode PetscFunctionListAdd(PetscFunctionList flist,const char name[],void (*fptr)(void))

146:    Not Collective

148:    Input Parameters:
149: +  flist - pointer registry
150: .  name - string to identify routine
151: -  fptr - function pointer

153:    Notes:
154:    To remove a registered routine, pass in a NULL fptr.

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

161:     Level: developer

163: .seealso: PetscFunctionListDestroy(), SNESRegister(), KSPRegister(),
164:           PCRegister(), TSRegister(), PetscFunctionList, PetscObjectComposeFunction()
165: M*/
168: PETSC_EXTERN PetscErrorCode PetscFunctionListAdd_Private(PetscFunctionList *fl,const char name[],void (*fnc)(void))
169: {
170:   PetscFunctionList entry,ne;
171:   PetscErrorCode    ierr;

174:   if (!*fl) {
175:     PetscNew(struct _n_PetscFunctionList,&entry);
176:     PetscStrallocpy(name,&entry->name);
177:     entry->routine = fnc;
178:     entry->next    = 0;
179:     *fl            = entry;

181:     /* add this new list to list of all lists */
182:     if (!dlallhead) {
183:       dlallhead        = *fl;
184:       (*fl)->next_list = 0;
185:     } else {
186:       ne               = dlallhead;
187:       dlallhead        = *fl;
188:       (*fl)->next_list = ne;
189:     }
190:   } else {
191:     /* search list to see if it is already there */
192:     ne = *fl;
193:     while (ne) {
194:       PetscBool founddup;

196:       PetscStrcmp(ne->name,name,&founddup);
197:       if (founddup) { /* found duplicate */
198:         ne->routine = fnc;
199:         return(0);
200:       }
201:       if (ne->next) ne = ne->next;
202:       else break;
203:     }
204:     /* create new entry and add to end of list */
205:     PetscNew(struct _n_PetscFunctionList,&entry);
206:     PetscStrallocpy(name,&entry->name);
207:     entry->routine = fnc;
208:     entry->next    = 0;
209:     ne->next       = entry;
210:   }
211:   return(0);
212: }

216: /*@
217:     PetscFunctionListDestroy - Destroys a list of registered routines.

219:     Input Parameter:
220: .   fl  - pointer to list

222:     Level: developer

224: .seealso: PetscFunctionListAdd(), PetscFunctionList
225: @*/
226: PetscErrorCode  PetscFunctionListDestroy(PetscFunctionList *fl)
227: {
228:   PetscFunctionList next,entry,tmp = dlallhead;
229:   PetscErrorCode    ierr;

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

234:   /*
235:        Remove this entry from the master DL list (if it is in it)
236:   */
237:   if (dlallhead == *fl) {
238:     if (dlallhead->next_list) dlallhead = dlallhead->next_list;
239:     else dlallhead = NULL;
240:   } else if (tmp) {
241:     while (tmp->next_list != *fl) {
242:       tmp = tmp->next_list;
243:       if (!tmp->next_list) break;
244:     }
245:     if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
246:   }

248:   /* free this list */
249:   entry = *fl;
250:   while (entry) {
251:     next  = entry->next;
252:     PetscFree(entry->name);
253:     PetscFree(entry);
254:     entry = next;
255:   }
256:   *fl = 0;
257:   return(0);
258: }

260: /*
261:    Print any PetscFunctionLists that have not be destroyed
262: */
265: PetscErrorCode  PetscFunctionListPrintAll(void)
266: {
267:   PetscFunctionList tmp = dlallhead;
268:   PetscErrorCode    ierr;

271:   if (tmp) {
272:     PetscPrintf(PETSC_COMM_WORLD,"The following PetscFunctionLists were not destroyed\n");
273:   }
274:   while (tmp) {
275:     PetscPrintf(PETSC_COMM_WORLD,"%s \n",tmp->name);
276:     tmp = tmp->next_list;
277:   }
278:   return(0);
279: }

281: /*MC
282:     PetscFunctionListFind - Find function registered under given name

284:     Synopsis:
285:     #include "petscsys.h"
286:     PetscErrorCode PetscFunctionListFind(PetscFunctionList flist,const char name[],void (**fptr)(void))

288:     Input Parameters:
289: +   flist   - pointer to list
290: -   name - name registered for the function

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

295:     Level: developer

297: .seealso: PetscFunctionListAdd(), PetscFunctionList, PetscObjectQueryFunction()
298: M*/
301: PETSC_EXTERN PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl,const char name[],void (**r)(void))
302: {
303:   PetscFunctionList entry = fl;
304:   PetscErrorCode    ierr;
305:   PetscBool         flg;

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

310:   *r = 0;
311:   while (entry) {
312:     PetscStrcmp(name,entry->name,&flg);
313:     if (flg) {
314:       *r   = entry->routine;
315:       return(0);
316:     }
317:     entry = entry->next;
318:   }
319:   return(0);
320: }

324: /*@
325:    PetscFunctionListView - prints out contents of an PetscFunctionList

327:    Collective over MPI_Comm

329:    Input Parameters:
330: +  list - the list of functions
331: -  viewer - currently ignored

333:    Level: developer

335: .seealso: PetscFunctionListAdd(), PetscFunctionListPrintTypes(), PetscFunctionList
336: @*/
337: PetscErrorCode  PetscFunctionListView(PetscFunctionList list,PetscViewer viewer)
338: {
340:   PetscBool      iascii;

343:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;

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

350:   while (list) {
351:     PetscViewerASCIIPrintf(viewer," %s\n",list->name);
352:     list = list->next;
353:   }
354:   PetscViewerASCIIPrintf(viewer,"\n");
355:   return(0);
356: }

360: /*@C
361:    PetscFunctionListGet - Gets an array the contains the entries in PetscFunctionList, this is used
362:          by help etc.

364:    Not Collective

366:    Input Parameter:
367: .  list   - list of types

369:    Output Parameter:
370: +  array - array of names
371: -  n - length of array

373:    Notes:
374:        This allocates the array so that must be freed. BUT the individual entries are
375:     not copied so should not be freed.

377:    Level: developer

379: .seealso: PetscFunctionListAdd(), PetscFunctionList
380: @*/
381: PetscErrorCode  PetscFunctionListGet(PetscFunctionList list,const char ***array,int *n)
382: {
383:   PetscErrorCode    ierr;
384:   PetscInt          count = 0;
385:   PetscFunctionList klist = list;

388:   while (list) {
389:     list = list->next;
390:     count++;
391:   }
392:   PetscMalloc((count+1)*sizeof(char*),array);
393:   count = 0;
394:   while (klist) {
395:     (*array)[count] = klist->name;
396:     klist           = klist->next;
397:     count++;
398:   }
399:   (*array)[count] = 0;
400:   *n              = count+1;
401:   return(0);
402: }


407: /*@C
408:    PetscFunctionListPrintTypes - Prints the methods available.

410:    Collective over MPI_Comm

412:    Input Parameters:
413: +  comm   - the communicator (usually MPI_COMM_WORLD)
414: .  fd     - file to print to, usually stdout
415: .  prefix - prefix to prepend to name (optional)
416: .  name   - option string (for example, "-ksp_type")
417: .  text - short description of the object (for example, "Krylov solvers")
418: .  man - name of manual page that discusses the object (for example, "KSPCreate")
419: .  list   - list of types
420: -  def - default (current) value

422:    Level: developer

424: .seealso: PetscFunctionListAdd(), PetscFunctionList
425: @*/
426: PetscErrorCode  PetscFunctionListPrintTypes(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[],PetscFunctionList list,const char def[])
427: {
429:   PetscInt       count = 0;
430:   char           p[64];

433:   if (!fd) fd = PETSC_STDOUT;

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

439:   while (list) {
440:     PetscFPrintf(comm,fd," %s",list->name);
441:     list = list->next;
442:     count++;
443:     if (count == 8) {PetscFPrintf(comm,fd,"\n     ");}
444:   }
445:   PetscFPrintf(comm,fd," (%s)\n",man);
446:   return(0);
447: }

451: /*@
452:     PetscFunctionListDuplicate - Creates a new list from a given object list.

454:     Input Parameters:
455: .   fl   - pointer to list

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

460:     Level: developer

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

464: @*/
465: PetscErrorCode  PetscFunctionListDuplicate(PetscFunctionList fl,PetscFunctionList *nl)
466: {

470:   while (fl) {
471:     PetscFunctionListAdd(nl,fl->name,fl->routine);
472:     fl   = fl->next;
473:   }
474:   return(0);
475: }