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