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