xref: /petsc/src/sys/objects/pinit.c (revision a79482ff88c096eb73b6d30dd972596b036637e0)
1 
2 /*
3    This file defines the initialization of PETSc, including PetscInitialize()
4 */
5 #include <petsc/private/petscimpl.h>        /*I  "petscsys.h"   I*/
6 #include <petscvalgrind.h>
7 #include <petscviewer.h>
8 
9 #if defined(PETSC_HAVE_CUDA)
10 #include <cublas.h>
11 #endif
12 
13 #if defined(PETSC_USE_LOG)
14 extern PetscErrorCode PetscLogBegin_Private(void);
15 #endif
16 
17 #if defined(PETSC_SERIALIZE_FUNCTIONS)
18 PetscFPT PetscFPTData = 0;
19 #endif
20 
21 #if defined(PETSC_HAVE_SAWS)
22 #include <petscviewersaws.h>
23 #endif
24 /* -----------------------------------------------------------------------------------------*/
25 
26 extern FILE *petsc_history;
27 
28 extern PetscErrorCode PetscInitialize_DynamicLibraries(void);
29 extern PetscErrorCode PetscFinalize_DynamicLibraries(void);
30 extern PetscErrorCode PetscFunctionListPrintAll(void);
31 extern PetscErrorCode PetscSequentialPhaseBegin_Private(MPI_Comm,int);
32 extern PetscErrorCode PetscSequentialPhaseEnd_Private(MPI_Comm,int);
33 extern PetscErrorCode PetscCloseHistoryFile(FILE**);
34 
35 /* user may set this BEFORE calling PetscInitialize() */
36 MPI_Comm PETSC_COMM_WORLD = MPI_COMM_NULL;
37 
38 PetscMPIInt Petsc_Counter_keyval   = MPI_KEYVAL_INVALID;
39 PetscMPIInt Petsc_InnerComm_keyval = MPI_KEYVAL_INVALID;
40 PetscMPIInt Petsc_OuterComm_keyval = MPI_KEYVAL_INVALID;
41 
42 /*
43      Declare and set all the string names of the PETSc enums
44 */
45 const char *const PetscBools[]     = {"FALSE","TRUE","PetscBool","PETSC_",0};
46 const char *const PetscCopyModes[] = {"COPY_VALUES","OWN_POINTER","USE_POINTER","PetscCopyMode","PETSC_",0};
47 const char *const PetscDataTypes[] = {"INT","DOUBLE","COMPLEX","LONG","SHORT","FLOAT",
48                                       "CHAR","LOGICAL","ENUM","BOOL","LONGDOUBLE","OBJECT","FUNCTION","PetscDataType","PETSC_",0};
49 
50 PetscBool PetscPreLoadingUsed = PETSC_FALSE;
51 PetscBool PetscPreLoadingOn   = PETSC_FALSE;
52 
53 PetscInt PetscHotRegionDepth;
54 
55 /*
56        Checks the options database for initializations related to the
57     PETSc components
58 */
59 #undef __FUNCT__
60 #define __FUNCT__ "PetscOptionsCheckInitial_Components"
61 PetscErrorCode  PetscOptionsCheckInitial_Components(void)
62 {
63   PetscBool      flg1;
64   PetscErrorCode ierr;
65 
66   PetscFunctionBegin;
67   ierr = PetscOptionsHasName(NULL,"-help",&flg1);CHKERRQ(ierr);
68   if (flg1) {
69 #if defined(PETSC_USE_LOG)
70     MPI_Comm comm = PETSC_COMM_WORLD;
71     ierr = (*PetscHelpPrintf)(comm,"------Additional PETSc component options--------\n");CHKERRQ(ierr);
72     ierr = (*PetscHelpPrintf)(comm," -log_summary_exclude: <vec,mat,pc.ksp,snes>\n");CHKERRQ(ierr);
73     ierr = (*PetscHelpPrintf)(comm," -info_exclude: <null,vec,mat,pc,ksp,snes,ts>\n");CHKERRQ(ierr);
74     ierr = (*PetscHelpPrintf)(comm,"-----------------------------------------------\n");CHKERRQ(ierr);
75 #endif
76   }
77   PetscFunctionReturn(0);
78 }
79 
80 #undef __FUNCT__
81 #define __FUNCT__ "PetscInitializeNoPointers"
82 /*
83       PetscInitializeNoPointers - Calls PetscInitialize() from C/C++ without the pointers to argc and args
84 
85    Collective
86 
87    Level: advanced
88 
89     Notes: this is called only by the PETSc MATLAB and Julia interface. Even though it might start MPI it sets the flag to
90      indicate that it did NOT start MPI so that the PetscFinalize() does not end MPI, thus allowing PetscInitialize() to
91      be called multiple times from MATLAB and Julia without the problem of trying to initialize MPI more than once.
92 
93      Turns off PETSc signal handling because that can interact with MATLAB's signal handling causing random crashes.
94 
95 .seealso: PetscInitialize(), PetscInitializeFortran(), PetscInitializeNoArguments()
96 */
97 PetscErrorCode  PetscInitializeNoPointers(int argc,char **args,const char *filename,const char *help)
98 {
99   PetscErrorCode ierr;
100   int            myargc   = argc;
101   char           **myargs = args;
102 
103   PetscFunctionBegin;
104   ierr = PetscInitialize(&myargc,&myargs,filename,help);CHKERRQ(ierr);
105   ierr = PetscPopSignalHandler();CHKERRQ(ierr);
106   PetscBeganMPI = PETSC_FALSE;
107   PetscFunctionReturn(ierr);
108 }
109 
110 #undef __FUNCT__
111 #define __FUNCT__ "PetscGetPETSC_COMM_SELF"
112 /*
113       Used by MATLAB and Julia interface to get communicator
114 */
115 PetscErrorCode  PetscGetPETSC_COMM_SELF(MPI_Comm *comm)
116 {
117   PetscFunctionBegin;
118   *comm = PETSC_COMM_SELF;
119   PetscFunctionReturn(0);
120 }
121 
122 #undef __FUNCT__
123 #define __FUNCT__ "PetscInitializeNoArguments"
124 /*@C
125       PetscInitializeNoArguments - Calls PetscInitialize() from C/C++ without
126         the command line arguments.
127 
128    Collective
129 
130    Level: advanced
131 
132 .seealso: PetscInitialize(), PetscInitializeFortran()
133 @*/
134 PetscErrorCode  PetscInitializeNoArguments(void)
135 {
136   PetscErrorCode ierr;
137   int            argc   = 0;
138   char           **args = 0;
139 
140   PetscFunctionBegin;
141   ierr = PetscInitialize(&argc,&args,NULL,NULL);
142   PetscFunctionReturn(ierr);
143 }
144 
145 #undef __FUNCT__
146 #define __FUNCT__ "PetscInitialized"
147 /*@
148       PetscInitialized - Determine whether PETSc is initialized.
149 
150    Level: beginner
151 
152 .seealso: PetscInitialize(), PetscInitializeNoArguments(), PetscInitializeFortran()
153 @*/
154 PetscErrorCode PetscInitialized(PetscBool  *isInitialized)
155 {
156   *isInitialized = PetscInitializeCalled;
157   return 0;
158 }
159 
160 #undef __FUNCT__
161 #define __FUNCT__ "PetscFinalized"
162 /*@
163       PetscFinalized - Determine whether PetscFinalize() has been called yet
164 
165    Level: developer
166 
167 .seealso: PetscInitialize(), PetscInitializeNoArguments(), PetscInitializeFortran()
168 @*/
169 PetscErrorCode  PetscFinalized(PetscBool  *isFinalized)
170 {
171   *isFinalized = PetscFinalizeCalled;
172   return 0;
173 }
174 
175 extern PetscErrorCode PetscOptionsCheckInitial_Private(void);
176 
177 /*
178        This function is the MPI reduction operation used to compute the sum of the
179    first half of the datatype and the max of the second half.
180 */
181 MPI_Op PetscMaxSum_Op = 0;
182 
183 #undef __FUNCT__
184 #define __FUNCT__ "PetscMaxSum_Local"
185 PETSC_EXTERN void MPIAPI PetscMaxSum_Local(void *in,void *out,int *cnt,MPI_Datatype *datatype)
186 {
187   PetscInt *xin = (PetscInt*)in,*xout = (PetscInt*)out,i,count = *cnt;
188 
189   PetscFunctionBegin;
190   if (*datatype != MPIU_2INT) {
191     (*PetscErrorPrintf)("Can only handle MPIU_2INT data types");
192     MPI_Abort(MPI_COMM_WORLD,1);
193   }
194 
195   for (i=0; i<count; i++) {
196     xout[2*i]    = PetscMax(xout[2*i],xin[2*i]);
197     xout[2*i+1] += xin[2*i+1];
198   }
199   PetscFunctionReturnVoid();
200 }
201 
202 /*
203     Returns the max of the first entry owned by this processor and the
204 sum of the second entry.
205 
206     The reason sizes[2*i] contains lengths sizes[2*i+1] contains flag of 1 if length is nonzero
207 is so that the PetscMaxSum_Op() can set TWO values, if we passed in only sizes[i] with lengths
208 there would be no place to store the both needed results.
209 */
210 #undef __FUNCT__
211 #define __FUNCT__ "PetscMaxSum"
212 PetscErrorCode  PetscMaxSum(MPI_Comm comm,const PetscInt sizes[],PetscInt *max,PetscInt *sum)
213 {
214   PetscErrorCode ierr;
215 
216   PetscFunctionBegin;
217 #if defined(PETSC_HAVE_MPI_REDUCE_SCATTER_BLOCK)
218   {
219     struct {PetscInt max,sum;} work;
220     ierr = MPI_Reduce_scatter_block((void*)sizes,&work,1,MPIU_2INT,PetscMaxSum_Op,comm);CHKERRQ(ierr);
221     *max = work.max;
222     *sum = work.sum;
223   }
224 #else
225   {
226     PetscMPIInt    size,rank;
227     struct {PetscInt max,sum;} *work;
228     ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
229     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
230     ierr = PetscMalloc1(size,&work);CHKERRQ(ierr);
231     ierr = MPI_Allreduce((void*)sizes,work,size,MPIU_2INT,PetscMaxSum_Op,comm);CHKERRQ(ierr);
232     *max = work[rank].max;
233     *sum = work[rank].sum;
234     ierr = PetscFree(work);CHKERRQ(ierr);
235   }
236 #endif
237   PetscFunctionReturn(0);
238 }
239 
240 /* ----------------------------------------------------------------------------*/
241 
242 #if (defined(PETSC_HAVE_COMPLEX) && !defined(PETSC_HAVE_MPI_C_DOUBLE_COMPLEX)) || defined(PETSC_USE_REAL___FLOAT128)
243 MPI_Op MPIU_SUM = 0;
244 
245 #undef __FUNCT__
246 #define __FUNCT__ "PetscSum_Local"
247 PETSC_EXTERN void PetscSum_Local(void *in,void *out,PetscMPIInt *cnt,MPI_Datatype *datatype)
248 {
249   PetscInt i,count = *cnt;
250 
251   PetscFunctionBegin;
252   if (*datatype == MPIU_REAL) {
253     PetscReal *xin = (PetscReal*)in,*xout = (PetscReal*)out;
254     for (i=0; i<count; i++) xout[i] += xin[i];
255   }
256 #if defined(PETSC_HAVE_COMPLEX)
257   else if (*datatype == MPIU_COMPLEX) {
258     PetscComplex *xin = (PetscComplex*)in,*xout = (PetscComplex*)out;
259     for (i=0; i<count; i++) xout[i] += xin[i];
260   }
261 #endif
262   else {
263     (*PetscErrorPrintf)("Can only handle MPIU_REAL or MPIU_COMPLEX data types");
264     MPI_Abort(MPI_COMM_WORLD,1);
265   }
266   PetscFunctionReturnVoid();
267 }
268 #endif
269 
270 #if defined(PETSC_USE_REAL___FLOAT128)
271 MPI_Op MPIU_MAX = 0;
272 MPI_Op MPIU_MIN = 0;
273 
274 #undef __FUNCT__
275 #define __FUNCT__ "PetscMax_Local"
276 PETSC_EXTERN void PetscMax_Local(void *in,void *out,PetscMPIInt *cnt,MPI_Datatype *datatype)
277 {
278   PetscInt i,count = *cnt;
279 
280   PetscFunctionBegin;
281   if (*datatype == MPIU_REAL) {
282     PetscReal *xin = (PetscReal*)in,*xout = (PetscReal*)out;
283     for (i=0; i<count; i++) xout[i] = PetscMax(xout[i],xin[i]);
284   }
285 #if defined(PETSC_HAVE_COMPLEX)
286   else if (*datatype == MPIU_COMPLEX) {
287     PetscComplex *xin = (PetscComplex*)in,*xout = (PetscComplex*)out;
288     for (i=0; i<count; i++) {
289       xout[i] = PetscRealPartComplex(xout[i])<PetscRealPartComplex(xin[i]) ? xin[i] : xout[i];
290     }
291   }
292 #endif
293   else {
294     (*PetscErrorPrintf)("Can only handle MPIU_REAL or MPIU_COMPLEX data types");
295     MPI_Abort(MPI_COMM_WORLD,1);
296   }
297   PetscFunctionReturnVoid();
298 }
299 
300 #undef __FUNCT__
301 #define __FUNCT__ "PetscMin_Local"
302 PETSC_EXTERN void PetscMin_Local(void *in,void *out,PetscMPIInt *cnt,MPI_Datatype *datatype)
303 {
304   PetscInt    i,count = *cnt;
305 
306   PetscFunctionBegin;
307   if (*datatype == MPIU_REAL) {
308     PetscReal *xin = (PetscReal*)in,*xout = (PetscReal*)out;
309     for (i=0; i<count; i++) xout[i] = PetscMin(xout[i],xin[i]);
310   }
311 #if defined(PETSC_HAVE_COMPLEX)
312   else if (*datatype == MPIU_COMPLEX) {
313     PetscComplex *xin = (PetscComplex*)in,*xout = (PetscComplex*)out;
314     for (i=0; i<count; i++) {
315       xout[i] = PetscRealPartComplex(xout[i])>PetscRealPartComplex(xin[i]) ? xin[i] : xout[i];
316     }
317   }
318 #endif
319   else {
320     (*PetscErrorPrintf)("Can only handle MPIU_REAL or MPIU_SCALAR data (i.e. double or complex) types");
321     MPI_Abort(MPI_COMM_WORLD,1);
322   }
323   PetscFunctionReturnVoid();
324 }
325 #endif
326 
327 #undef __FUNCT__
328 #define __FUNCT__ "Petsc_DelCounter"
329 /*
330    Private routine to delete internal tag/name counter storage when a communicator is freed.
331 
332    This is called by MPI, not by users. This is called by MPI_Comm_free() when the communicator that has this  data as an attribute is freed.
333 
334    Note: this is declared extern "C" because it is passed to MPI_Keyval_create()
335 
336 */
337 PETSC_EXTERN PetscMPIInt MPIAPI Petsc_DelCounter(MPI_Comm comm,PetscMPIInt keyval,void *count_val,void *extra_state)
338 {
339   PetscErrorCode ierr;
340 
341   PetscFunctionBegin;
342   ierr = PetscInfo1(0,"Deleting counter data in an MPI_Comm %ld\n",(long)comm);if (ierr) PetscFunctionReturn((PetscMPIInt)ierr);
343   ierr = PetscFree(count_val);if (ierr) PetscFunctionReturn((PetscMPIInt)ierr);
344   PetscFunctionReturn(MPI_SUCCESS);
345 }
346 
347 #undef __FUNCT__
348 #define __FUNCT__ "Petsc_DelComm_Outer"
349 /*
350   This is invoked on the outer comm as a result of either PetscCommDestroy() (via MPI_Attr_delete) or when the user
351   calls MPI_Comm_free().
352 
353   This is the only entry point for breaking the links between inner and outer comms.
354 
355   This is called by MPI, not by users. This is called when MPI_Comm_free() is called on the communicator.
356 
357   Note: this is declared extern "C" because it is passed to MPI_Keyval_create()
358 
359 */
360 PETSC_EXTERN PetscMPIInt MPIAPI Petsc_DelComm_Outer(MPI_Comm comm,PetscMPIInt keyval,void *attr_val,void *extra_state)
361 {
362   PetscErrorCode ierr;
363   PetscMPIInt    flg;
364   union {MPI_Comm comm; void *ptr;} icomm,ocomm;
365 
366   PetscFunctionBegin;
367   if (keyval != Petsc_InnerComm_keyval) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Unexpected keyval");
368   icomm.ptr = attr_val;
369 
370   ierr = MPI_Attr_get(icomm.comm,Petsc_OuterComm_keyval,&ocomm,&flg);CHKERRQ(ierr);
371   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Inner MPI_Comm does not have expected reference to outer comm");
372   if (ocomm.comm != comm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Inner MPI_Comm has reference to non-matching outer comm");
373   ierr = MPI_Attr_delete(icomm.comm,Petsc_OuterComm_keyval);CHKERRQ(ierr); /* Calls Petsc_DelComm_Inner */
374   ierr = PetscInfo1(0,"User MPI_Comm %ld is being freed after removing reference from inner PETSc comm to this outer comm\n",(long)comm);if (ierr) PetscFunctionReturn((PetscMPIInt)ierr);
375   PetscFunctionReturn(MPI_SUCCESS);
376 }
377 
378 #undef __FUNCT__
379 #define __FUNCT__ "Petsc_DelComm_Inner"
380 /*
381  * This is invoked on the inner comm when Petsc_DelComm_Outer calls MPI_Attr_delete.  It should not be reached any other way.
382  */
383 PETSC_EXTERN PetscMPIInt MPIAPI Petsc_DelComm_Inner(MPI_Comm comm,PetscMPIInt keyval,void *attr_val,void *extra_state)
384 {
385   PetscErrorCode ierr;
386 
387   PetscFunctionBegin;
388   ierr = PetscInfo1(0,"Removing reference to PETSc communicator embedded in a user MPI_Comm %ld\n",(long)comm);if (ierr) PetscFunctionReturn((PetscMPIInt)ierr);
389   PetscFunctionReturn(MPI_SUCCESS);
390 }
391 
392 #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
393 #if !defined(PETSC_WORDS_BIGENDIAN)
394 PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype,MPI_Aint*,void*);
395 PETSC_EXTERN PetscMPIInt PetscDataRep_read_conv_fn(void*, MPI_Datatype,PetscMPIInt,void*,MPI_Offset,void*);
396 PETSC_EXTERN PetscMPIInt PetscDataRep_write_conv_fn(void*, MPI_Datatype,PetscMPIInt,void*,MPI_Offset,void*);
397 #endif
398 #endif
399 
400 int  PetscGlobalArgc   = 0;
401 char **PetscGlobalArgs = 0;
402 PetscSegBuffer PetscCitationsList;
403 
404 #undef __FUNCT__
405 #define __FUNCT__ "PetscCitationsInitialize"
406 PetscErrorCode PetscCitationsInitialize()
407 {
408   PetscErrorCode ierr;
409 
410   PetscFunctionBegin;
411   ierr = PetscSegBufferCreate(1,10000,&PetscCitationsList);CHKERRQ(ierr);
412   ierr = PetscCitationsRegister("@TechReport{petsc-user-ref,\n  Author = {Satish Balay and Shrirang Abhyankar and Mark F. Adams and Jed Brown and Peter Brune\n            and Kris Buschelman and Lisandro Dalcin and Victor Eijkhout and William D. Gropp\n            and Dinesh Kaushik and Matthew G. Knepley\n            and Lois Curfman McInnes and Karl Rupp and Barry F. Smith\n            and Stefano Zampini and Hong Zhang},\n  Title = {{PETS}c Users Manual},\n  Number = {ANL-95/11 - Revision 3.6},\n  Institution = {Argonne National Laboratory},\n  Year = {2015}\n}\n",NULL);CHKERRQ(ierr);
413   ierr = PetscCitationsRegister("@InProceedings{petsc-efficient,\n  Author = {Satish Balay and William D. Gropp and Lois Curfman McInnes and Barry F. Smith},\n  Title = {Efficient Management of Parallelism in Object Oriented Numerical Software Libraries},\n  Booktitle = {Modern Software Tools in Scientific Computing},\n  Editor = {E. Arge and A. M. Bruaset and H. P. Langtangen},\n  Pages = {163--202},\n  Publisher = {Birkh{\\\"{a}}user Press},\n  Year = {1997}\n}\n",NULL);CHKERRQ(ierr);
414   PetscFunctionReturn(0);
415 }
416 
417 #undef __FUNCT__
418 #define __FUNCT__ "PetscGetArgs"
419 /*@C
420    PetscGetArgs - Allows you to access the raw command line arguments anywhere
421      after PetscInitialize() is called but before PetscFinalize().
422 
423    Not Collective
424 
425    Output Parameters:
426 +  argc - count of number of command line arguments
427 -  args - the command line arguments
428 
429    Level: intermediate
430 
431    Notes:
432       This is usually used to pass the command line arguments into other libraries
433    that are called internally deep in PETSc or the application.
434 
435       The first argument contains the program name as is normal for C arguments.
436 
437    Concepts: command line arguments
438 
439 .seealso: PetscFinalize(), PetscInitializeFortran(), PetscGetArguments()
440 
441 @*/
442 PetscErrorCode  PetscGetArgs(int *argc,char ***args)
443 {
444   PetscFunctionBegin;
445   if (!PetscInitializeCalled && PetscFinalizeCalled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"You must call after PetscInitialize() but before PetscFinalize()");
446   *argc = PetscGlobalArgc;
447   *args = PetscGlobalArgs;
448   PetscFunctionReturn(0);
449 }
450 
451 #undef __FUNCT__
452 #define __FUNCT__ "PetscGetArguments"
453 /*@C
454    PetscGetArguments - Allows you to access the  command line arguments anywhere
455      after PetscInitialize() is called but before PetscFinalize().
456 
457    Not Collective
458 
459    Output Parameters:
460 .  args - the command line arguments
461 
462    Level: intermediate
463 
464    Notes:
465       This does NOT start with the program name and IS null terminated (final arg is void)
466 
467    Concepts: command line arguments
468 
469 .seealso: PetscFinalize(), PetscInitializeFortran(), PetscGetArgs(), PetscFreeArguments()
470 
471 @*/
472 PetscErrorCode  PetscGetArguments(char ***args)
473 {
474   PetscInt       i,argc = PetscGlobalArgc;
475   PetscErrorCode ierr;
476 
477   PetscFunctionBegin;
478   if (!PetscInitializeCalled && PetscFinalizeCalled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"You must call after PetscInitialize() but before PetscFinalize()");
479   if (!argc) {*args = 0; PetscFunctionReturn(0);}
480   ierr = PetscMalloc1(argc,args);CHKERRQ(ierr);
481   for (i=0; i<argc-1; i++) {
482     ierr = PetscStrallocpy(PetscGlobalArgs[i+1],&(*args)[i]);CHKERRQ(ierr);
483   }
484   (*args)[argc-1] = 0;
485   PetscFunctionReturn(0);
486 }
487 
488 #undef __FUNCT__
489 #define __FUNCT__ "PetscFreeArguments"
490 /*@C
491    PetscFreeArguments - Frees the memory obtained with PetscGetArguments()
492 
493    Not Collective
494 
495    Output Parameters:
496 .  args - the command line arguments
497 
498    Level: intermediate
499 
500    Concepts: command line arguments
501 
502 .seealso: PetscFinalize(), PetscInitializeFortran(), PetscGetArgs(), PetscGetArguments()
503 
504 @*/
505 PetscErrorCode  PetscFreeArguments(char **args)
506 {
507   PetscInt       i = 0;
508   PetscErrorCode ierr;
509 
510   PetscFunctionBegin;
511   if (!args) PetscFunctionReturn(0);
512   while (args[i]) {
513     ierr = PetscFree(args[i]);CHKERRQ(ierr);
514     i++;
515   }
516   ierr = PetscFree(args);CHKERRQ(ierr);
517   PetscFunctionReturn(0);
518 }
519 
520 #if defined(PETSC_HAVE_SAWS)
521 #include <petscconfiginfo.h>
522 
523 #undef __FUNCT__
524 #define __FUNCT__ "PetscInitializeSAWs"
525 PetscErrorCode  PetscInitializeSAWs(const char help[])
526 {
527   if (!PetscGlobalRank) {
528     char           cert[PETSC_MAX_PATH_LEN],root[PETSC_MAX_PATH_LEN],*intro,programname[64],*appline,*options,version[64];
529     int            port;
530     PetscBool      flg,rootlocal = PETSC_FALSE,flg2;
531     size_t         applinelen,introlen;
532     PetscErrorCode ierr;
533     /* char           sawsurl[256]; */
534 
535     ierr = PetscOptionsHasName(NULL,"-saws_log",&flg);CHKERRQ(ierr);
536     if (flg) {
537       char  sawslog[PETSC_MAX_PATH_LEN];
538 
539       ierr = PetscOptionsGetString(NULL,"-saws_log",sawslog,PETSC_MAX_PATH_LEN,NULL);CHKERRQ(ierr);
540       if (sawslog[0]) {
541         PetscStackCallSAWs(SAWs_Set_Use_Logfile,(sawslog));
542       } else {
543         PetscStackCallSAWs(SAWs_Set_Use_Logfile,(NULL));
544       }
545     }
546     ierr = PetscOptionsGetString(NULL,"-saws_https",cert,PETSC_MAX_PATH_LEN,&flg);CHKERRQ(ierr);
547     if (flg) {
548       PetscStackCallSAWs(SAWs_Set_Use_HTTPS,(cert));
549     }
550     ierr = PetscOptionsGetInt(NULL,"-saws_port",&port,&flg);CHKERRQ(ierr);
551     if (flg) {
552       PetscStackCallSAWs(SAWs_Set_Port,(port));
553     }
554     ierr = PetscOptionsGetString(NULL,"-saws_root",root,PETSC_MAX_PATH_LEN,&flg);CHKERRQ(ierr);
555     if (flg) {
556       PetscStackCallSAWs(SAWs_Set_Document_Root,(root));CHKERRQ(ierr);
557       ierr = PetscStrcmp(root,".",&rootlocal);CHKERRQ(ierr);
558     } else {
559       ierr = PetscOptionsHasName(NULL,"-saws_options",&flg);CHKERRQ(ierr);
560       if (flg) {
561         ierr = PetscStrreplace(PETSC_COMM_WORLD,"${PETSC_DIR}/share/petsc/saws",root,PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
562         PetscStackCallSAWs(SAWs_Set_Document_Root,(root));CHKERRQ(ierr);
563       }
564     }
565     ierr = PetscOptionsHasName(NULL,"-saws_local",&flg2);CHKERRQ(ierr);
566     if (flg2) {
567       char jsdir[PETSC_MAX_PATH_LEN];
568       if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"-saws_local option requires -saws_root option");
569       ierr = PetscSNPrintf(jsdir,PETSC_MAX_PATH_LEN,"%s/js",root);CHKERRQ(ierr);
570       ierr = PetscTestDirectory(jsdir,'r',&flg);CHKERRQ(ierr);
571       if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"-saws_local option requires js directory in root directory");
572       PetscStackCallSAWs(SAWs_Push_Local_Header,());CHKERRQ(ierr);
573     }
574     ierr = PetscGetProgramName(programname,64);CHKERRQ(ierr);
575     ierr = PetscStrlen(help,&applinelen);CHKERRQ(ierr);
576     introlen   = 4096 + applinelen;
577     applinelen += 1024;
578     ierr = PetscMalloc(applinelen,&appline);CHKERRQ(ierr);
579     ierr = PetscMalloc(introlen,&intro);CHKERRQ(ierr);
580 
581     if (rootlocal) {
582       ierr = PetscSNPrintf(appline,applinelen,"%s.c.html",programname);CHKERRQ(ierr);
583       ierr = PetscTestFile(appline,'r',&rootlocal);CHKERRQ(ierr);
584     }
585     ierr = PetscOptionsGetAll(&options);CHKERRQ(ierr);
586     if (rootlocal && help) {
587       ierr = PetscSNPrintf(appline,applinelen,"<center> Running <a href=\"%s.c.html\">%s</a> %s</center><br><center><pre>%s</pre></center><br>\n",programname,programname,options,help);
588     } else if (help) {
589       ierr = PetscSNPrintf(appline,applinelen,"<center>Running %s %s</center><br><center><pre>%s</pre></center><br>",programname,options,help);
590     } else {
591       ierr = PetscSNPrintf(appline,applinelen,"<center> Running %s %s</center><br>\n",programname,options);
592     }
593     ierr = PetscFree(options);CHKERRQ(ierr);
594     ierr = PetscGetVersion(version,sizeof(version));CHKERRQ(ierr);
595     ierr = PetscSNPrintf(intro,introlen,"<body>\n"
596                                     "<center><h2> <a href=\"http://www.mcs.anl.gov/petsc\">PETSc</a> Application Web server powered by <a href=\"https://bitbucket.org/saws/saws\">SAWs</a> </h2></center>\n"
597                                     "<center>This is the default PETSc application dashboard, from it you can access any published PETSc objects or logging data</center><br><center>%s configured with %s</center><br>\n"
598                                     "%s",version,petscconfigureoptions,appline);
599     PetscStackCallSAWs(SAWs_Push_Body,("index.html",0,intro));
600     ierr = PetscFree(intro);CHKERRQ(ierr);
601     ierr = PetscFree(appline);CHKERRQ(ierr);
602     PetscStackCallSAWs(SAWs_Initialize,());
603     /* PetscStackCallSAWs(SAWs_Get_FullURL,(sizeof(sawsurl),sawsurl));
604      ierr = PetscPrintf(PETSC_COMM_WORLD,"Point your browser to %s for SAWs\n",sawsurl);CHKERRQ(ierr); */
605     ierr = PetscCitationsRegister("@TechReport{ saws,\n"
606                                   "  Author = {Matt Otten and Jed Brown and Barry Smith},\n"
607                                   "  Title  = {Scientific Application Web Server (SAWs) Users Manual},\n"
608                                   "  Institution = {Argonne National Laboratory},\n"
609                                   "  Year   = 2013\n}\n",NULL);CHKERRQ(ierr);
610   }
611   PetscFunctionReturn(0);
612 }
613 #endif
614 
615 #undef __FUNCT__
616 #define __FUNCT__ "PetscInitialize"
617 /*@C
618    PetscInitialize - Initializes the PETSc database and MPI.
619    PetscInitialize() calls MPI_Init() if that has yet to be called,
620    so this routine should always be called near the beginning of
621    your program -- usually the very first line!
622 
623    Collective on MPI_COMM_WORLD or PETSC_COMM_WORLD if it has been set
624 
625    Input Parameters:
626 +  argc - count of number of command line arguments
627 .  args - the command line arguments
628 .  file - [optional] PETSc database file, also checks ~username/.petscrc and .petscrc use NULL to not check for
629           code specific file. Use -skip_petscrc in the code specific file to skip the .petscrc files
630 -  help - [optional] Help message to print, use NULL for no message
631 
632    If you wish PETSc code to run ONLY on a subcommunicator of MPI_COMM_WORLD, create that
633    communicator first and assign it to PETSC_COMM_WORLD BEFORE calling PetscInitialize(). Thus if you are running a
634    four process job and two processes will run PETSc and have PetscInitialize() and PetscFinalize() and two process will not,
635    then do this. If ALL processes in the job are using PetscInitialize() and PetscFinalize() then you don't need to do this, even
636    if different subcommunicators of the job are doing different things with PETSc.
637 
638    Options Database Keys:
639 +  -start_in_debugger [noxterm,dbx,xdb,gdb,...] - Starts program in debugger
640 .  -on_error_attach_debugger [noxterm,dbx,xdb,gdb,...] - Starts debugger when error detected
641 .  -on_error_emacs <machinename> causes emacsclient to jump to error file
642 .  -on_error_abort calls abort() when error detected (no traceback)
643 .  -on_error_mpiabort calls MPI_abort() when error detected
644 .  -error_output_stderr prints error messages to stderr instead of the default stdout
645 .  -error_output_none does not print the error messages (but handles errors in the same way as if this was not called)
646 .  -debugger_nodes [node1,node2,...] - Indicates nodes to start in debugger
647 .  -debugger_pause [sleeptime] (in seconds) - Pauses debugger
648 .  -stop_for_debugger - Print message on how to attach debugger manually to
649                         process and wait (-debugger_pause) seconds for attachment
650 .  -malloc - Indicates use of PETSc error-checking malloc (on by default for debug version of libraries)
651 .  -malloc no - Indicates not to use error-checking malloc
652 .  -malloc_debug - check for memory corruption at EVERY malloc or free
653 .  -malloc_dump - prints a list of all unfreed memory at the end of the run
654 .  -malloc_test - like -malloc_dump -malloc_debug, but only active for debugging builds
655 .  -fp_trap - Stops on floating point exceptions (Note that on the
656               IBM RS6000 this slows code by at least a factor of 10.)
657 .  -no_signal_handler - Indicates not to trap error signals
658 .  -shared_tmp - indicates /tmp directory is shared by all processors
659 .  -not_shared_tmp - each processor has own /tmp
660 .  -tmp - alternative name of /tmp directory
661 .  -get_total_flops - returns total flops done by all processors
662 -  -memory_info - Print memory usage at end of run
663 
664    Options Database Keys for Profiling:
665    See Users-Manual: ch_profiling for details.
666 +  -info <optional filename> - Prints verbose information to the screen
667 .  -info_exclude <null,vec,mat,pc,ksp,snes,ts> - Excludes some of the verbose messages
668 .  -log_sync - Log the synchronization in scatters, inner products and norms
669 .  -log_trace [filename] - Print traces of all PETSc calls to the screen (useful to determine where a program
670         hangs without running in the debugger).  See PetscLogTraceBegin().
671 .  -log_summary [filename] - Prints summary of flop and timing information to screen. If the filename is specified the
672         summary is written to the file.  See PetscLogView().
673 .  -log_all [filename] - Logs extensive profiling information  See PetscLogDump().
674 .  -log [filename] - Logs basic profiline information  See PetscLogDump().
675 -  -log_mpe [filename] - Creates a logfile viewable by the utility Jumpshot (in MPICH distribution)
676 
677     Only one of -log_trace, -log_summary, -log_all, -log, or -log_mpe may be used at a time
678 
679    Environmental Variables:
680 +   PETSC_TMP - alternative tmp directory
681 .   PETSC_SHARED_TMP - tmp is shared by all processes
682 .   PETSC_NOT_SHARED_TMP - each process has its own private tmp
683 .   PETSC_VIEWER_SOCKET_PORT - socket number to use for socket viewer
684 -   PETSC_VIEWER_SOCKET_MACHINE - machine to use for socket viewer to connect to
685 
686 
687    Level: beginner
688 
689    Notes:
690    If for some reason you must call MPI_Init() separately, call
691    it before PetscInitialize().
692 
693    Fortran Version:
694    In Fortran this routine has the format
695 $       call PetscInitialize(file,ierr)
696 
697 +   ierr - error return code
698 -  file - [optional] PETSc database file, also checks ~username/.petscrc and .petscrc use PETSC_NULL_CHARACTER to not check for
699           code specific file. Use -skip_petscrc in the code specific file to skip the .petscrc files
700 
701    Important Fortran Note:
702    In Fortran, you MUST use PETSC_NULL_CHARACTER to indicate a
703    null character string; you CANNOT just use NULL as
704    in the C version. See Users-Manual: ch_fortran for details.
705 
706    If your main program is C but you call Fortran code that also uses PETSc you need to call PetscInitializeFortran() soon after
707    calling PetscInitialize().
708 
709    Concepts: initializing PETSc
710 
711 .seealso: PetscFinalize(), PetscInitializeFortran(), PetscGetArgs(), PetscInitializeNoArguments()
712 
713 @*/
714 PetscErrorCode  PetscInitialize(int *argc,char ***args,const char file[],const char help[])
715 {
716   PetscErrorCode ierr;
717   PetscMPIInt    flag, size;
718   PetscBool      flg;
719   char           hostname[256];
720 
721   PetscFunctionBegin;
722   if (PetscInitializeCalled) PetscFunctionReturn(0);
723 
724   /* these must be initialized in a routine, not as a constant declaration*/
725   PETSC_STDOUT = stdout;
726   PETSC_STDERR = stderr;
727 
728   /* on Windows - set printf to default to printing 2 digit exponents */
729 #if defined(PETSC_HAVE__SET_OUTPUT_FORMAT)
730   _set_output_format(_TWO_DIGIT_EXPONENT);
731 #endif
732 
733   ierr = PetscOptionsCreate();CHKERRQ(ierr);
734 
735   /*
736      We initialize the program name here (before MPI_Init()) because MPICH has a bug in
737      it that it sets args[0] on all processors to be args[0] on the first processor.
738   */
739   if (argc && *argc) {
740     ierr = PetscSetProgramName(**args);CHKERRQ(ierr);
741   } else {
742     ierr = PetscSetProgramName("Unknown Name");CHKERRQ(ierr);
743   }
744 
745   ierr = MPI_Initialized(&flag);CHKERRQ(ierr);
746   if (!flag) {
747     if (PETSC_COMM_WORLD != MPI_COMM_NULL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"You cannot set PETSC_COMM_WORLD if you have not initialized MPI first");
748 #if defined(PETSC_HAVE_MPI_INIT_THREAD)
749     {
750       PetscMPIInt provided;
751       ierr = MPI_Init_thread(argc,args,MPI_THREAD_FUNNELED,&provided);CHKERRQ(ierr);
752     }
753 #else
754     ierr = MPI_Init(argc,args);CHKERRQ(ierr);
755 #endif
756     PetscBeganMPI = PETSC_TRUE;
757   }
758   if (argc && args) {
759     PetscGlobalArgc = *argc;
760     PetscGlobalArgs = *args;
761   }
762   PetscFinalizeCalled = PETSC_FALSE;
763 
764   if (PETSC_COMM_WORLD == MPI_COMM_NULL) PETSC_COMM_WORLD = MPI_COMM_WORLD;
765   ierr = MPI_Comm_set_errhandler(PETSC_COMM_WORLD,MPI_ERRORS_RETURN);CHKERRQ(ierr);
766 
767   /* Done after init due to a bug in MPICH-GM? */
768   ierr = PetscErrorPrintfInitialize();CHKERRQ(ierr);
769 
770   ierr = MPI_Comm_rank(MPI_COMM_WORLD,&PetscGlobalRank);CHKERRQ(ierr);
771   ierr = MPI_Comm_size(MPI_COMM_WORLD,&PetscGlobalSize);CHKERRQ(ierr);
772 
773   MPIU_BOOL = MPI_INT;
774   MPIU_ENUM = MPI_INT;
775 
776   /*
777      Initialized the global complex variable; this is because with
778      shared libraries the constructors for global variables
779      are not called; at least on IRIX.
780   */
781 #if defined(PETSC_HAVE_COMPLEX)
782   {
783 #if defined(PETSC_CLANGUAGE_CXX)
784     PetscComplex ic(0.0,1.0);
785     PETSC_i = ic;
786 #elif defined(PETSC_CLANGUAGE_C)
787     PETSC_i = _Complex_I;
788 #endif
789   }
790 
791 #if !defined(PETSC_HAVE_MPI_C_DOUBLE_COMPLEX)
792   ierr = MPI_Type_contiguous(2,MPI_DOUBLE,&MPIU_C_DOUBLE_COMPLEX);CHKERRQ(ierr);
793   ierr = MPI_Type_commit(&MPIU_C_DOUBLE_COMPLEX);CHKERRQ(ierr);
794   ierr = MPI_Type_contiguous(2,MPI_FLOAT,&MPIU_C_COMPLEX);CHKERRQ(ierr);
795   ierr = MPI_Type_commit(&MPIU_C_COMPLEX);CHKERRQ(ierr);
796 #endif
797 #endif /* PETSC_HAVE_COMPLEX */
798 
799   /*
800      Create the PETSc MPI reduction operator that sums of the first
801      half of the entries and maxes the second half.
802   */
803   ierr = MPI_Op_create(PetscMaxSum_Local,1,&PetscMaxSum_Op);CHKERRQ(ierr);
804 
805 #if defined(PETSC_USE_REAL___FLOAT128)
806   ierr = MPI_Type_contiguous(2,MPI_DOUBLE,&MPIU___FLOAT128);CHKERRQ(ierr);
807   ierr = MPI_Type_commit(&MPIU___FLOAT128);CHKERRQ(ierr);
808 #if defined(PETSC_HAVE_COMPLEX)
809   ierr = MPI_Type_contiguous(4,MPI_DOUBLE,&MPIU___COMPLEX128);CHKERRQ(ierr);
810   ierr = MPI_Type_commit(&MPIU___COMPLEX128);CHKERRQ(ierr);
811 #endif
812   ierr = MPI_Op_create(PetscMax_Local,1,&MPIU_MAX);CHKERRQ(ierr);
813   ierr = MPI_Op_create(PetscMin_Local,1,&MPIU_MIN);CHKERRQ(ierr);
814 #endif
815 
816 #if (defined(PETSC_HAVE_COMPLEX) && !defined(PETSC_HAVE_MPI_C_DOUBLE_COMPLEX)) || defined(PETSC_USE_REAL___FLOAT128)
817   ierr = MPI_Op_create(PetscSum_Local,1,&MPIU_SUM);CHKERRQ(ierr);
818 #endif
819 
820   ierr = MPI_Type_contiguous(2,MPIU_SCALAR,&MPIU_2SCALAR);CHKERRQ(ierr);
821   ierr = MPI_Type_commit(&MPIU_2SCALAR);CHKERRQ(ierr);
822 
823 #if defined(PETSC_USE_64BIT_INDICES) || !defined(MPI_2INT)
824   ierr = MPI_Type_contiguous(2,MPIU_INT,&MPIU_2INT);CHKERRQ(ierr);
825   ierr = MPI_Type_commit(&MPIU_2INT);CHKERRQ(ierr);
826 #endif
827 
828 
829   /*
830      Attributes to be set on PETSc communicators
831   */
832   ierr = MPI_Keyval_create(MPI_NULL_COPY_FN,Petsc_DelCounter,&Petsc_Counter_keyval,(void*)0);CHKERRQ(ierr);
833   ierr = MPI_Keyval_create(MPI_NULL_COPY_FN,Petsc_DelComm_Outer,&Petsc_InnerComm_keyval,(void*)0);CHKERRQ(ierr);
834   ierr = MPI_Keyval_create(MPI_NULL_COPY_FN,Petsc_DelComm_Inner,&Petsc_OuterComm_keyval,(void*)0);CHKERRQ(ierr);
835 
836   /*
837      Build the options database
838   */
839   ierr = PetscOptionsInsert(argc,args,file);CHKERRQ(ierr);
840 
841 
842   /*
843      Print main application help message
844   */
845   ierr = PetscOptionsHasName(NULL,"-help",&flg);CHKERRQ(ierr);
846   if (help && flg) {
847     ierr = PetscPrintf(PETSC_COMM_WORLD,help);CHKERRQ(ierr);
848   }
849   ierr = PetscOptionsCheckInitial_Private();CHKERRQ(ierr);
850 
851   ierr = PetscCitationsInitialize();CHKERRQ(ierr);
852 
853 #if defined(PETSC_HAVE_SAWS)
854   ierr = PetscInitializeSAWs(help);CHKERRQ(ierr);
855 #endif
856 
857   /* SHOULD PUT IN GUARDS: Make sure logging is initialized, even if we do not print it out */
858 #if defined(PETSC_USE_LOG)
859   ierr = PetscLogBegin_Private();CHKERRQ(ierr);
860 #endif
861 
862   /*
863      Load the dynamic libraries (on machines that support them), this registers all
864      the solvers etc. (On non-dynamic machines this initializes the PetscDraw and PetscViewer classes)
865   */
866   ierr = PetscInitialize_DynamicLibraries();CHKERRQ(ierr);
867 
868   ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr);
869   ierr = PetscInfo1(0,"PETSc successfully started: number of processors = %d\n",size);CHKERRQ(ierr);
870   ierr = PetscGetHostName(hostname,256);CHKERRQ(ierr);
871   ierr = PetscInfo1(0,"Running on machine: %s\n",hostname);CHKERRQ(ierr);
872 
873   ierr = PetscOptionsCheckInitial_Components();CHKERRQ(ierr);
874   /* Check the options database for options related to the options database itself */
875   ierr = PetscOptionsSetFromOptions();CHKERRQ(ierr);
876 
877 #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
878   /*
879       Tell MPI about our own data representation converter, this would/should be used if extern32 is not supported by the MPI
880 
881       Currently not used because it is not supported by MPICH.
882   */
883 #if !defined(PETSC_WORDS_BIGENDIAN)
884   ierr = MPI_Register_datarep((char*)"petsc",PetscDataRep_read_conv_fn,PetscDataRep_write_conv_fn,PetscDataRep_extent_fn,NULL);CHKERRQ(ierr);
885 #endif
886 #endif
887 
888 #if defined(PETSC_HAVE_CUDA)
889   flg  = PETSC_TRUE;
890   ierr = PetscOptionsGetBool(NULL,"-cublas",&flg,NULL);CHKERRQ(ierr);
891   if (flg) {
892     PetscMPIInt p;
893     for (p = 0; p < PetscGlobalSize; ++p) {
894       if (p == PetscGlobalRank) cublasInit();
895       ierr = MPI_Barrier(PETSC_COMM_WORLD);CHKERRQ(ierr);
896     }
897   }
898 #endif
899 
900   ierr = PetscOptionsHasName(NULL,"-python",&flg);CHKERRQ(ierr);
901   if (flg) {
902     PetscInitializeCalled = PETSC_TRUE;
903     ierr = PetscPythonInitialize(NULL,NULL);CHKERRQ(ierr);
904   }
905 
906   /*
907       Setup building of stack frames for all function calls
908   */
909 #if defined(PETSC_USE_DEBUG)
910   ierr = PetscStackCreate();CHKERRQ(ierr);
911 #endif
912 
913 #if defined(PETSC_SERIALIZE_FUNCTIONS)
914   ierr = PetscFPTCreate(10000);CHKERRQ(ierr);
915 #endif
916 
917 
918   /*
919       Once we are completedly initialized then we can set this variables
920   */
921   PetscInitializeCalled = PETSC_TRUE;
922   PetscFunctionReturn(0);
923 }
924 
925 #if defined(PETSC_USE_LOG)
926 extern PetscObject *PetscObjects;
927 extern PetscInt    PetscObjectsCounts, PetscObjectsMaxCounts;
928 extern PetscBool   PetscObjectsLog;
929 #endif
930 
931 #undef __FUNCT__
932 #define __FUNCT__ "PetscFinalize"
933 /*@C
934    PetscFinalize - Checks for options to be called at the conclusion
935    of the program. MPI_Finalize() is called only if the user had not
936    called MPI_Init() before calling PetscInitialize().
937 
938    Collective on PETSC_COMM_WORLD
939 
940    Options Database Keys:
941 +  -options_table - Calls PetscOptionsView()
942 .  -options_left - Prints unused options that remain in the database
943 .  -objects_dump [all] - Prints list of objects allocated by the user that have not been freed, the option all cause all outstanding objects to be listed
944 .  -mpidump - Calls PetscMPIDump()
945 .  -malloc_dump - Calls PetscMallocDump()
946 .  -malloc_info - Prints total memory usage
947 -  -malloc_log - Prints summary of memory usage
948 
949    Level: beginner
950 
951    Note:
952    See PetscInitialize() for more general runtime options.
953 
954 .seealso: PetscInitialize(), PetscOptionsView(), PetscMallocDump(), PetscMPIDump(), PetscEnd()
955 @*/
956 PetscErrorCode  PetscFinalize(void)
957 {
958   PetscErrorCode ierr;
959   PetscMPIInt    rank;
960   PetscInt       nopt;
961   PetscBool      flg1 = PETSC_FALSE,flg2 = PETSC_FALSE,flg3 = PETSC_FALSE;
962   PetscBool      flg;
963 #if defined(PETSC_USE_LOG)
964   char           mname[PETSC_MAX_PATH_LEN];
965 #endif
966 
967   PetscFunctionBegin;
968   if (!PetscInitializeCalled) {
969     printf("PetscInitialize() must be called before PetscFinalize()\n");
970     PetscFunctionReturn(PETSC_ERR_ARG_WRONGSTATE);
971   }
972   ierr = PetscInfo(NULL,"PetscFinalize() called\n");CHKERRQ(ierr);
973 
974   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
975 
976   ierr = PetscOptionsHasName(NULL,"-citations",&flg);CHKERRQ(ierr);
977   if (flg) {
978     char  *cits, filename[PETSC_MAX_PATH_LEN];
979     FILE  *fd = PETSC_STDOUT;
980 
981     ierr = PetscOptionsGetString(NULL,"-citations",filename,PETSC_MAX_PATH_LEN,NULL);CHKERRQ(ierr);
982     if (filename[0]) {
983       ierr = PetscFOpen(PETSC_COMM_WORLD,filename,"w",&fd);CHKERRQ(ierr);
984     }
985     ierr = PetscSegBufferGet(PetscCitationsList,1,&cits);CHKERRQ(ierr);
986     cits[0] = 0;
987     ierr = PetscSegBufferExtractAlloc(PetscCitationsList,&cits);CHKERRQ(ierr);
988     ierr = PetscFPrintf(PETSC_COMM_WORLD,fd,"If you publish results based on this computation please cite the following:\n");CHKERRQ(ierr);
989     ierr = PetscFPrintf(PETSC_COMM_WORLD,fd,"===========================================================================\n");CHKERRQ(ierr);
990     ierr = PetscFPrintf(PETSC_COMM_WORLD,fd,"%s",cits);CHKERRQ(ierr);
991     ierr = PetscFPrintf(PETSC_COMM_WORLD,fd,"===========================================================================\n");CHKERRQ(ierr);
992     ierr = PetscFClose(PETSC_COMM_WORLD,fd);CHKERRQ(ierr);
993     ierr = PetscFree(cits);CHKERRQ(ierr);
994   }
995   ierr = PetscSegBufferDestroy(&PetscCitationsList);CHKERRQ(ierr);
996 
997 #if defined(PETSC_HAVE_SSL) && defined(PETSC_USE_SOCKET_VIEWER)
998   /* TextBelt is run for testing purposes only, please do not use this feature often */
999   {
1000     PetscInt nmax = 2;
1001     char     **buffs;
1002     ierr = PetscMalloc1(2,&buffs);CHKERRQ(ierr);
1003     ierr = PetscOptionsGetStringArray(NULL,"-textbelt",buffs,&nmax,&flg1);CHKERRQ(ierr);
1004     if (flg1) {
1005       if (!nmax) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_USER,"-textbelt requires either the phone number or number,\"message\"");
1006       if (nmax == 1) {
1007         ierr = PetscMalloc1(128,&buffs[1]);CHKERRQ(ierr);
1008         ierr = PetscGetProgramName(buffs[1],32);CHKERRQ(ierr);
1009         ierr = PetscStrcat(buffs[1]," has completed");CHKERRQ(ierr);
1010       }
1011       ierr = PetscTextBelt(PETSC_COMM_WORLD,buffs[0],buffs[1],NULL);CHKERRQ(ierr);
1012       ierr = PetscFree(buffs[0]);CHKERRQ(ierr);
1013       ierr = PetscFree(buffs[1]);CHKERRQ(ierr);
1014     }
1015     ierr = PetscFree(buffs);CHKERRQ(ierr);
1016   }
1017 #endif
1018   /*
1019     It should be safe to cancel the options monitors, since we don't expect to be setting options
1020     here (at least that are worth monitoring).  Monitors ought to be released so that they release
1021     whatever memory was allocated there before -malloc_dump reports unfreed memory.
1022   */
1023   ierr = PetscOptionsMonitorCancel();CHKERRQ(ierr);
1024 
1025 #if defined(PETSC_SERIALIZE_FUNCTIONS)
1026   ierr = PetscFPTDestroy();CHKERRQ(ierr);
1027 #endif
1028 
1029 
1030 #if defined(PETSC_HAVE_SAWS)
1031   flg = PETSC_FALSE;
1032   ierr = PetscOptionsGetBool(NULL,"-saw_options",&flg,NULL);CHKERRQ(ierr);
1033   if (flg) {
1034     ierr = PetscOptionsSAWsDestroy();CHKERRQ(ierr);
1035   }
1036 #endif
1037 
1038 #if defined(PETSC_HAVE_X)
1039   flg1 = PETSC_FALSE;
1040   ierr = PetscOptionsGetBool(NULL,"-x_virtual",&flg1,NULL);CHKERRQ(ierr);
1041   if (flg1) {
1042     /*  this is a crude hack, but better than nothing */
1043     ierr = PetscPOpen(PETSC_COMM_WORLD,NULL,"pkill -9 Xvfb","r",NULL);CHKERRQ(ierr);
1044   }
1045 #endif
1046 
1047 #if !defined(PETSC_HAVE_THREADSAFETY)
1048   ierr = PetscOptionsGetBool(NULL,"-malloc_info",&flg2,NULL);CHKERRQ(ierr);
1049   if (!flg2) {
1050     flg2 = PETSC_FALSE;
1051     ierr = PetscOptionsGetBool(NULL,"-memory_info",&flg2,NULL);CHKERRQ(ierr);
1052   }
1053   if (flg2) {
1054     ierr = PetscMemoryShowUsage(PETSC_VIEWER_STDOUT_WORLD,"Summary of Memory Usage in PETSc\n");CHKERRQ(ierr);
1055   }
1056 #endif
1057 
1058 #if defined(PETSC_USE_LOG)
1059   flg1 = PETSC_FALSE;
1060   ierr = PetscOptionsGetBool(NULL,"-get_total_flops",&flg1,NULL);CHKERRQ(ierr);
1061   if (flg1) {
1062     PetscLogDouble flops = 0;
1063     ierr = MPI_Reduce(&petsc_TotalFlops,&flops,1,MPI_DOUBLE,MPI_SUM,0,PETSC_COMM_WORLD);CHKERRQ(ierr);
1064     ierr = PetscPrintf(PETSC_COMM_WORLD,"Total flops over all processors %g\n",flops);CHKERRQ(ierr);
1065   }
1066 #endif
1067 
1068 
1069 #if defined(PETSC_USE_LOG)
1070 #if defined(PETSC_HAVE_MPE)
1071   mname[0] = 0;
1072 
1073   ierr = PetscOptionsGetString(NULL,"-log_mpe",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr);
1074   if (flg1) {
1075     if (mname[0]) {ierr = PetscLogMPEDump(mname);CHKERRQ(ierr);}
1076     else          {ierr = PetscLogMPEDump(0);CHKERRQ(ierr);}
1077   }
1078 #endif
1079   mname[0] = 0;
1080 
1081   ierr = PetscLogViewFromOptions();CHKERRQ(ierr);
1082   ierr = PetscOptionsGetString(NULL,"-log_summary",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr);
1083   if (flg1) {
1084     PetscViewer viewer;
1085     if (mname[0]) {
1086       ierr = PetscViewerASCIIOpen(PETSC_COMM_WORLD,mname,&viewer);CHKERRQ(ierr);
1087       ierr = PetscLogView(viewer);CHKERRQ(ierr);
1088       ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1089     } else {
1090       viewer = PETSC_VIEWER_STDOUT_WORLD;
1091       ierr   = PetscLogView(viewer);CHKERRQ(ierr);
1092     }
1093   }
1094   mname[0] = 0;
1095 
1096   ierr = PetscOptionsGetString(NULL,"-log_all",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr);
1097   ierr = PetscOptionsGetString(NULL,"-log",mname,PETSC_MAX_PATH_LEN,&flg2);CHKERRQ(ierr);
1098   if (flg1 || flg2) {
1099     if (mname[0]) PetscLogDump(mname);
1100     else          PetscLogDump(0);
1101   }
1102 #endif
1103 
1104   /*
1105      Free all objects registered with PetscObjectRegisterDestroy() such as PETSC_VIEWER_XXX_().
1106   */
1107   ierr = PetscObjectRegisterDestroyAll();CHKERRQ(ierr);
1108 
1109   ierr = PetscStackDestroy();CHKERRQ(ierr);
1110 
1111   flg1 = PETSC_FALSE;
1112   ierr = PetscOptionsGetBool(NULL,"-no_signal_handler",&flg1,NULL);CHKERRQ(ierr);
1113   if (!flg1) { ierr = PetscPopSignalHandler();CHKERRQ(ierr);}
1114   flg1 = PETSC_FALSE;
1115   ierr = PetscOptionsGetBool(NULL,"-mpidump",&flg1,NULL);CHKERRQ(ierr);
1116   if (flg1) {
1117     ierr = PetscMPIDump(stdout);CHKERRQ(ierr);
1118   }
1119   flg1 = PETSC_FALSE;
1120   flg2 = PETSC_FALSE;
1121   /* preemptive call to avoid listing this option in options table as unused */
1122   ierr = PetscOptionsHasName(NULL,"-malloc_dump",&flg1);CHKERRQ(ierr);
1123   ierr = PetscOptionsHasName(NULL,"-objects_dump",&flg1);CHKERRQ(ierr);
1124   ierr = PetscOptionsGetBool(NULL,"-options_view",&flg2,NULL);CHKERRQ(ierr);
1125 
1126   if (flg2) {
1127     PetscViewer viewer;
1128     ierr = PetscViewerCreate(PETSC_COMM_WORLD,&viewer);CHKERRQ(ierr);
1129     ierr = PetscViewerSetType(viewer,PETSCVIEWERASCII);CHKERRQ(ierr);
1130     ierr = PetscOptionsView(viewer);CHKERRQ(ierr);
1131     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1132   }
1133 
1134   /* to prevent PETSc -options_left from warning */
1135   ierr = PetscOptionsHasName(NULL,"-nox",&flg1);CHKERRQ(ierr);
1136   ierr = PetscOptionsHasName(NULL,"-nox_warning",&flg1);CHKERRQ(ierr);
1137 
1138   flg3 = PETSC_FALSE; /* default value is required */
1139   ierr = PetscOptionsGetBool(NULL,"-options_left",&flg3,&flg1);CHKERRQ(ierr);
1140   ierr = PetscOptionsAllUsed(&nopt);CHKERRQ(ierr);
1141   if (flg3) {
1142     if (!flg2) { /* have not yet printed the options */
1143       PetscViewer viewer;
1144       ierr = PetscViewerCreate(PETSC_COMM_WORLD,&viewer);CHKERRQ(ierr);
1145       ierr = PetscViewerSetType(viewer,PETSCVIEWERASCII);CHKERRQ(ierr);
1146       ierr = PetscOptionsView(viewer);CHKERRQ(ierr);
1147       ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1148     }
1149     if (!nopt) {
1150       ierr = PetscPrintf(PETSC_COMM_WORLD,"There are no unused options.\n");CHKERRQ(ierr);
1151     } else if (nopt == 1) {
1152       ierr = PetscPrintf(PETSC_COMM_WORLD,"There is one unused database option. It is:\n");CHKERRQ(ierr);
1153     } else {
1154       ierr = PetscPrintf(PETSC_COMM_WORLD,"There are %D unused database options. They are:\n",nopt);CHKERRQ(ierr);
1155     }
1156   }
1157 #if defined(PETSC_USE_DEBUG)
1158   if (nopt && !flg3 && !flg1) {
1159     ierr = PetscPrintf(PETSC_COMM_WORLD,"WARNING! There are options you set that were not used!\n");CHKERRQ(ierr);
1160     ierr = PetscPrintf(PETSC_COMM_WORLD,"WARNING! could be spelling mistake, etc!\n");CHKERRQ(ierr);
1161     ierr = PetscOptionsLeft();CHKERRQ(ierr);
1162   } else if (nopt && flg3) {
1163 #else
1164   if (nopt && flg3) {
1165 #endif
1166     ierr = PetscOptionsLeft();CHKERRQ(ierr);
1167   }
1168 
1169 #if defined(PETSC_HAVE_SAWS)
1170   if (!PetscGlobalRank) {
1171     ierr = PetscStackSAWsViewOff();CHKERRQ(ierr);
1172     PetscStackCallSAWs(SAWs_Finalize,());
1173   }
1174 #endif
1175 
1176 #if defined(PETSC_USE_LOG)
1177   /*
1178        List all objects the user may have forgot to free
1179   */
1180   if (PetscObjectsLog) {
1181     ierr = PetscOptionsHasName(NULL,"-objects_dump",&flg1);CHKERRQ(ierr);
1182     if (flg1) {
1183       MPI_Comm local_comm;
1184       char     string[64];
1185 
1186       ierr = PetscOptionsGetString(NULL,"-objects_dump",string,64,NULL);CHKERRQ(ierr);
1187       ierr = MPI_Comm_dup(MPI_COMM_WORLD,&local_comm);CHKERRQ(ierr);
1188       ierr = PetscSequentialPhaseBegin_Private(local_comm,1);CHKERRQ(ierr);
1189       ierr = PetscObjectsDump(stdout,(string[0] == 'a') ? PETSC_TRUE : PETSC_FALSE);CHKERRQ(ierr);
1190       ierr = PetscSequentialPhaseEnd_Private(local_comm,1);CHKERRQ(ierr);
1191       ierr = MPI_Comm_free(&local_comm);CHKERRQ(ierr);
1192     }
1193   }
1194 #endif
1195 
1196 #if defined(PETSC_USE_LOG)
1197   PetscObjectsCounts    = 0;
1198   PetscObjectsMaxCounts = 0;
1199   ierr = PetscFree(PetscObjects);CHKERRQ(ierr);
1200 #endif
1201 
1202 #if defined(PETSC_USE_LOG)
1203   ierr = PetscLogDestroy();CHKERRQ(ierr);
1204 #endif
1205 
1206   /*
1207      Close any open dynamic libraries
1208   */
1209   ierr = PetscFinalize_DynamicLibraries();CHKERRQ(ierr);
1210 
1211   /*
1212      Destroy any packages that registered a finalize
1213   */
1214   ierr = PetscRegisterFinalizeAll();CHKERRQ(ierr);
1215 
1216   /*
1217      Print PetscFunctionLists that have not been properly freed
1218 
1219   ierr = PetscFunctionListPrintAll();CHKERRQ(ierr);
1220   */
1221 
1222   if (petsc_history) {
1223     ierr = PetscCloseHistoryFile(&petsc_history);CHKERRQ(ierr);
1224     petsc_history = 0;
1225   }
1226 
1227   ierr = PetscInfoAllow(PETSC_FALSE,NULL);CHKERRQ(ierr);
1228 
1229 #if !defined(PETSC_HAVE_THREADSAFETY)
1230   {
1231     char fname[PETSC_MAX_PATH_LEN];
1232     FILE *fd;
1233     int  err;
1234 
1235     fname[0] = 0;
1236 
1237     ierr = PetscOptionsGetString(NULL,"-malloc_dump",fname,250,&flg1);CHKERRQ(ierr);
1238     flg2 = PETSC_FALSE;
1239     ierr = PetscOptionsGetBool(NULL,"-malloc_test",&flg2,NULL);CHKERRQ(ierr);
1240 #if defined(PETSC_USE_DEBUG)
1241     if (PETSC_RUNNING_ON_VALGRIND) flg2 = PETSC_FALSE;
1242 #else
1243     flg2 = PETSC_FALSE;         /* Skip reporting for optimized builds regardless of -malloc_test */
1244 #endif
1245     if (flg1 && fname[0]) {
1246       char sname[PETSC_MAX_PATH_LEN];
1247 
1248       sprintf(sname,"%s_%d",fname,rank);
1249       fd   = fopen(sname,"w"); if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open log file: %s",sname);
1250       ierr = PetscMallocDump(fd);CHKERRQ(ierr);
1251       err  = fclose(fd);
1252       if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
1253     } else if (flg1 || flg2) {
1254       MPI_Comm local_comm;
1255 
1256       ierr = MPI_Comm_dup(MPI_COMM_WORLD,&local_comm);CHKERRQ(ierr);
1257       ierr = PetscSequentialPhaseBegin_Private(local_comm,1);CHKERRQ(ierr);
1258       ierr = PetscMallocDump(stdout);CHKERRQ(ierr);
1259       ierr = PetscSequentialPhaseEnd_Private(local_comm,1);CHKERRQ(ierr);
1260       ierr = MPI_Comm_free(&local_comm);CHKERRQ(ierr);
1261     }
1262   }
1263 
1264   {
1265     char fname[PETSC_MAX_PATH_LEN];
1266     FILE *fd = NULL;
1267 
1268     fname[0] = 0;
1269 
1270     ierr = PetscOptionsGetString(NULL,"-malloc_log",fname,250,&flg1);CHKERRQ(ierr);
1271     ierr = PetscOptionsHasName(NULL,"-malloc_log_threshold",&flg2);CHKERRQ(ierr);
1272     if (flg1 && fname[0]) {
1273       int err;
1274 
1275       if (!rank) {
1276         fd = fopen(fname,"w");
1277         if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open log file: %s",fname);
1278       }
1279       ierr = PetscMallocDumpLog(fd);CHKERRQ(ierr);
1280       if (fd) {
1281         err = fclose(fd);
1282         if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
1283       }
1284     } else if (flg1 || flg2) {
1285       ierr = PetscMallocDumpLog(stdout);CHKERRQ(ierr);
1286     }
1287   }
1288 #endif
1289 
1290 #if defined(PETSC_HAVE_CUDA)
1291   flg  = PETSC_TRUE;
1292   ierr = PetscOptionsGetBool(NULL,"-cublas",&flg,NULL);CHKERRQ(ierr);
1293   if (flg) {
1294     PetscInt p;
1295     for (p = 0; p < PetscGlobalSize; ++p) {
1296       if (p == PetscGlobalRank) cublasShutdown();
1297       ierr = MPI_Barrier(PETSC_COMM_WORLD);CHKERRQ(ierr);
1298     }
1299   }
1300 #endif
1301 
1302   /* Can be destroyed only after all the options are used */
1303   ierr = PetscOptionsDestroy();CHKERRQ(ierr);
1304 
1305   PetscGlobalArgc = 0;
1306   PetscGlobalArgs = 0;
1307 
1308 #if defined(PETSC_USE_REAL___FLOAT128)
1309   ierr = MPI_Type_free(&MPIU___FLOAT128);CHKERRQ(ierr);
1310 #if defined(PETSC_HAVE_COMPLEX)
1311   ierr = MPI_Type_free(&MPIU___COMPLEX128);CHKERRQ(ierr);
1312 #endif
1313   ierr = MPI_Op_free(&MPIU_MAX);CHKERRQ(ierr);
1314   ierr = MPI_Op_free(&MPIU_MIN);CHKERRQ(ierr);
1315 #endif
1316 
1317 #if defined(PETSC_HAVE_COMPLEX)
1318 #if !defined(PETSC_HAVE_MPI_C_DOUBLE_COMPLEX)
1319   ierr = MPI_Type_free(&MPIU_C_DOUBLE_COMPLEX);CHKERRQ(ierr);
1320   ierr = MPI_Type_free(&MPIU_C_COMPLEX);CHKERRQ(ierr);
1321 #endif
1322 #endif
1323 
1324 #if (defined(PETSC_HAVE_COMPLEX) && !defined(PETSC_HAVE_MPI_C_DOUBLE_COMPLEX)) || defined(PETSC_USE_REAL___FLOAT128)
1325   ierr = MPI_Op_free(&MPIU_SUM);CHKERRQ(ierr);
1326 #endif
1327 
1328   ierr = MPI_Type_free(&MPIU_2SCALAR);CHKERRQ(ierr);
1329 #if defined(PETSC_USE_64BIT_INDICES) || !defined(MPI_2INT)
1330   ierr = MPI_Type_free(&MPIU_2INT);CHKERRQ(ierr);
1331 #endif
1332   ierr = MPI_Op_free(&PetscMaxSum_Op);CHKERRQ(ierr);
1333 
1334   /*
1335      Destroy any known inner MPI_Comm's and attributes pointing to them
1336      Note this will not destroy any new communicators the user has created.
1337 
1338      If all PETSc objects were not destroyed those left over objects will have hanging references to
1339      the MPI_Comms that were freed; but that is ok because those PETSc objects will never be used again
1340  */
1341   {
1342     PetscCommCounter *counter;
1343     PetscMPIInt      flg;
1344     MPI_Comm         icomm;
1345     union {MPI_Comm comm; void *ptr;} ucomm;
1346     ierr = MPI_Attr_get(PETSC_COMM_SELF,Petsc_InnerComm_keyval,&ucomm,&flg);CHKERRQ(ierr);
1347     if (flg) {
1348       icomm = ucomm.comm;
1349       ierr = MPI_Attr_get(icomm,Petsc_Counter_keyval,&counter,&flg);CHKERRQ(ierr);
1350       if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Inner MPI_Comm does not have expected tag/name counter, problem with corrupted memory");
1351 
1352       ierr = MPI_Attr_delete(PETSC_COMM_SELF,Petsc_InnerComm_keyval);CHKERRQ(ierr);
1353       ierr = MPI_Attr_delete(icomm,Petsc_Counter_keyval);CHKERRQ(ierr);
1354       ierr = MPI_Comm_free(&icomm);CHKERRQ(ierr);
1355     }
1356     ierr = MPI_Attr_get(PETSC_COMM_WORLD,Petsc_InnerComm_keyval,&ucomm,&flg);CHKERRQ(ierr);
1357     if (flg) {
1358       icomm = ucomm.comm;
1359       ierr = MPI_Attr_get(icomm,Petsc_Counter_keyval,&counter,&flg);CHKERRQ(ierr);
1360       if (!flg) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_ARG_CORRUPT,"Inner MPI_Comm does not have expected tag/name counter, problem with corrupted memory");
1361 
1362       ierr = MPI_Attr_delete(PETSC_COMM_WORLD,Petsc_InnerComm_keyval);CHKERRQ(ierr);
1363       ierr = MPI_Attr_delete(icomm,Petsc_Counter_keyval);CHKERRQ(ierr);
1364       ierr = MPI_Comm_free(&icomm);CHKERRQ(ierr);
1365     }
1366   }
1367 
1368   ierr = MPI_Keyval_free(&Petsc_Counter_keyval);CHKERRQ(ierr);
1369   ierr = MPI_Keyval_free(&Petsc_InnerComm_keyval);CHKERRQ(ierr);
1370   ierr = MPI_Keyval_free(&Petsc_OuterComm_keyval);CHKERRQ(ierr);
1371 
1372   if (PetscBeganMPI) {
1373 #if defined(PETSC_HAVE_MPI_FINALIZED)
1374     PetscMPIInt flag;
1375     ierr = MPI_Finalized(&flag);CHKERRQ(ierr);
1376     if (flag) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"MPI_Finalize() has already been called, even though MPI_Init() was called by PetscInitialize()");
1377 #endif
1378     ierr = MPI_Finalize();CHKERRQ(ierr);
1379   }
1380 /*
1381 
1382      Note: In certain cases PETSC_COMM_WORLD is never MPI_Comm_free()ed because
1383    the communicator has some outstanding requests on it. Specifically if the
1384    flag PETSC_HAVE_BROKEN_REQUEST_FREE is set (for IBM MPI implementation). See
1385    src/vec/utils/vpscat.c. Due to this the memory allocated in PetscCommDuplicate()
1386    is never freed as it should be. Thus one may obtain messages of the form
1387    [ 1] 8 bytes PetscCommDuplicate() line 645 in src/sys/mpiu.c indicating the
1388    memory was not freed.
1389 
1390 */
1391   ierr = PetscMallocClear();CHKERRQ(ierr);
1392 
1393   PetscInitializeCalled = PETSC_FALSE;
1394   PetscFinalizeCalled   = PETSC_TRUE;
1395   PetscFunctionReturn(ierr);
1396 }
1397 
1398 #if defined(PETSC_MISSING_LAPACK_lsame_)
1399 PETSC_EXTERN int lsame_(char *a,char *b)
1400 {
1401   if (*a == *b) return 1;
1402   if (*a + 32 == *b) return 1;
1403   if (*a - 32 == *b) return 1;
1404   return 0;
1405 }
1406 #endif
1407 
1408 #if defined(PETSC_MISSING_LAPACK_lsame)
1409 PETSC_EXTERN int lsame(char *a,char *b)
1410 {
1411   if (*a == *b) return 1;
1412   if (*a + 32 == *b) return 1;
1413   if (*a - 32 == *b) return 1;
1414   return 0;
1415 }
1416 #endif
1417