xref: /petsc/src/sys/dll/reg.c (revision d8d19677bbccf95218448bee62e6b87f4513e133)
17d0a6c19SBarry Smith 
2e5c89e4eSSatish Balay /*
3e5c89e4eSSatish Balay     Provides a general mechanism to allow one to register new routines in
4e5c89e4eSSatish Balay     dynamic libraries for many of the PETSc objects (including, e.g., KSP and PC).
5e5c89e4eSSatish Balay */
6af0996ceSBarry Smith #include <petsc/private/petscimpl.h>           /*I "petscsys.h" I*/
7665c2dedSJed Brown #include <petscviewer.h>
8e5c89e4eSSatish Balay 
93fa76a5bSLisandro Dalcin /*
103fa76a5bSLisandro Dalcin     This is the default list used by PETSc with the PetscDLLibrary register routines
113fa76a5bSLisandro Dalcin */
1202c9f0b5SLisandro Dalcin PetscDLLibrary PetscDLLibrariesLoaded = NULL;
133fa76a5bSLisandro Dalcin 
14cbd104e6SBarry Smith #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES)
15ebd79076SLisandro Dalcin 
1660da17ecSBarry Smith static PetscErrorCode  PetscLoadDynamicLibrary(const char *name,PetscBool  *found)
17487e5849SBarry Smith {
18487e5849SBarry Smith   char           libs[PETSC_MAX_PATH_LEN],dlib[PETSC_MAX_PATH_LEN];
19487e5849SBarry Smith   PetscErrorCode ierr;
20487e5849SBarry Smith 
21487e5849SBarry Smith   PetscFunctionBegin;
22a126751eSBarry Smith   ierr = PetscStrncpy(libs,"${PETSC_LIB_DIR}/libpetsc",sizeof(libs));CHKERRQ(ierr);
23a126751eSBarry Smith   ierr = PetscStrlcat(libs,name,sizeof(libs));CHKERRQ(ierr);
24487e5849SBarry Smith   ierr = PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);CHKERRQ(ierr);
25487e5849SBarry Smith   if (*found) {
26d44a1e48SBarry Smith     ierr = PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,dlib);CHKERRQ(ierr);
27487e5849SBarry Smith   } else {
28a126751eSBarry Smith     ierr = PetscStrncpy(libs,"${PETSC_DIR}/${PETSC_ARCH}/lib/libpetsc",sizeof(libs));CHKERRQ(ierr);
29a126751eSBarry Smith     ierr = PetscStrlcat(libs,name,sizeof(libs));CHKERRQ(ierr);
30487e5849SBarry Smith     ierr = PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);CHKERRQ(ierr);
31487e5849SBarry Smith     if (*found) {
32d44a1e48SBarry Smith       ierr = PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,dlib);CHKERRQ(ierr);
33487e5849SBarry Smith     }
34487e5849SBarry Smith   }
35487e5849SBarry Smith   PetscFunctionReturn(0);
36487e5849SBarry Smith }
373fa76a5bSLisandro Dalcin #endif
383fa76a5bSLisandro Dalcin 
3960da17ecSBarry Smith #if defined(PETSC_USE_SINGLE_LIBRARY) && !(defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES))
4095c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode AOInitializePackage(void);
4195c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscSFInitializePackage(void);
427da51e29SSatish Balay #if !defined(PETSC_USE_COMPLEX)
4395c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode CharacteristicInitializePackage(void);
447da51e29SSatish Balay #endif
4595c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode ISInitializePackage(void);
4695c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode VecInitializePackage(void);
4795c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode MatInitializePackage(void);
4895c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode DMInitializePackage(void);
4995c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PCInitializePackage(void);
5095c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode KSPInitializePackage(void);
5195c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode SNESInitializePackage(void);
5295c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode TSInitializePackage(void);
5360da17ecSBarry Smith PETSC_EXTERN PetscErrorCode TaoInitializePackage(void);
5460da17ecSBarry Smith #endif
5560da17ecSBarry Smith #if defined(PETSC_HAVE_THREADSAFETY)
5622b6d1caSBarry Smith static MPI_Comm PETSC_COMM_WORLD_INNER = 0,PETSC_COMM_SELF_INNER = 0;
57acff04ddSBarry Smith #endif
58acff04ddSBarry Smith 
59e5c89e4eSSatish Balay /*
60e5c89e4eSSatish Balay     PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
61e5c89e4eSSatish Balay     search path.
62e5c89e4eSSatish Balay */
6395c0884eSLisandro Dalcin PETSC_INTERN PetscErrorCode PetscInitialize_DynamicLibraries(void)
64e5c89e4eSSatish Balay {
65487e5849SBarry Smith   char           *libname[32];
66e5c89e4eSSatish Balay   PetscErrorCode ierr;
67e5c89e4eSSatish Balay   PetscInt       nmax,i;
6860da17ecSBarry Smith   PetscBool      preload = PETSC_FALSE;
69540e20f2SPierre Jolivet #if defined(PETSC_HAVE_ELEMENTAL)
70540e20f2SPierre Jolivet   PetscBool      PetscInitialized = PetscInitializeCalled;
71540e20f2SPierre Jolivet #endif
72e5c89e4eSSatish Balay 
7360154eb2SBarry Smith   PetscFunctionBegin;
7460da17ecSBarry Smith #if defined(PETSC_HAVE_THREADSAFETY)
7560da17ecSBarry Smith   /* These must be all initialized here because it is not safe for individual threads to call these initialize routines */
7660da17ecSBarry Smith   preload = PETSC_TRUE;
7760da17ecSBarry Smith #endif
7860da17ecSBarry Smith 
79e5c89e4eSSatish Balay   nmax = 32;
80c5929fdfSBarry Smith   ierr = PetscOptionsGetStringArray(NULL,NULL,"-dll_prepend",libname,&nmax,NULL);CHKERRQ(ierr);
81e5c89e4eSSatish Balay   for (i=0; i<nmax; i++) {
82d44a1e48SBarry Smith     ierr = PetscDLLibraryPrepend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);CHKERRQ(ierr);
83e5c89e4eSSatish Balay     ierr = PetscFree(libname[i]);CHKERRQ(ierr);
84e5c89e4eSSatish Balay   }
85e5c89e4eSSatish Balay 
8660da17ecSBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-library_preload",&preload,NULL);CHKERRQ(ierr);
8760da17ecSBarry Smith   if (!preload) {
88607a6623SBarry Smith     ierr = PetscSysInitializePackage();CHKERRQ(ierr);
8960da17ecSBarry Smith   } else {
9060da17ecSBarry Smith #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES)
91aa2d57e9SJed Brown     PetscBool found;
9260154eb2SBarry Smith #if defined(PETSC_USE_SINGLE_LIBRARY)
93487e5849SBarry Smith     ierr = PetscLoadDynamicLibrary("",&found);CHKERRQ(ierr);
94e32f2f54SBarry Smith     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
9560154eb2SBarry Smith #else
9660154eb2SBarry Smith     ierr = PetscLoadDynamicLibrary("sys",&found);CHKERRQ(ierr);
9760154eb2SBarry Smith     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
98487e5849SBarry Smith     ierr = PetscLoadDynamicLibrary("vec",&found);CHKERRQ(ierr);
99e32f2f54SBarry Smith     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Vec dynamic library \n You cannot move the dynamic libraries!");
100487e5849SBarry Smith     ierr = PetscLoadDynamicLibrary("mat",&found);CHKERRQ(ierr);
101e32f2f54SBarry Smith     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Mat dynamic library \n You cannot move the dynamic libraries!");
102487e5849SBarry Smith     ierr = PetscLoadDynamicLibrary("dm",&found);CHKERRQ(ierr);
103e32f2f54SBarry Smith     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc DM dynamic library \n You cannot move the dynamic libraries!");
104487e5849SBarry Smith     ierr = PetscLoadDynamicLibrary("ksp",&found);CHKERRQ(ierr);
105e32f2f54SBarry Smith     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc KSP dynamic library \n You cannot move the dynamic libraries!");
106487e5849SBarry Smith     ierr = PetscLoadDynamicLibrary("snes",&found);CHKERRQ(ierr);
107e32f2f54SBarry Smith     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc SNES dynamic library \n You cannot move the dynamic libraries!");
108487e5849SBarry Smith     ierr = PetscLoadDynamicLibrary("ts",&found);CHKERRQ(ierr);
109e32f2f54SBarry Smith     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc TS dynamic library \n You cannot move the dynamic libraries!");
11060da17ecSBarry Smith     ierr = PetscLoadDynamicLibrary("tao",&found);CHKERRQ(ierr);
11160da17ecSBarry Smith     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate Tao dynamic library \n You cannot move the dynamic libraries!");
112bb84e0fdSBarry Smith #endif
11360da17ecSBarry Smith #else /* defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) */
11460da17ecSBarry Smith #if defined(PETSC_USE_SINGLE_LIBRARY)
1153020f62cSBarry Smith   ierr = AOInitializePackage();CHKERRQ(ierr);
1163020f62cSBarry Smith   ierr = PetscSFInitializePackage();CHKERRQ(ierr);
1177da51e29SSatish Balay #if !defined(PETSC_USE_COMPLEX)
1183020f62cSBarry Smith   ierr = CharacteristicInitializePackage();CHKERRQ(ierr);
1197da51e29SSatish Balay #endif
1203020f62cSBarry Smith   ierr = ISInitializePackage();CHKERRQ(ierr);
1213020f62cSBarry Smith   ierr = VecInitializePackage();CHKERRQ(ierr);
1223020f62cSBarry Smith   ierr = MatInitializePackage();CHKERRQ(ierr);
1233020f62cSBarry Smith   ierr = DMInitializePackage();CHKERRQ(ierr);
1243020f62cSBarry Smith   ierr = PCInitializePackage();CHKERRQ(ierr);
1253020f62cSBarry Smith   ierr = KSPInitializePackage();CHKERRQ(ierr);
1263020f62cSBarry Smith   ierr = SNESInitializePackage();CHKERRQ(ierr);
1273020f62cSBarry Smith   ierr = TSInitializePackage();CHKERRQ(ierr);
12860da17ecSBarry Smith   ierr = TaoInitializePackage();CHKERRQ(ierr);
12960da17ecSBarry Smith #else
13060da17ecSBarry Smith   SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"Cannot use -library_preload with multiple static PETSc libraries");
13160da17ecSBarry Smith #endif
13260da17ecSBarry Smith #endif /* defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) */
13360da17ecSBarry Smith   }
13460da17ecSBarry Smith 
13560da17ecSBarry Smith #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) && defined(PETSC_HAVE_BAMG)
13660da17ecSBarry Smith   {
13760da17ecSBarry Smith     PetscBool found;
13860da17ecSBarry Smith     ierr = PetscLoadDynamicLibrary("bamg",&found);CHKERRQ(ierr);
13960da17ecSBarry Smith     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc BAMG dynamic library \n You cannot move the dynamic libraries!");
14060da17ecSBarry Smith   }
14160da17ecSBarry Smith #endif
14260da17ecSBarry Smith 
14360da17ecSBarry Smith   nmax = 32;
14460da17ecSBarry Smith   ierr = PetscOptionsGetStringArray(NULL,NULL,"-dll_append",libname,&nmax,NULL);CHKERRQ(ierr);
14560da17ecSBarry Smith   for (i=0; i<nmax; i++) {
14660da17ecSBarry Smith     ierr = PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);CHKERRQ(ierr);
14760da17ecSBarry Smith     ierr = PetscFree(libname[i]);CHKERRQ(ierr);
14860da17ecSBarry Smith   }
14960da17ecSBarry Smith 
15060da17ecSBarry Smith #if defined(PETSC_HAVE_THREADSAFETY)
151acff04ddSBarry Smith   ierr = PetscCommDuplicate(PETSC_COMM_SELF,&PETSC_COMM_SELF_INNER,NULL);CHKERRQ(ierr);
152acff04ddSBarry Smith   ierr = PetscCommDuplicate(PETSC_COMM_WORLD,&PETSC_COMM_WORLD_INNER,NULL);CHKERRQ(ierr);
153acff04ddSBarry Smith #endif
154540e20f2SPierre Jolivet #if defined(PETSC_HAVE_ELEMENTAL)
155540e20f2SPierre Jolivet   /* in Fortran, PetscInitializeCalled is set to PETSC_TRUE before PetscInitialize_DynamicLibraries() */
156540e20f2SPierre Jolivet   /* in C, it is not the case, but the value is forced to PETSC_TRUE so that PetscRegisterFinalize() is called */
157540e20f2SPierre Jolivet   PetscInitializeCalled = PETSC_TRUE;
158540e20f2SPierre Jolivet   ierr = PetscElementalInitializePackage();CHKERRQ(ierr);
159540e20f2SPierre Jolivet   PetscInitializeCalled = PetscInitialized;
160540e20f2SPierre Jolivet #endif
161e5c89e4eSSatish Balay   PetscFunctionReturn(0);
162e5c89e4eSSatish Balay }
163e5c89e4eSSatish Balay 
164ebd79076SLisandro Dalcin /*
165ebd79076SLisandro Dalcin      PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
166ebd79076SLisandro Dalcin */
16795c0884eSLisandro Dalcin PETSC_INTERN PetscErrorCode PetscFinalize_DynamicLibraries(void)
168e5c89e4eSSatish Balay {
169ebd79076SLisandro Dalcin   PetscErrorCode ierr;
170ace3abfcSBarry Smith   PetscBool      flg = PETSC_FALSE;
171e5c89e4eSSatish Balay 
172ebd79076SLisandro Dalcin   PetscFunctionBegin;
173c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-dll_view",&flg,NULL);CHKERRQ(ierr);
174d44a1e48SBarry Smith   if (flg) { ierr = PetscDLLibraryPrintPath(PetscDLLibrariesLoaded);CHKERRQ(ierr); }
175d44a1e48SBarry Smith   ierr = PetscDLLibraryClose(PetscDLLibrariesLoaded);CHKERRQ(ierr);
176a297a907SKarl Rupp 
177acff04ddSBarry Smith #if defined(PETSC_HAVE_THREADSAFETY)
178acff04ddSBarry Smith   ierr = PetscCommDestroy(&PETSC_COMM_SELF_INNER);CHKERRQ(ierr);
179acff04ddSBarry Smith   ierr = PetscCommDestroy(&PETSC_COMM_WORLD_INNER);CHKERRQ(ierr);
180acff04ddSBarry Smith #endif
181acff04ddSBarry Smith 
18202c9f0b5SLisandro Dalcin   PetscDLLibrariesLoaded = NULL;
183e5c89e4eSSatish Balay   PetscFunctionReturn(0);
184e5c89e4eSSatish Balay }
185e5c89e4eSSatish Balay 
186e5c89e4eSSatish Balay /* ------------------------------------------------------------------------------*/
187140e18c1SBarry Smith struct _n_PetscFunctionList {
188e5c89e4eSSatish Balay   void              (*routine)(void);    /* the routine */
189e5c89e4eSSatish Balay   char              *name;               /* string to identify routine */
190140e18c1SBarry Smith   PetscFunctionList next;                /* next pointer */
191140e18c1SBarry Smith   PetscFunctionList next_list;           /* used to maintain list of all lists for freeing */
192e5c89e4eSSatish Balay };
193e5c89e4eSSatish Balay 
194e5c89e4eSSatish Balay /*
195140e18c1SBarry Smith      Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones.
196e5c89e4eSSatish Balay */
19702c9f0b5SLisandro Dalcin static PetscFunctionList dlallhead = NULL;
198e5c89e4eSSatish Balay 
199a240a19fSJed Brown /*MC
200140e18c1SBarry Smith    PetscFunctionListAdd - Given a routine and a string id, saves that routine in the
201e5c89e4eSSatish Balay    specified registry.
202e5c89e4eSSatish Balay 
203a240a19fSJed Brown    Synopsis:
204aaa7dc30SBarry Smith    #include <petscsys.h>
205b9fb364aSBarry Smith    PetscErrorCode PetscFunctionListAdd(PetscFunctionList *flist,const char name[],void (*fptr)(void))
206a240a19fSJed Brown 
207d4349b43SBarry Smith    Not Collective
208e5c89e4eSSatish Balay 
209e5c89e4eSSatish Balay    Input Parameters:
210b9fb364aSBarry Smith +  flist - pointer to function list object
211e5c89e4eSSatish Balay .  name - string to identify routine
212a240a19fSJed Brown -  fptr - function pointer
213e5c89e4eSSatish Balay 
214e5c89e4eSSatish Balay    Notes:
215a240a19fSJed Brown    To remove a registered routine, pass in a NULL fptr.
216e5c89e4eSSatish Balay 
217e5c89e4eSSatish Balay    Users who wish to register new classes for use by a particular PETSc
218e5c89e4eSSatish Balay    component (e.g., SNES) should generally call the registration routine
2191c84c290SBarry Smith    for that particular component (e.g., SNESRegister()) instead of
220140e18c1SBarry Smith    calling PetscFunctionListAdd() directly.
221e5c89e4eSSatish Balay 
222e5c89e4eSSatish Balay     Level: developer
223e5c89e4eSSatish Balay 
2241c84c290SBarry Smith .seealso: PetscFunctionListDestroy(), SNESRegister(), KSPRegister(),
225a240a19fSJed Brown           PCRegister(), TSRegister(), PetscFunctionList, PetscObjectComposeFunction()
226a240a19fSJed Brown M*/
227a240a19fSJed Brown PETSC_EXTERN PetscErrorCode PetscFunctionListAdd_Private(PetscFunctionList *fl,const char name[],void (*fnc)(void))
228e5c89e4eSSatish Balay {
229140e18c1SBarry Smith   PetscFunctionList entry,ne;
230e5c89e4eSSatish Balay   PetscErrorCode    ierr;
231e5c89e4eSSatish Balay 
232e5c89e4eSSatish Balay   PetscFunctionBegin;
233e5c89e4eSSatish Balay   if (!*fl) {
234b00a9115SJed Brown     ierr           = PetscNew(&entry);CHKERRQ(ierr);
235e5c89e4eSSatish Balay     ierr           = PetscStrallocpy(name,&entry->name);CHKERRQ(ierr);
236e5c89e4eSSatish Balay     entry->routine = fnc;
23702c9f0b5SLisandro Dalcin     entry->next    = NULL;
238e5c89e4eSSatish Balay     *fl            = entry;
239e5c89e4eSSatish Balay 
24076bd3646SJed Brown     if (PetscDefined(USE_DEBUG)) {
241e5c89e4eSSatish Balay       /* add this new list to list of all lists */
242e5c89e4eSSatish Balay       if (!dlallhead) {
243e5c89e4eSSatish Balay         dlallhead        = *fl;
24402c9f0b5SLisandro Dalcin         (*fl)->next_list = NULL;
245e5c89e4eSSatish Balay       } else {
246e5c89e4eSSatish Balay         ne               = dlallhead;
247e5c89e4eSSatish Balay         dlallhead        = *fl;
248e5c89e4eSSatish Balay         (*fl)->next_list = ne;
249e5c89e4eSSatish Balay       }
25076bd3646SJed Brown     }
251a8a6328fSBarry Smith 
252e5c89e4eSSatish Balay   } else {
253e5c89e4eSSatish Balay     /* search list to see if it is already there */
254e5c89e4eSSatish Balay     ne = *fl;
255e5c89e4eSSatish Balay     while (ne) {
256ace3abfcSBarry Smith       PetscBool founddup;
257e5c89e4eSSatish Balay 
258e5c89e4eSSatish Balay       ierr = PetscStrcmp(ne->name,name,&founddup);CHKERRQ(ierr);
259e5c89e4eSSatish Balay       if (founddup) { /* found duplicate */
260e5c89e4eSSatish Balay         ne->routine = fnc;
261e5c89e4eSSatish Balay         PetscFunctionReturn(0);
262e5c89e4eSSatish Balay       }
263a297a907SKarl Rupp       if (ne->next) ne = ne->next;
264a297a907SKarl Rupp       else break;
265e5c89e4eSSatish Balay     }
266e5c89e4eSSatish Balay     /* create new entry and add to end of list */
267b00a9115SJed Brown     ierr           = PetscNew(&entry);CHKERRQ(ierr);
268e5c89e4eSSatish Balay     ierr           = PetscStrallocpy(name,&entry->name);CHKERRQ(ierr);
269e5c89e4eSSatish Balay     entry->routine = fnc;
27002c9f0b5SLisandro Dalcin     entry->next    = NULL;
271e5c89e4eSSatish Balay     ne->next       = entry;
272e5c89e4eSSatish Balay   }
273e5c89e4eSSatish Balay   PetscFunctionReturn(0);
274e5c89e4eSSatish Balay }
275e5c89e4eSSatish Balay 
276e5c89e4eSSatish Balay /*@
277140e18c1SBarry Smith     PetscFunctionListDestroy - Destroys a list of registered routines.
278e5c89e4eSSatish Balay 
279e5c89e4eSSatish Balay     Input Parameter:
280e5c89e4eSSatish Balay .   fl  - pointer to list
281e5c89e4eSSatish Balay 
282e5c89e4eSSatish Balay     Level: developer
283e5c89e4eSSatish Balay 
284a240a19fSJed Brown .seealso: PetscFunctionListAdd(), PetscFunctionList
285e5c89e4eSSatish Balay @*/
286140e18c1SBarry Smith PetscErrorCode  PetscFunctionListDestroy(PetscFunctionList *fl)
287e5c89e4eSSatish Balay {
288140e18c1SBarry Smith   PetscFunctionList next,entry,tmp = dlallhead;
289e5c89e4eSSatish Balay   PetscErrorCode    ierr;
290e5c89e4eSSatish Balay 
291e5c89e4eSSatish Balay   PetscFunctionBegin;
2921441b1d3SBarry Smith   if (!*fl) PetscFunctionReturn(0);
293e5c89e4eSSatish Balay 
294e5c89e4eSSatish Balay   /*
2959dddd249SSatish Balay        Remove this entry from the main DL list (if it is in it)
296e5c89e4eSSatish Balay   */
2971441b1d3SBarry Smith   if (dlallhead == *fl) {
298a297a907SKarl Rupp     if (dlallhead->next_list) dlallhead = dlallhead->next_list;
29937e93019SBarry Smith     else dlallhead = NULL;
30037e93019SBarry Smith   } else if (tmp) {
3011441b1d3SBarry Smith     while (tmp->next_list != *fl) {
302e5c89e4eSSatish Balay       tmp = tmp->next_list;
303e5c89e4eSSatish Balay       if (!tmp->next_list) break;
304e5c89e4eSSatish Balay     }
305e5c89e4eSSatish Balay     if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
306e5c89e4eSSatish Balay   }
307e5c89e4eSSatish Balay 
308e5c89e4eSSatish Balay   /* free this list */
3091441b1d3SBarry Smith   entry = *fl;
310e5c89e4eSSatish Balay   while (entry) {
311e5c89e4eSSatish Balay     next  = entry->next;
312e5c89e4eSSatish Balay     ierr  = PetscFree(entry->name);CHKERRQ(ierr);
313e5c89e4eSSatish Balay     ierr  = PetscFree(entry);CHKERRQ(ierr);
314e5c89e4eSSatish Balay     entry = next;
315e5c89e4eSSatish Balay   }
31602c9f0b5SLisandro Dalcin   *fl = NULL;
317e5c89e4eSSatish Balay   PetscFunctionReturn(0);
318e5c89e4eSSatish Balay }
319e5c89e4eSSatish Balay 
320e5c89e4eSSatish Balay /*
32137e93019SBarry Smith    Print any PetscFunctionLists that have not be destroyed
322e5c89e4eSSatish Balay */
32337e93019SBarry Smith PetscErrorCode  PetscFunctionListPrintAll(void)
324e5c89e4eSSatish Balay {
32537e93019SBarry Smith   PetscFunctionList tmp = dlallhead;
326e5c89e4eSSatish Balay   PetscErrorCode    ierr;
327e5c89e4eSSatish Balay 
328e5c89e4eSSatish Balay   PetscFunctionBegin;
32937e93019SBarry Smith   if (tmp) {
33037e93019SBarry Smith     ierr = PetscPrintf(PETSC_COMM_WORLD,"The following PetscFunctionLists were not destroyed\n");CHKERRQ(ierr);
331e5c89e4eSSatish Balay   }
33237e93019SBarry Smith   while (tmp) {
33337e93019SBarry Smith     ierr = PetscPrintf(PETSC_COMM_WORLD,"%s \n",tmp->name);CHKERRQ(ierr);
33437e93019SBarry Smith     tmp = tmp->next_list;
33537e93019SBarry Smith   }
336e5c89e4eSSatish Balay   PetscFunctionReturn(0);
337e5c89e4eSSatish Balay }
338e5c89e4eSSatish Balay 
3391c9cd337SJed Brown /*MC
3401c9cd337SJed Brown     PetscFunctionListFind - Find function registered under given name
3411c9cd337SJed Brown 
3421c9cd337SJed Brown     Synopsis:
343aaa7dc30SBarry Smith     #include <petscsys.h>
3441c9cd337SJed Brown     PetscErrorCode PetscFunctionListFind(PetscFunctionList flist,const char name[],void (**fptr)(void))
345e5c89e4eSSatish Balay 
346e5c89e4eSSatish Balay     Input Parameters:
3471c9cd337SJed Brown +   flist   - pointer to list
3481c9cd337SJed Brown -   name - name registered for the function
349e5c89e4eSSatish Balay 
350e5c89e4eSSatish Balay     Output Parameters:
3511c9cd337SJed Brown .   fptr - the function pointer if name was found, else NULL
352e5c89e4eSSatish Balay 
353e5c89e4eSSatish Balay     Level: developer
354e5c89e4eSSatish Balay 
3551c9cd337SJed Brown .seealso: PetscFunctionListAdd(), PetscFunctionList, PetscObjectQueryFunction()
3561c9cd337SJed Brown M*/
3571c9cd337SJed Brown PETSC_EXTERN PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl,const char name[],void (**r)(void))
358e5c89e4eSSatish Balay {
359140e18c1SBarry Smith   PetscFunctionList entry = fl;
360e5c89e4eSSatish Balay   PetscErrorCode    ierr;
361bdf89e91SBarry Smith   PetscBool         flg;
362e5c89e4eSSatish Balay 
363e5c89e4eSSatish Balay   PetscFunctionBegin;
364e32f2f54SBarry Smith   if (!name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Trying to find routine with null name");
365e5c89e4eSSatish Balay 
36602c9f0b5SLisandro Dalcin   *r = NULL;
367e5c89e4eSSatish Balay   while (entry) {
368bdf89e91SBarry Smith     ierr = PetscStrcmp(name,entry->name,&flg);CHKERRQ(ierr);
369bdf89e91SBarry Smith     if (flg) {
370e5c89e4eSSatish Balay       *r   = entry->routine;
371e5c89e4eSSatish Balay       PetscFunctionReturn(0);
372e5c89e4eSSatish Balay     }
373e5c89e4eSSatish Balay     entry = entry->next;
374e5c89e4eSSatish Balay   }
375e5c89e4eSSatish Balay   PetscFunctionReturn(0);
376e5c89e4eSSatish Balay }
377e5c89e4eSSatish Balay 
378e5c89e4eSSatish Balay /*@
379140e18c1SBarry Smith    PetscFunctionListView - prints out contents of an PetscFunctionList
380e5c89e4eSSatish Balay 
381e5c89e4eSSatish Balay    Collective over MPI_Comm
382e5c89e4eSSatish Balay 
383e5c89e4eSSatish Balay    Input Parameters:
384e5c89e4eSSatish Balay +  list - the list of functions
385e5c89e4eSSatish Balay -  viewer - currently ignored
386e5c89e4eSSatish Balay 
387e5c89e4eSSatish Balay    Level: developer
388e5c89e4eSSatish Balay 
389a240a19fSJed Brown .seealso: PetscFunctionListAdd(), PetscFunctionListPrintTypes(), PetscFunctionList
390e5c89e4eSSatish Balay @*/
391140e18c1SBarry Smith PetscErrorCode  PetscFunctionListView(PetscFunctionList list,PetscViewer viewer)
392e5c89e4eSSatish Balay {
393e5c89e4eSSatish Balay   PetscErrorCode ierr;
394ace3abfcSBarry Smith   PetscBool      iascii;
395e5c89e4eSSatish Balay 
396e5c89e4eSSatish Balay   PetscFunctionBegin;
397e5c89e4eSSatish Balay   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
398e5c89e4eSSatish Balay   PetscValidPointer(list,1);
3990700a824SBarry Smith   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
400e5c89e4eSSatish Balay 
401251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
402e32f2f54SBarry Smith   if (!iascii) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ASCII viewer supported");
403e5c89e4eSSatish Balay 
404e5c89e4eSSatish Balay   while (list) {
405bdf89e91SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer," %s\n",list->name);CHKERRQ(ierr);
406e5c89e4eSSatish Balay     list = list->next;
407e5c89e4eSSatish Balay   }
408e5c89e4eSSatish Balay   ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
409e5c89e4eSSatish Balay   PetscFunctionReturn(0);
410e5c89e4eSSatish Balay }
411e5c89e4eSSatish Balay 
412065533a5SJed Brown /*@C
413140e18c1SBarry Smith    PetscFunctionListGet - Gets an array the contains the entries in PetscFunctionList, this is used
414e5c89e4eSSatish Balay          by help etc.
415e5c89e4eSSatish Balay 
416d4349b43SBarry Smith    Not Collective
417e5c89e4eSSatish Balay 
418e5c89e4eSSatish Balay    Input Parameter:
419e5c89e4eSSatish Balay .  list   - list of types
420e5c89e4eSSatish Balay 
421*d8d19677SJose E. Roman    Output Parameters:
422e5c89e4eSSatish Balay +  array - array of names
423e5c89e4eSSatish Balay -  n - length of array
424e5c89e4eSSatish Balay 
425e5c89e4eSSatish Balay    Notes:
426e5c89e4eSSatish Balay        This allocates the array so that must be freed. BUT the individual entries are
427e5c89e4eSSatish Balay     not copied so should not be freed.
428e5c89e4eSSatish Balay 
429e5c89e4eSSatish Balay    Level: developer
430e5c89e4eSSatish Balay 
431a240a19fSJed Brown .seealso: PetscFunctionListAdd(), PetscFunctionList
432e5c89e4eSSatish Balay @*/
433ca1b3570SJed Brown PetscErrorCode  PetscFunctionListGet(PetscFunctionList list,const char ***array,int *n)
434e5c89e4eSSatish Balay {
435e5c89e4eSSatish Balay   PetscErrorCode    ierr;
436e5c89e4eSSatish Balay   PetscInt          count = 0;
437140e18c1SBarry Smith   PetscFunctionList klist = list;
438e5c89e4eSSatish Balay 
439e5c89e4eSSatish Balay   PetscFunctionBegin;
440e5c89e4eSSatish Balay   while (list) {
441e5c89e4eSSatish Balay     list = list->next;
442e5c89e4eSSatish Balay     count++;
443e5c89e4eSSatish Balay   }
444ca1b3570SJed Brown   ierr  = PetscMalloc1(count+1,(char***)array);CHKERRQ(ierr);
445e5c89e4eSSatish Balay   count = 0;
446e5c89e4eSSatish Balay   while (klist) {
447e5c89e4eSSatish Balay     (*array)[count] = klist->name;
448e5c89e4eSSatish Balay     klist           = klist->next;
449e5c89e4eSSatish Balay     count++;
450e5c89e4eSSatish Balay   }
45102c9f0b5SLisandro Dalcin   (*array)[count] = NULL;
452e5c89e4eSSatish Balay   *n              = count+1;
453e5c89e4eSSatish Balay   PetscFunctionReturn(0);
454e5c89e4eSSatish Balay }
455e5c89e4eSSatish Balay 
456e5c89e4eSSatish Balay /*@C
457140e18c1SBarry Smith    PetscFunctionListPrintTypes - Prints the methods available.
458e5c89e4eSSatish Balay 
459e5c89e4eSSatish Balay    Collective over MPI_Comm
460e5c89e4eSSatish Balay 
461e5c89e4eSSatish Balay    Input Parameters:
462e5c89e4eSSatish Balay +  comm   - the communicator (usually MPI_COMM_WORLD)
463e5c89e4eSSatish Balay .  fd     - file to print to, usually stdout
464e5c89e4eSSatish Balay .  prefix - prefix to prepend to name (optional)
465e5c89e4eSSatish Balay .  name   - option string (for example, "-ksp_type")
466e5c89e4eSSatish Balay .  text - short description of the object (for example, "Krylov solvers")
467e5c89e4eSSatish Balay .  man - name of manual page that discusses the object (for example, "KSPCreate")
4683cc1e11dSBarry Smith .  list   - list of types
46944ef3d73SBarry Smith .  def - default (current) value
47044ef3d73SBarry Smith -  newv - new value
471e5c89e4eSSatish Balay 
472e5c89e4eSSatish Balay    Level: developer
473e5c89e4eSSatish Balay 
474a240a19fSJed Brown .seealso: PetscFunctionListAdd(), PetscFunctionList
475e5c89e4eSSatish Balay @*/
47644ef3d73SBarry Smith 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[])
477e5c89e4eSSatish Balay {
478e5c89e4eSSatish Balay   PetscErrorCode ierr;
479e5c89e4eSSatish Balay   char           p[64];
480e5c89e4eSSatish Balay 
481e5c89e4eSSatish Balay   PetscFunctionBegin;
482da9f1d6bSBarry Smith   if (!fd) fd = PETSC_STDOUT;
483e5c89e4eSSatish Balay 
484a126751eSBarry Smith   ierr = PetscStrncpy(p,"-",sizeof(p));CHKERRQ(ierr);
485a126751eSBarry Smith   if (prefix) {ierr = PetscStrlcat(p,prefix,sizeof(p));CHKERRQ(ierr);}
4860e4c290aSBarry Smith   ierr = PetscFPrintf(comm,fd,"  %s%s <now %s : formerly %s>: %s (one of)",p,name+1,newv,def,text);CHKERRQ(ierr);
487e5c89e4eSSatish Balay 
488e5c89e4eSSatish Balay   while (list) {
489e5c89e4eSSatish Balay     ierr = PetscFPrintf(comm,fd," %s",list->name);CHKERRQ(ierr);
490e5c89e4eSSatish Balay     list = list->next;
491e5c89e4eSSatish Balay   }
492e5c89e4eSSatish Balay   ierr = PetscFPrintf(comm,fd," (%s)\n",man);CHKERRQ(ierr);
493e5c89e4eSSatish Balay   PetscFunctionReturn(0);
494e5c89e4eSSatish Balay }
495e5c89e4eSSatish Balay 
496e5c89e4eSSatish Balay /*@
497140e18c1SBarry Smith     PetscFunctionListDuplicate - Creates a new list from a given object list.
498e5c89e4eSSatish Balay 
499e5c89e4eSSatish Balay     Input Parameters:
500e5c89e4eSSatish Balay .   fl   - pointer to list
501e5c89e4eSSatish Balay 
502e5c89e4eSSatish Balay     Output Parameters:
503e5c89e4eSSatish Balay .   nl - the new list (should point to 0 to start, otherwise appends)
504e5c89e4eSSatish Balay 
505e5c89e4eSSatish Balay     Level: developer
506e5c89e4eSSatish Balay 
507140e18c1SBarry Smith .seealso: PetscFunctionList, PetscFunctionListAdd(), PetscFlistDestroy()
508e5c89e4eSSatish Balay 
509e5c89e4eSSatish Balay @*/
510140e18c1SBarry Smith PetscErrorCode  PetscFunctionListDuplicate(PetscFunctionList fl,PetscFunctionList *nl)
511e5c89e4eSSatish Balay {
512e5c89e4eSSatish Balay   PetscErrorCode ierr;
513e5c89e4eSSatish Balay 
514e5c89e4eSSatish Balay   PetscFunctionBegin;
515e5c89e4eSSatish Balay   while (fl) {
516bdf89e91SBarry Smith     ierr = PetscFunctionListAdd(nl,fl->name,fl->routine);CHKERRQ(ierr);
517e5c89e4eSSatish Balay     fl   = fl->next;
518e5c89e4eSSatish Balay   }
519e5c89e4eSSatish Balay   PetscFunctionReturn(0);
520e5c89e4eSSatish Balay }
521