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