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