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