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