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