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