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