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