xref: /petsc/src/sys/objects/pinit.c (revision 218d4943ca41a4b1a0eb642c9b5de5a8b4116578)
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 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 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   ierr = PetscOptionsGetBool(NULL,"-malloc_info",&flg2,NULL);CHKERRQ(ierr);
1042   if (!flg2) {
1043     flg2 = PETSC_FALSE;
1044     ierr = PetscOptionsGetBool(NULL,"-memory_info",&flg2,NULL);CHKERRQ(ierr);
1045   }
1046   if (flg2) {
1047     ierr = PetscMemoryShowUsage(PETSC_VIEWER_STDOUT_WORLD,"Summary of Memory Usage in PETSc\n");CHKERRQ(ierr);
1048   }
1049 
1050 #if defined(PETSC_USE_LOG)
1051   flg1 = PETSC_FALSE;
1052   ierr = PetscOptionsGetBool(NULL,"-get_total_flops",&flg1,NULL);CHKERRQ(ierr);
1053   if (flg1) {
1054     PetscLogDouble flops = 0;
1055     ierr = MPI_Reduce(&petsc_TotalFlops,&flops,1,MPI_DOUBLE,MPI_SUM,0,PETSC_COMM_WORLD);CHKERRQ(ierr);
1056     ierr = PetscPrintf(PETSC_COMM_WORLD,"Total flops over all processors %g\n",flops);CHKERRQ(ierr);
1057   }
1058 #endif
1059 
1060 
1061 #if defined(PETSC_USE_LOG)
1062 #if defined(PETSC_HAVE_MPE)
1063   mname[0] = 0;
1064 
1065   ierr = PetscOptionsGetString(NULL,"-log_mpe",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr);
1066   if (flg1) {
1067     if (mname[0]) {ierr = PetscLogMPEDump(mname);CHKERRQ(ierr);}
1068     else          {ierr = PetscLogMPEDump(0);CHKERRQ(ierr);}
1069   }
1070 #endif
1071   mname[0] = 0;
1072 
1073   ierr = PetscLogViewFromOptions();CHKERRQ(ierr);
1074   ierr = PetscOptionsGetString(NULL,"-log_summary",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr);
1075   if (flg1) {
1076     PetscViewer viewer;
1077     if (mname[0]) {
1078       ierr = PetscViewerASCIIOpen(PETSC_COMM_WORLD,mname,&viewer);CHKERRQ(ierr);
1079       ierr = PetscLogView(viewer);CHKERRQ(ierr);
1080       ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1081     } else {
1082       viewer = PETSC_VIEWER_STDOUT_WORLD;
1083       ierr   = PetscLogView(viewer);CHKERRQ(ierr);
1084     }
1085   }
1086   mname[0] = 0;
1087 
1088   ierr = PetscOptionsGetString(NULL,"-log_all",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr);
1089   ierr = PetscOptionsGetString(NULL,"-log",mname,PETSC_MAX_PATH_LEN,&flg2);CHKERRQ(ierr);
1090   if (flg1 || flg2) {
1091     if (mname[0]) PetscLogDump(mname);
1092     else          PetscLogDump(0);
1093   }
1094 #endif
1095 
1096   /*
1097      Free all objects registered with PetscObjectRegisterDestroy() such as PETSC_VIEWER_XXX_().
1098   */
1099   ierr = PetscObjectRegisterDestroyAll();CHKERRQ(ierr);
1100 
1101   ierr = PetscStackDestroy();CHKERRQ(ierr);
1102   PetscThreadLocalDestroy((PetscThreadKey)petscstack); /* Deletes pthread_key */
1103 
1104   flg1 = PETSC_FALSE;
1105   ierr = PetscOptionsGetBool(NULL,"-no_signal_handler",&flg1,NULL);CHKERRQ(ierr);
1106   if (!flg1) { ierr = PetscPopSignalHandler();CHKERRQ(ierr);}
1107   flg1 = PETSC_FALSE;
1108   ierr = PetscOptionsGetBool(NULL,"-mpidump",&flg1,NULL);CHKERRQ(ierr);
1109   if (flg1) {
1110     ierr = PetscMPIDump(stdout);CHKERRQ(ierr);
1111   }
1112   flg1 = PETSC_FALSE;
1113   flg2 = PETSC_FALSE;
1114   /* preemptive call to avoid listing this option in options table as unused */
1115   ierr = PetscOptionsHasName(NULL,"-malloc_dump",&flg1);CHKERRQ(ierr);
1116   ierr = PetscOptionsHasName(NULL,"-objects_dump",&flg1);CHKERRQ(ierr);
1117   ierr = PetscOptionsGetBool(NULL,"-options_view",&flg2,NULL);CHKERRQ(ierr);
1118 
1119   if (flg2) {
1120     PetscViewer viewer;
1121     ierr = PetscViewerCreate(PETSC_COMM_WORLD,&viewer);CHKERRQ(ierr);
1122     ierr = PetscViewerSetType(viewer,PETSCVIEWERASCII);CHKERRQ(ierr);
1123     ierr = PetscOptionsView(viewer);CHKERRQ(ierr);
1124     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1125   }
1126 
1127   /* to prevent PETSc -options_left from warning */
1128   ierr = PetscOptionsHasName(NULL,"-nox",&flg1);CHKERRQ(ierr);
1129   ierr = PetscOptionsHasName(NULL,"-nox_warning",&flg1);CHKERRQ(ierr);
1130 
1131   flg3 = PETSC_FALSE; /* default value is required */
1132   ierr = PetscOptionsGetBool(NULL,"-options_left",&flg3,&flg1);CHKERRQ(ierr);
1133   ierr = PetscOptionsAllUsed(&nopt);CHKERRQ(ierr);
1134   if (flg3) {
1135     if (!flg2) { /* have not yet printed the options */
1136       PetscViewer viewer;
1137       ierr = PetscViewerCreate(PETSC_COMM_WORLD,&viewer);CHKERRQ(ierr);
1138       ierr = PetscViewerSetType(viewer,PETSCVIEWERASCII);CHKERRQ(ierr);
1139       ierr = PetscOptionsView(viewer);CHKERRQ(ierr);
1140       ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1141     }
1142     if (!nopt) {
1143       ierr = PetscPrintf(PETSC_COMM_WORLD,"There are no unused options.\n");CHKERRQ(ierr);
1144     } else if (nopt == 1) {
1145       ierr = PetscPrintf(PETSC_COMM_WORLD,"There is one unused database option. It is:\n");CHKERRQ(ierr);
1146     } else {
1147       ierr = PetscPrintf(PETSC_COMM_WORLD,"There are %D unused database options. They are:\n",nopt);CHKERRQ(ierr);
1148     }
1149   }
1150 #if defined(PETSC_USE_DEBUG)
1151   if (nopt && !flg3 && !flg1) {
1152     ierr = PetscPrintf(PETSC_COMM_WORLD,"WARNING! There are options you set that were not used!\n");CHKERRQ(ierr);
1153     ierr = PetscPrintf(PETSC_COMM_WORLD,"WARNING! could be spelling mistake, etc!\n");CHKERRQ(ierr);
1154     ierr = PetscOptionsLeft();CHKERRQ(ierr);
1155   } else if (nopt && flg3) {
1156 #else
1157   if (nopt && flg3) {
1158 #endif
1159     ierr = PetscOptionsLeft();CHKERRQ(ierr);
1160   }
1161 
1162 #if defined(PETSC_HAVE_SAWS)
1163   if (!PetscGlobalRank) {
1164     ierr = PetscStackSAWsViewOff();CHKERRQ(ierr);
1165     PetscStackCallSAWs(SAWs_Finalize,());
1166   }
1167 #endif
1168 
1169   {
1170     PetscThreadComm tcomm_world;
1171     ierr = PetscGetThreadCommWorld(&tcomm_world);CHKERRQ(ierr);
1172     /* Free global thread communicator */
1173     ierr = PetscThreadCommDestroy(&tcomm_world);CHKERRQ(ierr);
1174   }
1175 
1176 #if defined(PETSC_USE_LOG)
1177   /*
1178        List all objects the user may have forgot to free
1179   */
1180   ierr = PetscOptionsHasName(NULL,"-objects_dump",&flg1);CHKERRQ(ierr);
1181   if (flg1) {
1182     MPI_Comm local_comm;
1183     char     string[64];
1184 
1185     ierr = PetscOptionsGetString(NULL,"-objects_dump",string,64,NULL);CHKERRQ(ierr);
1186     ierr = MPI_Comm_dup(MPI_COMM_WORLD,&local_comm);CHKERRQ(ierr);
1187     ierr = PetscSequentialPhaseBegin_Private(local_comm,1);CHKERRQ(ierr);
1188     ierr = PetscObjectsDump(stdout,(string[0] == 'a') ? PETSC_TRUE : PETSC_FALSE);CHKERRQ(ierr);
1189     ierr = PetscSequentialPhaseEnd_Private(local_comm,1);CHKERRQ(ierr);
1190     ierr = MPI_Comm_free(&local_comm);CHKERRQ(ierr);
1191   }
1192 #endif
1193 
1194 #if defined(PETSC_USE_LOG)
1195   PetscObjectsCounts    = 0;
1196   PetscObjectsMaxCounts = 0;
1197   ierr = PetscFree(PetscObjects);CHKERRQ(ierr);
1198 #endif
1199 
1200 #if defined(PETSC_USE_LOG)
1201   ierr = PetscLogDestroy();CHKERRQ(ierr);
1202 #endif
1203 
1204   /*
1205      Close any open dynamic libraries
1206   */
1207   ierr = PetscFinalize_DynamicLibraries();CHKERRQ(ierr);
1208 
1209   /*
1210      Destroy any packages that registered a finalize
1211   */
1212   ierr = PetscRegisterFinalizeAll();CHKERRQ(ierr);
1213 
1214   /*
1215      Print PetscFunctionLists that have not been properly freed
1216 
1217   ierr = PetscFunctionListPrintAll();CHKERRQ(ierr);
1218   */
1219 
1220   if (petsc_history) {
1221     ierr = PetscCloseHistoryFile(&petsc_history);CHKERRQ(ierr);
1222     petsc_history = 0;
1223   }
1224 
1225   ierr = PetscInfoAllow(PETSC_FALSE,NULL);CHKERRQ(ierr);
1226 
1227   {
1228     char fname[PETSC_MAX_PATH_LEN];
1229     FILE *fd;
1230     int  err;
1231 
1232     fname[0] = 0;
1233 
1234     ierr = PetscOptionsGetString(NULL,"-malloc_dump",fname,250,&flg1);CHKERRQ(ierr);
1235     flg2 = PETSC_FALSE;
1236     ierr = PetscOptionsGetBool(NULL,"-malloc_test",&flg2,NULL);CHKERRQ(ierr);
1237 #if defined(PETSC_USE_DEBUG)
1238     if (PETSC_RUNNING_ON_VALGRIND) flg2 = PETSC_FALSE;
1239 #else
1240     flg2 = PETSC_FALSE;         /* Skip reporting for optimized builds regardless of -malloc_test */
1241 #endif
1242     if (flg1 && fname[0]) {
1243       char sname[PETSC_MAX_PATH_LEN];
1244 
1245       sprintf(sname,"%s_%d",fname,rank);
1246       fd   = fopen(sname,"w"); if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open log file: %s",sname);
1247       ierr = PetscMallocDump(fd);CHKERRQ(ierr);
1248       err  = fclose(fd);
1249       if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
1250     } else if (flg1 || flg2) {
1251       MPI_Comm local_comm;
1252 
1253       ierr = MPI_Comm_dup(MPI_COMM_WORLD,&local_comm);CHKERRQ(ierr);
1254       ierr = PetscSequentialPhaseBegin_Private(local_comm,1);CHKERRQ(ierr);
1255       ierr = PetscMallocDump(stdout);CHKERRQ(ierr);
1256       ierr = PetscSequentialPhaseEnd_Private(local_comm,1);CHKERRQ(ierr);
1257       ierr = MPI_Comm_free(&local_comm);CHKERRQ(ierr);
1258     }
1259   }
1260 
1261   {
1262     char fname[PETSC_MAX_PATH_LEN];
1263     FILE *fd = NULL;
1264 
1265     fname[0] = 0;
1266 
1267     ierr = PetscOptionsGetString(NULL,"-malloc_log",fname,250,&flg1);CHKERRQ(ierr);
1268     ierr = PetscOptionsHasName(NULL,"-malloc_log_threshold",&flg2);CHKERRQ(ierr);
1269     if (flg1 && fname[0]) {
1270       int err;
1271 
1272       if (!rank) {
1273         fd = fopen(fname,"w");
1274         if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open log file: %s",fname);
1275       }
1276       ierr = PetscMallocDumpLog(fd);CHKERRQ(ierr);
1277       if (fd) {
1278         err = fclose(fd);
1279         if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
1280       }
1281     } else if (flg1 || flg2) {
1282       ierr = PetscMallocDumpLog(stdout);CHKERRQ(ierr);
1283     }
1284   }
1285 
1286 #if defined(PETSC_HAVE_CUDA)
1287   flg  = PETSC_TRUE;
1288   ierr = PetscOptionsGetBool(NULL,"-cublas",&flg,NULL);CHKERRQ(ierr);
1289   if (flg) {
1290     PetscInt p;
1291     for (p = 0; p < PetscGlobalSize; ++p) {
1292       if (p == PetscGlobalRank) cublasShutdown();
1293       ierr = MPI_Barrier(PETSC_COMM_WORLD);CHKERRQ(ierr);
1294     }
1295   }
1296 #endif
1297 
1298   /* Can be destroyed only after all the options are used */
1299   ierr = PetscOptionsDestroy();CHKERRQ(ierr);
1300 
1301   PetscGlobalArgc = 0;
1302   PetscGlobalArgs = 0;
1303 
1304 #if defined(PETSC_USE_REAL___FLOAT128)
1305   ierr = MPI_Type_free(&MPIU___FLOAT128);CHKERRQ(ierr);
1306 #if defined(PETSC_HAVE_COMPLEX)
1307   ierr = MPI_Type_free(&MPIU___COMPLEX128);CHKERRQ(ierr);
1308 #endif
1309   ierr = MPI_Op_free(&MPIU_MAX);CHKERRQ(ierr);
1310   ierr = MPI_Op_free(&MPIU_MIN);CHKERRQ(ierr);
1311 #endif
1312 
1313 #if defined(PETSC_HAVE_COMPLEX)
1314 #if !defined(PETSC_HAVE_MPI_C_DOUBLE_COMPLEX)
1315   ierr = MPI_Type_free(&MPIU_C_DOUBLE_COMPLEX);CHKERRQ(ierr);
1316   ierr = MPI_Type_free(&MPIU_C_COMPLEX);CHKERRQ(ierr);
1317 #endif
1318 #endif
1319 
1320 #if (defined(PETSC_HAVE_COMPLEX) && !defined(PETSC_HAVE_MPI_C_DOUBLE_COMPLEX)) || defined(PETSC_USE_REAL___FLOAT128)
1321   ierr = MPI_Op_free(&MPIU_SUM);CHKERRQ(ierr);
1322 #endif
1323 
1324   ierr = MPI_Type_free(&MPIU_2SCALAR);CHKERRQ(ierr);
1325 #if defined(PETSC_USE_64BIT_INDICES) || !defined(MPI_2INT)
1326   ierr = MPI_Type_free(&MPIU_2INT);CHKERRQ(ierr);
1327 #endif
1328   ierr = MPI_Op_free(&PetscMaxSum_Op);CHKERRQ(ierr);
1329 
1330   /*
1331      Destroy any known inner MPI_Comm's and attributes pointing to them
1332      Note this will not destroy any new communicators the user has created.
1333 
1334      If all PETSc objects were not destroyed those left over objects will have hanging references to
1335      the MPI_Comms that were freed; but that is ok because those PETSc objects will never be used again
1336  */
1337   {
1338     PetscCommCounter *counter;
1339     PetscMPIInt      flg;
1340     MPI_Comm         icomm;
1341     union {MPI_Comm comm; void *ptr;} ucomm;
1342     ierr = MPI_Attr_get(PETSC_COMM_SELF,Petsc_InnerComm_keyval,&ucomm,&flg);CHKERRQ(ierr);
1343     if (flg) {
1344       icomm = ucomm.comm;
1345       ierr = MPI_Attr_get(icomm,Petsc_Counter_keyval,&counter,&flg);CHKERRQ(ierr);
1346       if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Inner MPI_Comm does not have expected tag/name counter, problem with corrupted memory");
1347 
1348       ierr = MPI_Attr_delete(PETSC_COMM_SELF,Petsc_InnerComm_keyval);CHKERRQ(ierr);
1349       ierr = MPI_Attr_delete(icomm,Petsc_Counter_keyval);CHKERRQ(ierr);
1350       ierr = MPI_Comm_free(&icomm);CHKERRQ(ierr);
1351     }
1352     ierr = MPI_Attr_get(PETSC_COMM_WORLD,Petsc_InnerComm_keyval,&ucomm,&flg);CHKERRQ(ierr);
1353     if (flg) {
1354       icomm = ucomm.comm;
1355       ierr = MPI_Attr_get(icomm,Petsc_Counter_keyval,&counter,&flg);CHKERRQ(ierr);
1356       if (!flg) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_ARG_CORRUPT,"Inner MPI_Comm does not have expected tag/name counter, problem with corrupted memory");
1357 
1358       ierr = MPI_Attr_delete(PETSC_COMM_WORLD,Petsc_InnerComm_keyval);CHKERRQ(ierr);
1359       ierr = MPI_Attr_delete(icomm,Petsc_Counter_keyval);CHKERRQ(ierr);
1360       ierr = MPI_Comm_free(&icomm);CHKERRQ(ierr);
1361     }
1362   }
1363 
1364   ierr = MPI_Keyval_free(&Petsc_Counter_keyval);CHKERRQ(ierr);
1365   ierr = MPI_Keyval_free(&Petsc_InnerComm_keyval);CHKERRQ(ierr);
1366   ierr = MPI_Keyval_free(&Petsc_OuterComm_keyval);CHKERRQ(ierr);
1367 
1368   if (PetscBeganMPI) {
1369 #if defined(PETSC_HAVE_MPI_FINALIZED)
1370     PetscMPIInt flag;
1371     ierr = MPI_Finalized(&flag);CHKERRQ(ierr);
1372     if (flag) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"MPI_Finalize() has already been called, even though MPI_Init() was called by PetscInitialize()");
1373 #endif
1374     ierr = MPI_Finalize();CHKERRQ(ierr);
1375   }
1376 /*
1377 
1378      Note: In certain cases PETSC_COMM_WORLD is never MPI_Comm_free()ed because
1379    the communicator has some outstanding requests on it. Specifically if the
1380    flag PETSC_HAVE_BROKEN_REQUEST_FREE is set (for IBM MPI implementation). See
1381    src/vec/utils/vpscat.c. Due to this the memory allocated in PetscCommDuplicate()
1382    is never freed as it should be. Thus one may obtain messages of the form
1383    [ 1] 8 bytes PetscCommDuplicate() line 645 in src/sys/mpiu.c indicating the
1384    memory was not freed.
1385 
1386 */
1387   ierr = PetscMallocClear();CHKERRQ(ierr);
1388 
1389   PetscInitializeCalled = PETSC_FALSE;
1390   PetscFinalizeCalled   = PETSC_TRUE;
1391   PetscFunctionReturn(ierr);
1392 }
1393 
1394 #if defined(PETSC_MISSING_LAPACK_lsame_)
1395 PETSC_EXTERN int lsame_(char *a,char *b)
1396 {
1397   if (*a == *b) return 1;
1398   if (*a + 32 == *b) return 1;
1399   if (*a - 32 == *b) return 1;
1400   return 0;
1401 }
1402 #endif
1403 
1404 #if defined(PETSC_MISSING_LAPACK_lsame)
1405 PETSC_EXTERN int lsame(char *a,char *b)
1406 {
1407   if (*a == *b) return 1;
1408   if (*a + 32 == *b) return 1;
1409   if (*a - 32 == *b) return 1;
1410   return 0;
1411 }
1412 #endif
1413