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