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