xref: /petsc/src/sys/objects/pinit.c (revision 3a336bb1c5354aa6a7f04f397c2159a565cb027a)
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     if (!threads) {
1079       threads = getenv("OMP_NUM_THREADS");
1080       if (threads) PetscCall(PetscInfo(NULL, "BLAS: Environment number of MKL threads %s given by OMP_NUM_THREADS\n", threads));
1081     }
1082   #elif defined(PETSC_HAVE_OPENBLAS_SET_NUM_THREADS)
1083     threads = getenv("OPENBLAS_NUM_THREADS");
1084     if (threads) PetscCall(PetscInfo(NULL, "BLAS: Environment number of OpenBLAS threads %s given by OPENBLAS_NUM_THREADS\n", threads));
1085     if (!threads) {
1086       threads = getenv("OMP_NUM_THREADS");
1087       if (threads) PetscCall(PetscInfo(NULL, "BLAS: Environment number of OpenBLAS threads %s given by OMP_NUM_THREADS\n", threads));
1088     }
1089   #endif
1090     if (threads) (void)sscanf(threads, "%" PetscInt_FMT, &PetscNumBLASThreads);
1091     PetscCall(PetscOptionsInt("-blas_num_threads", "Number of threads to use for BLAS operations", "None", PetscNumBLASThreads, &PetscNumBLASThreads, &flg));
1092     if (flg) PetscCall(PetscInfo(NULL, "BLAS: Command line number of BLAS thread %" PetscInt_FMT "given by -blas_num_threads\n", PetscNumBLASThreads));
1093     if (flg || threads) {
1094       PetscCall(PetscBLASSetNumThreads(PetscNumBLASThreads));
1095       if (blas_view_flag) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "BLAS: number of threads %" PetscInt_FMT "\n", PetscNumBLASThreads));
1096     }
1097   }
1098 #elif defined(PETSC_HAVE_APPLE_ACCELERATE)
1099   PetscCall(PetscInfo(NULL, "BLAS: Apple Accelerate library, thread support with no user control\n"));
1100   if (blas_view_flag) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "BLAS: Apple Accelerate library, thread support with no user control\n"));
1101 #else
1102   if (blas_view_flag) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "BLAS: no thread support\n"));
1103 #endif
1104   PetscOptionsEnd();
1105 
1106 #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
1107   /*
1108       Tell MPI about our own data representation converter, this would/should be used if extern32 is not supported by the MPI
1109 
1110       Currently not used because it is not supported by MPICH.
1111   */
1112   if (!PetscBinaryBigEndian()) PetscCallMPI(MPI_Register_datarep((char *)"petsc", PetscDataRep_read_conv_fn, PetscDataRep_write_conv_fn, PetscDataRep_extent_fn, NULL));
1113 #endif
1114 
1115 #if defined(PETSC_SERIALIZE_FUNCTIONS)
1116   PetscCall(PetscFPTCreate(10000));
1117 #endif
1118 
1119 #if defined(PETSC_HAVE_HWLOC)
1120   {
1121     PetscViewer viewer;
1122     PetscCall(PetscOptionsCreateViewer(PETSC_COMM_WORLD, NULL, NULL, "-process_view", &viewer, NULL, &flg));
1123     if (flg) {
1124       PetscCall(PetscProcessPlacementView(viewer));
1125       PetscCall(PetscViewerDestroy(&viewer));
1126     }
1127   }
1128 #endif
1129 
1130   flg = PETSC_TRUE;
1131   PetscCall(PetscOptionsGetBool(NULL, NULL, "-viewfromoptions", &flg, NULL));
1132   if (!flg) PetscCall(PetscOptionsPushCreateViewerOff(PETSC_TRUE));
1133 
1134 #if defined(PETSC_HAVE_ADIOS)
1135   PetscCallExternal(adios_init_noxml, PETSC_COMM_WORLD);
1136   PetscCallExternal(adios_declare_group, &Petsc_adios_group, "PETSc", "", adios_stat_default);
1137   PetscCallExternal(adios_select_method, Petsc_adios_group, "MPI", "", "");
1138   PetscCallExternal(adios_read_init_method, ADIOS_READ_METHOD_BP, PETSC_COMM_WORLD, "");
1139 #endif
1140 
1141 #if defined(__VALGRIND_H)
1142   PETSC_RUNNING_ON_VALGRIND = RUNNING_ON_VALGRIND ? PETSC_TRUE : PETSC_FALSE;
1143   #if defined(PETSC_USING_DARWIN) && defined(PETSC_BLASLAPACK_SDOT_RETURNS_DOUBLE)
1144   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"));
1145   #endif
1146 #endif
1147   /*
1148       Set flag that we are completely initialized
1149   */
1150   PetscInitializeCalled = PETSC_TRUE;
1151 
1152   PetscCall(PetscOptionsHasName(NULL, NULL, "-python", &flg));
1153   if (flg) PetscCall(PetscPythonInitialize(NULL, NULL));
1154 
1155   PetscCall(PetscOptionsHasName(NULL, NULL, "-mpi_linear_solver_server", &flg));
1156   if (PetscDefined(USE_SINGLE_LIBRARY) && flg) PetscCall(PCMPIServerBegin());
1157   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");
1158   PetscFunctionReturn(PETSC_SUCCESS);
1159 }
1160 
1161 // "Unknown section 'Environmental Variables'"
1162 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1163 /*@C
1164   PetscInitialize - Initializes the PETSc database and MPI.
1165   `PetscInitialize()` calls MPI_Init() if that has yet to be called,
1166   so this routine should always be called near the beginning of
1167   your program -- usually the very first line!
1168 
1169   Collective on `MPI_COMM_WORLD` or `PETSC_COMM_WORLD` if it has been set
1170 
1171   Input Parameters:
1172 + argc - count of number of command line arguments
1173 . args - the command line arguments
1174 . file - [optional] PETSc database file, append ":yaml" to filename to specify YAML options format.
1175           Use NULL or empty string to not check for code specific file.
1176           Also checks ~/.petscrc, .petscrc and petscrc.
1177           Use -skip_petscrc in the code specific file (or command line) to skip ~/.petscrc, .petscrc and petscrc files.
1178 - help - [optional] Help message to print, use NULL for no message
1179 
1180    If you wish PETSc code to run ONLY on a subcommunicator of `MPI_COMM_WORLD`, create that
1181    communicator first and assign it to `PETSC_COMM_WORLD` BEFORE calling `PetscInitialize()`. Thus if you are running a
1182    four process job and two processes will run PETSc and have `PetscInitialize()` and PetscFinalize() and two process will not,
1183    then do this. If ALL processes in the job are using `PetscInitialize()` and `PetscFinalize()` then you don't need to do this, even
1184    if different subcommunicators of the job are doing different things with PETSc.
1185 
1186   Options Database Keys:
1187 + -help [intro]                                       - prints help method for each option; if intro is given the program stops after printing the introductory help message
1188 . -start_in_debugger [noxterm,dbx,xdb,gdb,...]        - Starts program in debugger
1189 . -on_error_attach_debugger [noxterm,dbx,xdb,gdb,...] - Starts debugger when error detected
1190 . -on_error_emacs <machinename>                       - causes emacsclient to jump to error file
1191 . -on_error_abort                                     - calls `abort()` when error detected (no traceback)
1192 . -on_error_mpiabort                                  - calls `MPI_abort()` when error detected
1193 . -error_output_stdout                                - prints PETSc error messages to stdout instead of the default stderr
1194 . -error_output_none                                  - does not print the error messages (but handles errors in the same way as if this was not called)
1195 . -debugger_ranks [rank1,rank2,...]                   - Indicates ranks to start in debugger
1196 . -debugger_pause [sleeptime] (in seconds)            - Pauses debugger
1197 . -stop_for_debugger                                  - Print message on how to attach debugger manually to
1198                         process and wait (-debugger_pause) seconds for attachment
1199 . -malloc_dump                                        - prints a list of all unfreed memory at the end of the run
1200 . -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
1201 . -malloc_view                                        - show a list of all allocated memory during `PetscFinalize()`
1202 . -malloc_view_threshold <t>                          - only list memory allocations of size greater than t with -malloc_view
1203 . -malloc_requested_size                              - malloc logging will record the requested size rather than size after alignment
1204 . -fp_trap                                            - Stops on floating point exceptions
1205 . -no_signal_handler                                  - Indicates not to trap error signals
1206 . -shared_tmp                                         - indicates /tmp directory is shared by all processors
1207 . -not_shared_tmp                                     - each processor has own /tmp
1208 . -tmp                                                - alternative name of /tmp directory
1209 . -get_total_flops                                    - returns total flops done by all processors
1210 - -memory_view                                        - Print memory usage at end of run
1211 
1212   Options Database Keys for Option Database:
1213 + -skip_petscrc           - skip the default option files ~/.petscrc, .petscrc, petscrc
1214 . -options_monitor        - monitor all set options to standard output for the whole program run
1215 - -options_monitor_cancel - cancel options monitoring hard-wired using `PetscOptionsMonitorSet()`
1216 
1217    Options -options_monitor_{all,cancel} are
1218    position-independent and apply to all options set since the PETSc start.
1219    They can be used also in option files.
1220 
1221    See `PetscOptionsMonitorSet()` to do monitoring programmatically.
1222 
1223   Options Database Keys for Profiling:
1224    See Users-Manual: ch_profiling for details.
1225 + -info [filename][:[~]<list,of,classnames>[:[~]self]] - Prints verbose information. See `PetscInfo()`.
1226 . -log_sync                                            - Enable barrier synchronization for all events. This option is useful to debug imbalance within each event,
1227         however it slows things down and gives a distorted view of the overall runtime.
1228 . -log_trace [filename]                                - Print traces of all PETSc calls to the screen (useful to determine where a program
1229         hangs without running in the debugger).  See `PetscLogTraceBegin()`.
1230 . -log_view [:filename:format][,[:filename:format]...] - Prints summary of flop and timing information to screen or file, see `PetscLogView()` (up to 4 viewers)
1231 . -log_view_memory                                     - Includes in the summary from -log_view the memory used in each event, see `PetscLogView()`.
1232 . -log_view_gpu_time                                   - Includes in the summary from -log_view the time used in each GPU kernel, see `PetscLogView().
1233 . -log_exclude: <vec,mat,pc,ksp,snes>                  - excludes subset of object classes from logging
1234 . -log [filename]                                      - Logs profiling information in a dump file, see `PetscLogDump()`.
1235 . -log_all [filename]                                  - Same as `-log`.
1236 . -log_mpe [filename]                                  - Creates a logfile viewable by the utility Jumpshot (in MPICH distribution)
1237 . -log_perfstubs                                       - Starts a log handler with the perfstubs interface (which is used by TAU)
1238 . -log_nvtx                                            - Starts an nvtx log handler for use with Nsight
1239 . -viewfromoptions on,off                              - Enable or disable `XXXSetFromOptions()` calls, for applications with many small solves turn this off
1240 - -check_pointer_intensity 0,1,2                       - if pointers are checked for validity (debug version only), using 0 will result in faster code
1241 
1242   Options Database Keys for SAWs:
1243 + -saws_port <portnumber>        - port number to publish SAWs data, default is 8080
1244 . -saws_port_auto_select         - have SAWs select a new unique port number where it publishes the data, the URL is printed to the screen
1245                                    this is useful when you are running many jobs that utilize SAWs at the same time
1246 . -saws_log <filename>           - save a log of all SAWs communication
1247 . -saws_https <certificate file> - have SAWs use HTTPS instead of HTTP
1248 - -saws_root <directory>         - allow SAWs to have access to the given directory to search for requested resources and files
1249 
1250   Environmental Variables:
1251 +   `PETSC_TMP` - alternative tmp directory
1252 .   `PETSC_SHARED_TMP` - tmp is shared by all processes
1253 .   `PETSC_NOT_SHARED_TMP` - each process has its own private tmp
1254 .   `PETSC_OPTIONS` - a string containing additional options for petsc in the form of command line "-key value" pairs
1255 .   `PETSC_OPTIONS_YAML` - (requires configuring PETSc to use libyaml) a string containing additional options for petsc in the form of a YAML document
1256 .   `PETSC_VIEWER_SOCKET_PORT` - socket number to use for socket viewer
1257 -   `PETSC_VIEWER_SOCKET_MACHINE` - machine to use for socket viewer to connect to
1258 
1259   Level: beginner
1260 
1261   Note:
1262   If for some reason you must call `MPI_Init()` separately, call
1263   it before `PetscInitialize()`.
1264 
1265   Fortran Notes:
1266   In Fortran this routine can be called with
1267 .vb
1268        call PetscInitialize(ierr)
1269        call PetscInitialize(file,ierr) or
1270        call PetscInitialize(file,help,ierr)
1271 .ve
1272 
1273   If your main program is C but you call Fortran code that also uses PETSc you need to call `PetscInitializeFortran()` soon after
1274   calling `PetscInitialize()`.
1275 
1276   Options Database Key for Developers:
1277 . -checkfunctionlist - automatically checks that function lists associated with objects are correctly cleaned up. Produces messages of the form:
1278     "function name: MatInodeGetInodeSizes_C" if they are not cleaned up. This flag is always set for the test harness (in framework.py)
1279 
1280 .seealso: `PetscFinalize()`, `PetscInitializeFortran()`, `PetscGetArgs()`, `PetscInitializeNoArguments()`, `PetscLogGpuTime()`
1281 @*/
1282 PetscErrorCode PetscInitialize(int *argc, char ***args, const char file[], const char help[])
1283 {
1284   PetscMPIInt flag;
1285   const char *prog = "Unknown Name", *mpienv;
1286 
1287   PetscFunctionBegin;
1288   if (PetscInitializeCalled) PetscFunctionReturn(PETSC_SUCCESS);
1289   PetscCallMPI(MPI_Initialized(&flag));
1290   if (!flag) {
1291     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");
1292     PetscCall(PetscPreMPIInit_Private());
1293 #if defined(PETSC_HAVE_MPI_INIT_THREAD)
1294     {
1295       PetscMPIInt provided;
1296       PetscCallMPI(MPI_Init_thread(argc, args, PETSC_MPI_THREAD_REQUIRED == PETSC_DECIDE ? MPI_THREAD_FUNNELED : PETSC_MPI_THREAD_REQUIRED, &provided));
1297       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");
1298       if (PETSC_MPI_THREAD_REQUIRED == PETSC_DECIDE) PETSC_MPI_THREAD_REQUIRED = MPI_THREAD_FUNNELED; // assign it a valid value after check-up
1299     }
1300 #else
1301     PetscCallMPI(MPI_Init(argc, args));
1302 #endif
1303     if (PetscDefined(HAVE_MPIUNI)) {
1304       mpienv = getenv("PMI_SIZE");
1305       if (!mpienv) mpienv = getenv("OMPI_COMM_WORLD_SIZE");
1306       if (mpienv) {
1307         PetscInt isize;
1308         PetscCall(PetscOptionsStringToInt(mpienv, &isize));
1309         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");
1310         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");
1311       }
1312     }
1313     PetscBeganMPI = PETSC_TRUE;
1314   }
1315 
1316   if (argc && *argc) prog = **args;
1317   if (argc && args) {
1318     PetscGlobalArgc = *argc;
1319     PetscGlobalArgs = *args;
1320   }
1321   PetscCall(PetscInitialize_Common(prog, file, help, PETSC_FALSE, PETSC_FALSE, 0));
1322   PetscFunctionReturn(PETSC_SUCCESS);
1323 }
1324 
1325 PETSC_INTERN PetscObject *PetscObjects;
1326 PETSC_INTERN PetscInt     PetscObjectsCounts;
1327 PETSC_INTERN PetscInt     PetscObjectsMaxCounts;
1328 PETSC_INTERN PetscBool    PetscObjectsLog;
1329 
1330 /*
1331     Frees all the MPI types and operations that PETSc may have created
1332 */
1333 PetscErrorCode PetscFreeMPIResources(void)
1334 {
1335   PetscFunctionBegin;
1336 #if defined(PETSC_HAVE_REAL___FLOAT128)
1337   PetscCallMPI(MPI_Type_free(&MPIU___FLOAT128));
1338   #if defined(PETSC_HAVE_COMPLEX)
1339   PetscCallMPI(MPI_Type_free(&MPIU___COMPLEX128));
1340   #endif
1341 #endif
1342 #if defined(PETSC_HAVE_REAL___FP16)
1343   PetscCallMPI(MPI_Type_free(&MPIU___FP16));
1344 #endif
1345 
1346 #if defined(PETSC_USE_REAL___FLOAT128) || defined(PETSC_USE_REAL___FP16)
1347   PetscCallMPI(MPI_Op_free(&MPIU_SUM));
1348   PetscCallMPI(MPI_Op_free(&MPIU_MAX));
1349   PetscCallMPI(MPI_Op_free(&MPIU_MIN));
1350 #elif defined(PETSC_HAVE_REAL___FLOAT128) || defined(PETSC_HAVE_REAL___FP16)
1351   PetscCallMPI(MPI_Op_free(&MPIU_SUM___FP16___FLOAT128));
1352 #endif
1353 
1354   PetscCallMPI(MPI_Type_free(&MPIU_2SCALAR));
1355   PetscCallMPI(MPI_Type_free(&MPIU_REAL_INT));
1356   PetscCallMPI(MPI_Type_free(&MPIU_SCALAR_INT));
1357 #if defined(PETSC_USE_64BIT_INDICES)
1358   PetscCallMPI(MPI_Type_free(&MPIU_2INT));
1359 #endif
1360   PetscCallMPI(MPI_Type_free(&MPI_4INT));
1361   PetscCallMPI(MPI_Type_free(&MPIU_4INT));
1362   PetscCallMPI(MPI_Op_free(&MPIU_MAXSUM_OP));
1363   PetscCallMPI(MPI_Op_free(&Petsc_Garbage_SetIntersectOp));
1364   PetscFunctionReturn(PETSC_SUCCESS);
1365 }
1366 
1367 PETSC_INTERN PetscErrorCode PetscLogFinalize(void);
1368 
1369 /*@C
1370   PetscFinalize - Checks for options to be called at the conclusion
1371   of the program. `MPI_Finalize()` is called only if the user had not
1372   called `MPI_Init()` before calling `PetscInitialize()`.
1373 
1374   Collective on `PETSC_COMM_WORLD`
1375 
1376   Options Database Keys:
1377 + -options_view                    - Calls `PetscOptionsView()`
1378 . -options_left                    - Prints unused options that remain in the database
1379 . -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
1380 . -mpidump                         - Calls PetscMPIDump()
1381 . -malloc_dump <optional filename> - Calls `PetscMallocDump()`, displays all memory allocated that has not been freed
1382 . -memory_view                     - Prints total memory usage
1383 - -malloc_view <optional filename> - Prints list of all memory allocated and in what functions
1384 
1385   Level: beginner
1386 
1387   Note:
1388   See `PetscInitialize()` for other runtime options.
1389 
1390 .seealso: `PetscInitialize()`, `PetscOptionsView()`, `PetscMallocDump()`, `PetscMPIDump()`, `PetscEnd()`
1391 @*/
1392 PetscErrorCode PetscFinalize(void)
1393 {
1394   PetscMPIInt rank;
1395   PetscInt    nopt;
1396   PetscBool   flg1 = PETSC_FALSE, flg2 = PETSC_FALSE, flg3 = PETSC_FALSE;
1397   PetscBool   flg;
1398   char        mname[PETSC_MAX_PATH_LEN];
1399 
1400   PetscFunctionBegin;
1401   PetscCheck(PetscInitializeCalled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "PetscInitialize() must be called before PetscFinalize()");
1402   PetscCall(PetscInfo(NULL, "PetscFinalize() called\n"));
1403 
1404   PetscCall(PetscOptionsHasName(NULL, NULL, "-mpi_linear_solver_server", &flg));
1405   if (PetscDefined(USE_SINGLE_LIBRARY) && flg) PetscCall(PCMPIServerEnd());
1406 
1407   /* Clean up Garbage automatically on COMM_SELF and COMM_WORLD at finalize */
1408   {
1409     union
1410     {
1411       MPI_Comm comm;
1412       void    *ptr;
1413     } ucomm;
1414     PetscMPIInt flg;
1415     void       *tmp;
1416 
1417     PetscCallMPI(MPI_Comm_get_attr(PETSC_COMM_SELF, Petsc_InnerComm_keyval, &ucomm, &flg));
1418     if (flg) PetscCallMPI(MPI_Comm_get_attr(ucomm.comm, Petsc_Garbage_HMap_keyval, &tmp, &flg));
1419     if (flg) PetscCall(PetscGarbageCleanup(PETSC_COMM_SELF));
1420     PetscCallMPI(MPI_Comm_get_attr(PETSC_COMM_WORLD, Petsc_InnerComm_keyval, &ucomm, &flg));
1421     if (flg) PetscCallMPI(MPI_Comm_get_attr(ucomm.comm, Petsc_Garbage_HMap_keyval, &tmp, &flg));
1422     if (flg) PetscCall(PetscGarbageCleanup(PETSC_COMM_WORLD));
1423   }
1424 
1425   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1426 #if defined(PETSC_HAVE_ADIOS)
1427   PetscCallExternal(adios_read_finalize_method, ADIOS_READ_METHOD_BP_AGGREGATE);
1428   PetscCallExternal(adios_finalize, rank);
1429 #endif
1430   PetscCall(PetscOptionsHasName(NULL, NULL, "-citations", &flg));
1431   if (flg) {
1432     char *cits, filename[PETSC_MAX_PATH_LEN];
1433     FILE *fd = PETSC_STDOUT;
1434 
1435     PetscCall(PetscOptionsGetString(NULL, NULL, "-citations", filename, sizeof(filename), NULL));
1436     if (filename[0]) PetscCall(PetscFOpen(PETSC_COMM_WORLD, filename, "w", &fd));
1437     PetscCall(PetscSegBufferGet(PetscCitationsList, 1, &cits));
1438     cits[0] = 0;
1439     PetscCall(PetscSegBufferExtractAlloc(PetscCitationsList, &cits));
1440     PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "If you publish results based on this computation please cite the following:\n"));
1441     PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "===========================================================================\n"));
1442     PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "%s", cits));
1443     PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "===========================================================================\n"));
1444     PetscCall(PetscFClose(PETSC_COMM_WORLD, fd));
1445     PetscCall(PetscFree(cits));
1446   }
1447   PetscCall(PetscSegBufferDestroy(&PetscCitationsList));
1448 
1449 #if defined(PETSC_SERIALIZE_FUNCTIONS)
1450   PetscCall(PetscFPTDestroy());
1451 #endif
1452 
1453 #if defined(PETSC_HAVE_SAWS)
1454   flg = PETSC_FALSE;
1455   PetscCall(PetscOptionsGetBool(NULL, NULL, "-saw_options", &flg, NULL));
1456   if (flg) PetscCall(PetscOptionsSAWsDestroy());
1457 #endif
1458 
1459 #if defined(PETSC_HAVE_X)
1460   flg1 = PETSC_FALSE;
1461   PetscCall(PetscOptionsGetBool(NULL, NULL, "-x_virtual", &flg1, NULL));
1462   if (flg1) {
1463     /*  this is a crude hack, but better than nothing */
1464     PetscCall(PetscPOpen(PETSC_COMM_WORLD, NULL, "pkill -15 Xvfb", "r", NULL));
1465   }
1466 #endif
1467 
1468 #if !defined(PETSC_HAVE_THREADSAFETY)
1469   PetscCall(PetscOptionsGetBool(NULL, NULL, "-memory_view", &flg2, NULL));
1470   if (flg2) PetscCall(PetscMemoryView(PETSC_VIEWER_STDOUT_WORLD, "Summary of Memory Usage in PETSc\n"));
1471 #endif
1472 
1473   if (PetscDefined(USE_LOG)) {
1474     flg1 = PETSC_FALSE;
1475     PetscCall(PetscOptionsGetBool(NULL, NULL, "-get_total_flops", &flg1, NULL));
1476     if (flg1) {
1477       PetscLogDouble flops = 0;
1478       PetscCallMPI(MPI_Reduce(&petsc_TotalFlops, &flops, 1, MPI_DOUBLE, MPI_SUM, 0, PETSC_COMM_WORLD));
1479       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Total flops over all processors %g\n", flops));
1480     }
1481   }
1482 
1483   if (PetscDefined(USE_LOG) && PetscDefined(HAVE_MPE)) {
1484     mname[0] = 0;
1485     PetscCall(PetscOptionsGetString(NULL, NULL, "-log_mpe", mname, sizeof(mname), &flg1));
1486     if (flg1) PetscCall(PetscLogMPEDump(mname[0] ? mname : NULL));
1487   }
1488 
1489 #if defined(PETSC_HAVE_KOKKOS)
1490   // Free petsc/kokkos stuff before the potentially non-null petsc default gpu stream is destroyed by PetscObjectRegisterDestroyAll
1491   if (PetscKokkosInitialized) {
1492     PetscCall(PetscKokkosFinalize_Private());
1493     PetscKokkosInitialized = PETSC_FALSE;
1494   }
1495 #endif
1496 
1497   // Free all objects registered with PetscObjectRegisterDestroy() such as PETSC_VIEWER_XXX_().
1498   PetscCall(PetscObjectRegisterDestroyAll());
1499 
1500   if (PetscDefined(USE_LOG)) {
1501     PetscCall(PetscOptionsPushCreateViewerOff(PETSC_FALSE));
1502     PetscCall(PetscLogViewFromOptions());
1503     PetscCall(PetscOptionsPopCreateViewerOff());
1504     //  It should be turned on with PetscLogGpuTime() and never turned off except in this place
1505     PetscLogGpuTimeFlag = PETSC_FALSE;
1506 
1507     // Free any objects created by the last block of code.
1508     PetscCall(PetscObjectRegisterDestroyAll());
1509 
1510     mname[0] = 0;
1511     PetscCall(PetscOptionsGetString(NULL, NULL, "-log_all", mname, sizeof(mname), &flg1));
1512     PetscCall(PetscOptionsGetString(NULL, NULL, "-log", mname, sizeof(mname), &flg2));
1513     if (flg1 || flg2) PetscCall(PetscLogDump(mname));
1514   }
1515 
1516   flg1 = PETSC_FALSE;
1517   PetscCall(PetscOptionsGetBool(NULL, NULL, "-no_signal_handler", &flg1, NULL));
1518   if (!flg1) PetscCall(PetscPopSignalHandler());
1519   flg1 = PETSC_FALSE;
1520   PetscCall(PetscOptionsGetBool(NULL, NULL, "-mpidump", &flg1, NULL));
1521   if (flg1) PetscCall(PetscMPIDump(stdout));
1522   flg1 = PETSC_FALSE;
1523   flg2 = PETSC_FALSE;
1524   /* preemptive call to avoid listing this option in options table as unused */
1525   PetscCall(PetscOptionsHasName(NULL, NULL, "-malloc_dump", &flg1));
1526   PetscCall(PetscOptionsHasName(NULL, NULL, "-objects_dump", &flg1));
1527   PetscCall(PetscOptionsGetBool(NULL, NULL, "-options_view", &flg2, NULL));
1528 
1529   if (flg2) { PetscCall(PetscOptionsView(NULL, PETSC_VIEWER_STDOUT_WORLD)); }
1530 
1531   /* to prevent PETSc -options_left from warning */
1532   PetscCall(PetscOptionsHasName(NULL, NULL, "-nox", &flg1));
1533   PetscCall(PetscOptionsHasName(NULL, NULL, "-nox_warning", &flg1));
1534 
1535   flg3 = PETSC_FALSE; /* default value is required */
1536   PetscCall(PetscOptionsGetBool(NULL, NULL, "-options_left", &flg3, &flg1));
1537   if (!flg1) flg3 = PETSC_TRUE;
1538   if (flg3) {
1539     if (!flg2 && flg1) { /* have not yet printed the options */
1540       PetscCall(PetscOptionsView(NULL, PETSC_VIEWER_STDOUT_WORLD));
1541     }
1542     PetscCall(PetscOptionsAllUsed(NULL, &nopt));
1543     if (nopt) {
1544       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "WARNING! There are options you set that were not used!\n"));
1545       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "WARNING! could be spelling mistake, etc!\n"));
1546       if (nopt == 1) {
1547         PetscCall(PetscPrintf(PETSC_COMM_WORLD, "There is one unused database option. It is:\n"));
1548       } else {
1549         PetscCall(PetscPrintf(PETSC_COMM_WORLD, "There are %" PetscInt_FMT " unused database options. They are:\n", nopt));
1550       }
1551     } else if (flg3 && flg1) {
1552       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "There are no unused options.\n"));
1553     }
1554     PetscCall(PetscOptionsLeft(NULL));
1555   }
1556 
1557 #if defined(PETSC_HAVE_SAWS)
1558   if (!PetscGlobalRank) {
1559     PetscCall(PetscStackSAWsViewOff());
1560     PetscCallSAWs(SAWs_Finalize, ());
1561   }
1562 #endif
1563 
1564   /*
1565        List all objects the user may have forgot to free
1566   */
1567   if (PetscDefined(USE_LOG) && PetscObjectsLog) {
1568     PetscCall(PetscOptionsHasName(NULL, NULL, "-objects_dump", &flg1));
1569     if (flg1) {
1570       MPI_Comm local_comm;
1571       char     string[64];
1572 
1573       PetscCall(PetscOptionsGetString(NULL, NULL, "-objects_dump", string, sizeof(string), NULL));
1574       PetscCallMPI(MPI_Comm_dup(PETSC_COMM_WORLD, &local_comm));
1575       PetscCall(PetscSequentialPhaseBegin_Private(local_comm, 1));
1576       PetscCall(PetscObjectsDump(stdout, (string[0] == 'a') ? PETSC_TRUE : PETSC_FALSE));
1577       PetscCall(PetscSequentialPhaseEnd_Private(local_comm, 1));
1578       PetscCallMPI(MPI_Comm_free(&local_comm));
1579     }
1580   }
1581 
1582   PetscObjectsCounts    = 0;
1583   PetscObjectsMaxCounts = 0;
1584   PetscCall(PetscFree(PetscObjects));
1585 
1586   /*
1587      Destroy any packages that registered a finalize
1588   */
1589   PetscCall(PetscRegisterFinalizeAll());
1590 
1591   PetscCall(PetscLogFinalize());
1592 
1593   /*
1594      Print PetscFunctionLists that have not been properly freed
1595   */
1596   if (PetscPrintFunctionList) PetscCall(PetscFunctionListPrintAll());
1597 
1598   if (petsc_history) {
1599     PetscCall(PetscCloseHistoryFile(&petsc_history));
1600     petsc_history = NULL;
1601   }
1602   PetscCall(PetscOptionsHelpPrintedDestroy(&PetscOptionsHelpPrintedSingleton));
1603   PetscCall(PetscInfoDestroy());
1604 
1605 #if !defined(PETSC_HAVE_THREADSAFETY)
1606   if (!(PETSC_RUNNING_ON_VALGRIND)) {
1607     char  fname[PETSC_MAX_PATH_LEN];
1608     char  sname[PETSC_MAX_PATH_LEN];
1609     FILE *fd;
1610     int   err;
1611 
1612     flg2 = PETSC_FALSE;
1613     flg3 = PETSC_FALSE;
1614     if (PetscDefined(USE_DEBUG)) PetscCall(PetscOptionsGetBool(NULL, NULL, "-malloc_test", &flg2, NULL));
1615     PetscCall(PetscOptionsGetBool(NULL, NULL, "-malloc_debug", &flg3, NULL));
1616     fname[0] = 0;
1617     PetscCall(PetscOptionsGetString(NULL, NULL, "-malloc_dump", fname, sizeof(fname), &flg1));
1618     if (flg1 && fname[0]) {
1619       PetscCall(PetscSNPrintf(sname, sizeof(sname), "%s_%d", fname, rank));
1620       fd = fopen(sname, "w");
1621       PetscCheck(fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open log file: %s", sname);
1622       PetscCall(PetscMallocDump(fd));
1623       err = fclose(fd);
1624       PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file");
1625     } else if (flg1 || flg2 || flg3) {
1626       MPI_Comm local_comm;
1627 
1628       PetscCallMPI(MPI_Comm_dup(PETSC_COMM_WORLD, &local_comm));
1629       PetscCall(PetscSequentialPhaseBegin_Private(local_comm, 1));
1630       PetscCall(PetscMallocDump(stdout));
1631       PetscCall(PetscSequentialPhaseEnd_Private(local_comm, 1));
1632       PetscCallMPI(MPI_Comm_free(&local_comm));
1633     }
1634     fname[0] = 0;
1635     PetscCall(PetscOptionsGetString(NULL, NULL, "-malloc_view", fname, sizeof(fname), &flg1));
1636     if (flg1 && fname[0]) {
1637       PetscCall(PetscSNPrintf(sname, sizeof(sname), "%s_%d", fname, rank));
1638       fd = fopen(sname, "w");
1639       PetscCheck(fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open log file: %s", sname);
1640       PetscCall(PetscMallocView(fd));
1641       err = fclose(fd);
1642       PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file");
1643     } else if (flg1) {
1644       MPI_Comm local_comm;
1645 
1646       PetscCallMPI(MPI_Comm_dup(PETSC_COMM_WORLD, &local_comm));
1647       PetscCall(PetscSequentialPhaseBegin_Private(local_comm, 1));
1648       PetscCall(PetscMallocView(stdout));
1649       PetscCall(PetscSequentialPhaseEnd_Private(local_comm, 1));
1650       PetscCallMPI(MPI_Comm_free(&local_comm));
1651     }
1652   }
1653 #endif
1654 
1655   /*
1656      Close any open dynamic libraries
1657   */
1658   PetscCall(PetscFinalize_DynamicLibraries());
1659 
1660   /* Can be destroyed only after all the options are used */
1661   PetscCall(PetscOptionsDestroyDefault());
1662 
1663   PetscGlobalArgc = 0;
1664   PetscGlobalArgs = NULL;
1665 
1666 #if defined(PETSC_HAVE_NVSHMEM)
1667   if (PetscBeganNvshmem) {
1668     PetscCall(PetscNvshmemFinalize());
1669     PetscBeganNvshmem = PETSC_FALSE;
1670   }
1671 #endif
1672 
1673   PetscCall(PetscFreeMPIResources());
1674 
1675   /*
1676      Destroy any known inner MPI_Comm's and attributes pointing to them
1677      Note this will not destroy any new communicators the user has created.
1678 
1679      If all PETSc objects were not destroyed those left over objects will have hanging references to
1680      the MPI_Comms that were freed; but that is ok because those PETSc objects will never be used again
1681  */
1682   {
1683     PetscCommCounter *counter;
1684     PetscMPIInt       flg;
1685     MPI_Comm          icomm;
1686     union
1687     {
1688       MPI_Comm comm;
1689       void    *ptr;
1690     } ucomm;
1691     PetscCallMPI(MPI_Comm_get_attr(PETSC_COMM_SELF, Petsc_InnerComm_keyval, &ucomm, &flg));
1692     if (flg) {
1693       icomm = ucomm.comm;
1694       PetscCallMPI(MPI_Comm_get_attr(icomm, Petsc_Counter_keyval, &counter, &flg));
1695       PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Inner MPI_Comm does not have expected tag/name counter, problem with corrupted memory");
1696 
1697       PetscCallMPI(MPI_Comm_delete_attr(PETSC_COMM_SELF, Petsc_InnerComm_keyval));
1698       PetscCallMPI(MPI_Comm_delete_attr(icomm, Petsc_Counter_keyval));
1699       PetscCallMPI(MPI_Comm_free(&icomm));
1700     }
1701     PetscCallMPI(MPI_Comm_get_attr(PETSC_COMM_WORLD, Petsc_InnerComm_keyval, &ucomm, &flg));
1702     if (flg) {
1703       icomm = ucomm.comm;
1704       PetscCallMPI(MPI_Comm_get_attr(icomm, Petsc_Counter_keyval, &counter, &flg));
1705       PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_ARG_CORRUPT, "Inner MPI_Comm does not have expected tag/name counter, problem with corrupted memory");
1706 
1707       PetscCallMPI(MPI_Comm_delete_attr(PETSC_COMM_WORLD, Petsc_InnerComm_keyval));
1708       PetscCallMPI(MPI_Comm_delete_attr(icomm, Petsc_Counter_keyval));
1709       PetscCallMPI(MPI_Comm_free(&icomm));
1710     }
1711   }
1712 
1713   PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Counter_keyval));
1714   PetscCallMPI(MPI_Comm_free_keyval(&Petsc_InnerComm_keyval));
1715   PetscCallMPI(MPI_Comm_free_keyval(&Petsc_OuterComm_keyval));
1716   PetscCallMPI(MPI_Comm_free_keyval(&Petsc_ShmComm_keyval));
1717   PetscCallMPI(MPI_Comm_free_keyval(&Petsc_CreationIdx_keyval));
1718   PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Garbage_HMap_keyval));
1719 
1720   // Free keyvals which may be silently created by some routines
1721   if (Petsc_SharedWD_keyval != MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_free_keyval(&Petsc_SharedWD_keyval));
1722   if (Petsc_SharedTmp_keyval != MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_free_keyval(&Petsc_SharedTmp_keyval));
1723 
1724   PetscCall(PetscSpinlockDestroy(&PetscViewerASCIISpinLockOpen));
1725   PetscCall(PetscSpinlockDestroy(&PetscViewerASCIISpinLockStdout));
1726   PetscCall(PetscSpinlockDestroy(&PetscViewerASCIISpinLockStderr));
1727   PetscCall(PetscSpinlockDestroy(&PetscCommSpinLock));
1728 
1729   if (PetscBeganMPI) {
1730     PetscMPIInt flag;
1731     PetscCallMPI(MPI_Finalized(&flag));
1732     PetscCheck(!flag, PETSC_COMM_SELF, PETSC_ERR_LIB, "MPI_Finalize() has already been called, even though MPI_Init() was called by PetscInitialize()");
1733     /* wait until the very last moment to disable error handling */
1734     PetscErrorHandlingInitialized = PETSC_FALSE;
1735     PetscCallMPI(MPI_Finalize());
1736   } else PetscErrorHandlingInitialized = PETSC_FALSE;
1737 
1738   /*
1739 
1740      Note: In certain cases PETSC_COMM_WORLD is never MPI_Comm_free()ed because
1741    the communicator has some outstanding requests on it. Specifically if the
1742    flag PETSC_HAVE_BROKEN_REQUEST_FREE is set (for IBM MPI implementation). See
1743    src/vec/utils/vpscat.c. Due to this the memory allocated in PetscCommDuplicate()
1744    is never freed as it should be. Thus one may obtain messages of the form
1745    [ 1] 8 bytes PetscCommDuplicate() line 645 in src/sys/mpiu.c indicating the
1746    memory was not freed.
1747 
1748 */
1749   PetscCall(PetscMallocClear());
1750   PetscCall(PetscStackReset());
1751 
1752   PetscInitializeCalled = PETSC_FALSE;
1753   PetscFinalizeCalled   = PETSC_TRUE;
1754 #if defined(PETSC_USE_COVERAGE)
1755   /*
1756      flush gcov, otherwise during CI the flushing continues into the next pipeline resulting in git not being able to delete directories since the
1757      gcov files are still being added to the directories as git tries to remove the directories.
1758    */
1759   __gcov_flush();
1760 #endif
1761   /* To match PetscFunctionBegin() at the beginning of this function */
1762   PetscStackClearTop;
1763   return PETSC_SUCCESS;
1764 }
1765 
1766 #if defined(PETSC_MISSING_LAPACK_lsame_)
1767 PETSC_EXTERN int lsame_(char *a, char *b)
1768 {
1769   if (*a == *b) return 1;
1770   if (*a + 32 == *b) return 1;
1771   if (*a - 32 == *b) return 1;
1772   return 0;
1773 }
1774 #endif
1775 
1776 #if defined(PETSC_MISSING_LAPACK_lsame)
1777 PETSC_EXTERN int lsame(char *a, char *b)
1778 {
1779   if (*a == *b) return 1;
1780   if (*a + 32 == *b) return 1;
1781   if (*a - 32 == *b) return 1;
1782   return 0;
1783 }
1784 #endif
1785