xref: /petsc/src/sys/objects/pinit.c (revision 16dc8964ca763700383c940ec0bdd667c5da14cf)
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);CHKERRQ(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);CHKERRQ(ierr);
205     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(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, also checks ~/.petscrc, .petscrc and petscrc.
672           Use NULL to not check for code specific file.
673           Use -skip_petscrc in the code specific file (or command line) to skip ~/.petscrc, .petscrc and petscrc files.
674 -  help - [optional] Help message to print, use NULL for no message
675 
676    If you wish PETSc code to run ONLY on a subcommunicator of MPI_COMM_WORLD, create that
677    communicator first and assign it to PETSC_COMM_WORLD BEFORE calling PetscInitialize(). Thus if you are running a
678    four process job and two processes will run PETSc and have PetscInitialize() and PetscFinalize() and two process will not,
679    then do this. If ALL processes in the job are using PetscInitialize() and PetscFinalize() then you don't need to do this, even
680    if different subcommunicators of the job are doing different things with PETSc.
681 
682    Options Database Keys:
683 +  -help [intro] - prints help method for each option; if intro is given the program stops after printing the introductory help message
684 .  -start_in_debugger [noxterm,dbx,xdb,gdb,...] - Starts program in debugger
685 .  -on_error_attach_debugger [noxterm,dbx,xdb,gdb,...] - Starts debugger when error detected
686 .  -on_error_emacs <machinename> - causes emacsclient to jump to error file
687 .  -on_error_abort - calls abort() when error detected (no traceback)
688 .  -on_error_mpiabort - calls MPI_abort() when error detected
689 .  -error_output_stderr - prints error messages to stderr instead of the default stdout
690 .  -error_output_none - does not print the error messages (but handles errors in the same way as if this was not called)
691 .  -debugger_ranks [rank1,rank2,...] - Indicates ranks to start in debugger
692 .  -debugger_pause [sleeptime] (in seconds) - Pauses debugger
693 .  -stop_for_debugger - Print message on how to attach debugger manually to
694                         process and wait (-debugger_pause) seconds for attachment
695 .  -malloc - Indicates use of PETSc error-checking malloc (on by default for debug version of libraries) (deprecated, use -malloc_debug)
696 .  -malloc no - Indicates not to use error-checking malloc (deprecated, use -malloc_debug no)
697 .  -malloc_debug - check for memory corruption at EVERY malloc or free, see PetscMallocSetDebug()
698 .  -malloc_dump - prints a list of all unfreed memory at the end of the run
699 .  -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
700 .  -malloc_view - show a list of all allocated memory during PetscFinalize()
701 .  -malloc_view_threshold <t> - only list memory allocations of size greater than t with -malloc_view
702 .  -malloc_requested_size - malloc logging will record the requested size rather than size after alignment
703 .  -fp_trap - Stops on floating point exceptions
704 .  -no_signal_handler - Indicates not to trap error signals
705 .  -shared_tmp - indicates /tmp directory is shared by all processors
706 .  -not_shared_tmp - each processor has own /tmp
707 .  -tmp - alternative name of /tmp directory
708 .  -get_total_flops - returns total flops done by all processors
709 -  -memory_view - Print memory usage at end of run
710 
711    Options Database Keys for Option Database:
712 +  -skip_petscrc - skip the default option files ~/.petscrc, .petscrc, petscrc
713 .  -options_monitor - monitor all set options to standard output for the whole program run
714 -  -options_monitor_cancel - cancel options monitoring hard-wired using PetscOptionsMonitorSet()
715 
716    Options -options_monitor_{all,cancel} are
717    position-independent and apply to all options set since the PETSc start.
718    They can be used also in option files.
719 
720    See PetscOptionsMonitorSet() to do monitoring programmatically.
721 
722    Options Database Keys for Profiling:
723    See Users-Manual: ch_profiling for details.
724 +  -info [filename][:[~]<list,of,classnames>[:[~]self]] - Prints verbose information. See PetscInfo().
725 .  -log_sync - Enable barrier synchronization for all events. This option is useful to debug imbalance within each event,
726         however it slows things down and gives a distorted view of the overall runtime.
727 .  -log_trace [filename] - Print traces of all PETSc calls to the screen (useful to determine where a program
728         hangs without running in the debugger).  See PetscLogTraceBegin().
729 .  -log_view [:filename:format] - Prints summary of flop and timing information to screen or file, see PetscLogView().
730 .  -log_view_memory - Includes in the summary from -log_view the memory used in each method, see PetscLogView().
731 .  -log_summary [filename] - (Deprecated, use -log_view) Prints summary of flop and timing information to screen. If the filename is specified the
732         summary is written to the file.  See PetscLogView().
733 .  -log_exclude: <vec,mat,pc,ksp,snes> - excludes subset of object classes from logging
734 .  -log_all [filename] - Logs extensive profiling information  See PetscLogDump().
735 .  -log [filename] - Logs basic profiline information  See PetscLogDump().
736 .  -log_mpe [filename] - Creates a logfile viewable by the utility Jumpshot (in MPICH distribution)
737 .  -viewfromoptions on,off - Enable or disable XXXSetFromOptions() calls, for applications with many small solves turn this off
738 -  -check_pointer_intensity 0,1,2 - if pointers are checked for validity (debug version only), using 0 will result in faster code
739 
740     Only one of -log_trace, -log_view, -log_view, -log_all, -log, or -log_mpe may be used at a time
741 
742    Options Database Keys for SAWs:
743 +  -saws_port <portnumber> - port number to publish SAWs data, default is 8080
744 .  -saws_port_auto_select - have SAWs select a new unique port number where it publishes the data, the URL is printed to the screen
745                             this is useful when you are running many jobs that utilize SAWs at the same time
746 .  -saws_log <filename> - save a log of all SAWs communication
747 .  -saws_https <certificate file> - have SAWs use HTTPS instead of HTTP
748 -  -saws_root <directory> - allow SAWs to have access to the given directory to search for requested resources and files
749 
750    Environmental Variables:
751 +   PETSC_TMP - alternative tmp directory
752 .   PETSC_SHARED_TMP - tmp is shared by all processes
753 .   PETSC_NOT_SHARED_TMP - each process has its own private tmp
754 .   PETSC_OPTIONS - a string containing additional options for petsc in the form of command line "-key value" pairs
755 .   PETSC_OPTIONS_YAML - (requires configuring PETSc to use libyaml) a string containing additional options for petsc in the form of a YAML document
756 .   PETSC_VIEWER_SOCKET_PORT - socket number to use for socket viewer
757 -   PETSC_VIEWER_SOCKET_MACHINE - machine to use for socket viewer to connect to
758 
759 
760    Level: beginner
761 
762    Notes:
763    If for some reason you must call MPI_Init() separately, call
764    it before PetscInitialize().
765 
766    Fortran Version:
767    In Fortran this routine has the format
768 $       call PetscInitialize(file,ierr)
769 
770 +   ierr - error return code
771 -  file - [optional] PETSc database file, also checks ~/.petscrc, .petscrc and petscrc.
772           Use PETSC_NULL_CHARACTER to not check for code specific file.
773           Use -skip_petscrc in the code specific file (or command line) to skip ~/.petscrc, .petscrc and petscrc files.
774 
775    Important Fortran Note:
776    In Fortran, you MUST use PETSC_NULL_CHARACTER to indicate a
777    null character string; you CANNOT just use NULL as
778    in the C version. See Users-Manual: ch_fortran for details.
779 
780    If your main program is C but you call Fortran code that also uses PETSc you need to call PetscInitializeFortran() soon after
781    calling PetscInitialize().
782 
783 .seealso: PetscFinalize(), PetscInitializeFortran(), PetscGetArgs(), PetscInitializeNoArguments()
784 
785 @*/
786 PetscErrorCode  PetscInitialize(int *argc,char ***args,const char file[],const char help[])
787 {
788   PetscErrorCode ierr;
789   PetscMPIInt    flag, size;
790   PetscBool      flg = PETSC_TRUE;
791   char           hostname[256];
792 
793   PetscFunctionBegin;
794   if (PetscInitializeCalled) PetscFunctionReturn(0);
795   /*
796       The checking over compatible runtime libraries is complicated by the MPI ABI initiative
797       https://wiki.mpich.org/mpich/index.php/ABI_Compatibility_Initiative which started with
798         MPICH v3.1 (Released Feburary 2014)
799         IBM MPI v2.1 (December 2014)
800         Intel MPI Library v5.0 (2014)
801         Cray MPT v7.0.0 (June 2014)
802       As of July 31, 2017 the ABI number still appears to be 12, that is all of the versions
803       listed above and since that time are compatible.
804 
805       Unfortunately the MPI ABI initiative has not defined a way to determine the ABI number
806       at compile time or runtime. Thus we will need to systematically track the allowed versions
807       and how they are represented in the mpi.h and MPI_Get_library_version() output in order
808       to perform the checking.
809 
810       Currently we only check for pre MPI ABI versions (and packages that do not follow the MPI ABI).
811 
812       Questions:
813 
814         Should the checks for ABI incompatibility be only on the major version number below?
815         Presumably the output to stderr will be removed before a release.
816   */
817 
818 #if defined(PETSC_HAVE_MPI_GET_LIBRARY_VERSION)
819   {
820     char        mpilibraryversion[MPI_MAX_LIBRARY_VERSION_STRING];
821     PetscMPIInt mpilibraryversionlength;
822     ierr = MPI_Get_library_version(mpilibraryversion,&mpilibraryversionlength);if (ierr) return ierr;
823     /* check for MPICH versions before MPI ABI initiative */
824 #if defined(MPICH_VERSION)
825 #if MPICH_NUMVERSION < 30100000
826     {
827       char *ver,*lf;
828       flg = PETSC_FALSE;
829       ierr = PetscStrstr(mpilibraryversion,"MPICH Version:",&ver);if (ierr) return ierr;
830       if (ver) {
831         ierr = PetscStrchr(ver,'\n',&lf);if (ierr) return ierr;
832         if (lf) {
833           *lf = 0;
834           ierr = PetscStrendswith(ver,MPICH_VERSION,&flg);if (ierr) return ierr;
835         }
836       }
837       if (!flg) {
838         fprintf(stderr,"PETSc Error --- MPICH library version \n%s does not match what PETSc was compiled with %s, aborting\n",mpilibraryversion,MPICH_VERSION);
839         return PETSC_ERR_MPI_LIB_INCOMP;
840       }
841     }
842 #endif
843     /* check for OpenMPI version, it is not part of the MPI ABI initiative (is it part of another initiative that needs to be handled?) */
844 #elif defined(OMPI_MAJOR_VERSION)
845     {
846       char *ver,bs[MPI_MAX_LIBRARY_VERSION_STRING],*bsf;
847       flg = PETSC_FALSE;
848 #define PSTRSZ 2
849       char ompistr1[PSTRSZ][MPI_MAX_LIBRARY_VERSION_STRING] = {"Open MPI","FUJITSU MPI"};
850       char ompistr2[PSTRSZ][MPI_MAX_LIBRARY_VERSION_STRING] = {"v","Library "};
851       int i;
852       for (i=0; i<PSTRSZ; i++) {
853         ierr = PetscStrstr(mpilibraryversion,ompistr1[i],&ver);if (ierr) return ierr;
854         if (ver) {
855           PetscSNPrintf(bs,MPI_MAX_LIBRARY_VERSION_STRING,"%s%d.%d",ompistr2[i],OMPI_MAJOR_VERSION,OMPI_MINOR_VERSION);
856           ierr = PetscStrstr(ver,bs,&bsf);if (ierr) return ierr;
857           if (bsf) flg = PETSC_TRUE;
858           break;
859         }
860       }
861       if (!flg) {
862         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);
863         return PETSC_ERR_MPI_LIB_INCOMP;
864       }
865     }
866 #endif
867   }
868 #endif
869 
870 #if defined(PETSC_HAVE_DLSYM)
871   {
872     PetscInt cnt = 0;
873     /* 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 */
874     if (dlsym(RTLD_DEFAULT,"ompi_mpi_init")) cnt++;
875     if (dlsym(RTLD_DEFAULT,"MPL_exit")) cnt++;
876     if (cnt > 1) {
877       fprintf(stderr,"PETSc Error --- Application was linked against both OpenMPI and MPICH based MPI libraries and will not run correctly\n");
878       return PETSC_ERR_MPI_LIB_INCOMP;
879     }
880   }
881 #endif
882 
883   /* these must be initialized in a routine, not as a constant declaration*/
884   PETSC_STDOUT = stdout;
885   PETSC_STDERR = stderr;
886 
887   /*CHKERRQ can be used from now */
888   PetscErrorHandlingInitialized = PETSC_TRUE;
889 
890   /* on Windows - set printf to default to printing 2 digit exponents */
891 #if defined(PETSC_HAVE__SET_OUTPUT_FORMAT)
892   _set_output_format(_TWO_DIGIT_EXPONENT);
893 #endif
894 
895   ierr = PetscOptionsCreateDefault();CHKERRQ(ierr);
896 
897   /*
898      We initialize the program name here (before MPI_Init()) because MPICH has a bug in
899      it that it sets args[0] on all processors to be args[0] on the first processor.
900   */
901   if (argc && *argc) {
902     ierr = PetscSetProgramName(**args);CHKERRQ(ierr);
903   } else {
904     ierr = PetscSetProgramName("Unknown Name");CHKERRQ(ierr);
905   }
906 
907   ierr = MPI_Initialized(&flag);CHKERRQ(ierr);
908   if (!flag) {
909     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");
910     ierr = PetscPreMPIInit_Private();CHKERRQ(ierr);
911 #if defined(PETSC_HAVE_MPI_INIT_THREAD)
912     {
913       PetscMPIInt provided;
914       ierr = MPI_Init_thread(argc,args,PETSC_MPI_THREAD_REQUIRED,&provided);CHKERRQ(ierr);
915     }
916 #else
917     ierr = MPI_Init(argc,args);CHKERRQ(ierr);
918 #endif
919     PetscBeganMPI = PETSC_TRUE;
920   }
921 
922   if (argc && args) {
923     PetscGlobalArgc = *argc;
924     PetscGlobalArgs = *args;
925   }
926   PetscFinalizeCalled = PETSC_FALSE;
927   ierr = PetscSpinlockCreate(&PetscViewerASCIISpinLockOpen);CHKERRQ(ierr);
928   ierr = PetscSpinlockCreate(&PetscViewerASCIISpinLockStdout);CHKERRQ(ierr);
929   ierr = PetscSpinlockCreate(&PetscViewerASCIISpinLockStderr);CHKERRQ(ierr);
930   ierr = PetscSpinlockCreate(&PetscCommSpinLock);CHKERRQ(ierr);
931 
932   if (PETSC_COMM_WORLD == MPI_COMM_NULL) PETSC_COMM_WORLD = MPI_COMM_WORLD;
933   ierr = MPI_Comm_set_errhandler(PETSC_COMM_WORLD,MPI_ERRORS_RETURN);CHKERRQ(ierr);
934 
935   if (PETSC_MPI_ERROR_CLASS == MPI_ERR_LASTCODE) {
936     ierr = MPI_Add_error_class(&PETSC_MPI_ERROR_CLASS);CHKERRQ(ierr);
937     ierr = MPI_Add_error_code(PETSC_MPI_ERROR_CLASS,&PETSC_MPI_ERROR_CODE);CHKERRQ(ierr);
938   }
939 
940   /* Done after init due to a bug in MPICH-GM? */
941   ierr = PetscErrorPrintfInitialize();CHKERRQ(ierr);
942 
943   ierr = MPI_Comm_rank(MPI_COMM_WORLD,&PetscGlobalRank);CHKERRQ(ierr);
944   ierr = MPI_Comm_size(MPI_COMM_WORLD,&PetscGlobalSize);CHKERRQ(ierr);
945 
946   MPIU_BOOL = MPI_INT;
947   MPIU_ENUM = MPI_INT;
948   MPIU_FORTRANADDR = (sizeof(void*) == sizeof(int)) ? MPI_INT : MPIU_INT64;
949   if (sizeof(size_t) == sizeof(unsigned)) MPIU_SIZE_T = MPI_UNSIGNED;
950   else if (sizeof(size_t) == sizeof(unsigned long)) MPIU_SIZE_T = MPI_UNSIGNED_LONG;
951 #if defined(PETSC_SIZEOF_LONG_LONG)
952   else if (sizeof(size_t) == sizeof(unsigned long long)) MPIU_SIZE_T = MPI_UNSIGNED_LONG_LONG;
953 #endif
954   else {(*PetscErrorPrintf)("PetscInitialize: Could not find MPI type for size_t\n"); return PETSC_ERR_SUP_SYS;}
955 
956   /*
957      Initialized the global complex variable; this is because with
958      shared libraries the constructors for global variables
959      are not called; at least on IRIX.
960   */
961 #if defined(PETSC_HAVE_COMPLEX)
962   {
963 #if defined(PETSC_CLANGUAGE_CXX) && !defined(PETSC_USE_REAL___FLOAT128)
964     PetscComplex ic(0.0,1.0);
965     PETSC_i = ic;
966 #else
967     PETSC_i = _Complex_I;
968 #endif
969   }
970 
971 #if !defined(PETSC_HAVE_MPI_C_DOUBLE_COMPLEX)
972   ierr = MPI_Type_contiguous(2,MPI_DOUBLE,&MPIU_C_DOUBLE_COMPLEX);CHKERRQ(ierr);
973   ierr = MPI_Type_commit(&MPIU_C_DOUBLE_COMPLEX);CHKERRQ(ierr);
974   ierr = MPI_Type_contiguous(2,MPI_FLOAT,&MPIU_C_COMPLEX);CHKERRQ(ierr);
975   ierr = MPI_Type_commit(&MPIU_C_COMPLEX);CHKERRQ(ierr);
976 #endif
977 #endif /* PETSC_HAVE_COMPLEX */
978 
979   /*
980      Create the PETSc MPI reduction operator that sums of the first
981      half of the entries and maxes the second half.
982   */
983   ierr = MPI_Op_create(MPIU_MaxSum_Local,1,&MPIU_MAXSUM_OP);CHKERRQ(ierr);
984 
985 #if defined(PETSC_USE_REAL___FLOAT128)
986   ierr = MPI_Type_contiguous(2,MPI_DOUBLE,&MPIU___FLOAT128);CHKERRQ(ierr);
987   ierr = MPI_Type_commit(&MPIU___FLOAT128);CHKERRQ(ierr);
988 #if defined(PETSC_HAVE_COMPLEX)
989   ierr = MPI_Type_contiguous(4,MPI_DOUBLE,&MPIU___COMPLEX128);CHKERRQ(ierr);
990   ierr = MPI_Type_commit(&MPIU___COMPLEX128);CHKERRQ(ierr);
991 #endif
992   ierr = MPI_Op_create(PetscMax_Local,1,&MPIU_MAX);CHKERRQ(ierr);
993   ierr = MPI_Op_create(PetscMin_Local,1,&MPIU_MIN);CHKERRQ(ierr);
994 #elif defined(PETSC_USE_REAL___FP16)
995   ierr = MPI_Type_contiguous(2,MPI_CHAR,&MPIU___FP16);CHKERRQ(ierr);
996   ierr = MPI_Type_commit(&MPIU___FP16);CHKERRQ(ierr);
997   ierr = MPI_Op_create(PetscMax_Local,1,&MPIU_MAX);CHKERRQ(ierr);
998   ierr = MPI_Op_create(PetscMin_Local,1,&MPIU_MIN);CHKERRQ(ierr);
999 #endif
1000 
1001 #if (defined(PETSC_HAVE_COMPLEX) && !defined(PETSC_HAVE_MPI_C_DOUBLE_COMPLEX)) || defined(PETSC_USE_REAL___FLOAT128) || defined(PETSC_USE_REAL___FP16)
1002   ierr = MPI_Op_create(PetscSum_Local,1,&MPIU_SUM);CHKERRQ(ierr);
1003 #endif
1004 
1005   ierr = MPI_Type_contiguous(2,MPIU_SCALAR,&MPIU_2SCALAR);CHKERRQ(ierr);
1006   ierr = MPI_Type_commit(&MPIU_2SCALAR);CHKERRQ(ierr);
1007 
1008 #if defined(PETSC_USE_64BIT_INDICES)
1009   ierr = MPI_Type_contiguous(2,MPIU_INT,&MPIU_2INT);CHKERRQ(ierr);
1010   ierr = MPI_Type_commit(&MPIU_2INT);CHKERRQ(ierr);
1011 #endif
1012 
1013   /*
1014      Attributes to be set on PETSc communicators
1015   */
1016   ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,Petsc_Counter_Attr_Delete_Fn,&Petsc_Counter_keyval,(void*)0);CHKERRQ(ierr);
1017   ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,Petsc_InnerComm_Attr_Delete_Fn,&Petsc_InnerComm_keyval,(void*)0);CHKERRQ(ierr);
1018   ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,Petsc_OuterComm_Attr_Delete_Fn,&Petsc_OuterComm_keyval,(void*)0);CHKERRQ(ierr);
1019   ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,Petsc_ShmComm_Attr_Delete_Fn,&Petsc_ShmComm_keyval,(void*)0);CHKERRQ(ierr);
1020 
1021   /*
1022      Build the options database
1023   */
1024   ierr = PetscOptionsInsert(NULL,argc,args,file);CHKERRQ(ierr);
1025 
1026   /* call a second time so it can look in the options database */
1027   ierr = PetscErrorPrintfInitialize();CHKERRQ(ierr);
1028 
1029   /*
1030      Check system options and print help
1031   */
1032   ierr = PetscOptionsCheckInitial_Private(help);CHKERRQ(ierr);
1033 
1034   ierr = PetscCitationsInitialize();CHKERRQ(ierr);
1035 
1036 #if defined(PETSC_HAVE_SAWS)
1037   ierr = PetscInitializeSAWs(help);CHKERRQ(ierr);
1038 #endif
1039 
1040   /*
1041      Load the dynamic libraries (on machines that support them), this registers all
1042      the solvers etc. (On non-dynamic machines this initializes the PetscDraw and PetscViewer classes)
1043   */
1044   ierr = PetscInitialize_DynamicLibraries();CHKERRQ(ierr);
1045 
1046   ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr);
1047   ierr = PetscInfo1(NULL,"PETSc successfully started: number of processors = %d\n",size);CHKERRQ(ierr);
1048   ierr = PetscGetHostName(hostname,256);CHKERRQ(ierr);
1049   ierr = PetscInfo1(NULL,"Running on machine: %s\n",hostname);CHKERRQ(ierr);
1050 #if defined(PETSC_HAVE_OPENMP)
1051   {
1052     PetscBool omp_view_flag;
1053     char      *threads = getenv("OMP_NUM_THREADS");
1054 
1055    if (threads) {
1056      ierr = PetscInfo1(NULL,"Number of OpenMP threads %s (given by OMP_NUM_THREADS)\n",threads);CHKERRQ(ierr);
1057      (void) sscanf(threads, "%" PetscInt_FMT,&PetscNumOMPThreads);
1058    } else {
1059 #define NMAX  10000
1060      int          i;
1061       PetscScalar *x;
1062       ierr = PetscMalloc1(NMAX,&x);CHKERRQ(ierr);
1063 #pragma omp parallel for
1064       for (i=0; i<NMAX; i++) {
1065         x[i] = 0.0;
1066         PetscNumOMPThreads  = (PetscInt) omp_get_num_threads();
1067       }
1068       ierr = PetscFree(x);CHKERRQ(ierr);
1069       ierr = PetscInfo1(NULL,"Number of OpenMP threads %D (number not set with OMP_NUM_THREADS, chosen by system)\n",PetscNumOMPThreads);CHKERRQ(ierr);
1070     }
1071     ierr = PetscOptionsBegin(PETSC_COMM_WORLD,NULL,"OpenMP options","Sys");CHKERRQ(ierr);
1072     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);
1073     ierr = PetscOptionsName("-omp_view","Display OpenMP number of threads",NULL,&omp_view_flag);CHKERRQ(ierr);
1074     ierr = PetscOptionsEnd();CHKERRQ(ierr);
1075     if (flg) {
1076       ierr = PetscInfo1(NULL,"Number of OpenMP theads %D (given by -omp_num_threads)\n",PetscNumOMPThreads);CHKERRQ(ierr);
1077       omp_set_num_threads((int)PetscNumOMPThreads);
1078     }
1079     if (omp_view_flag) {
1080       ierr = PetscPrintf(PETSC_COMM_WORLD,"OpenMP: number of threads %D\n",PetscNumOMPThreads);CHKERRQ(ierr);
1081     }
1082   }
1083 #endif
1084 
1085 #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
1086   /*
1087       Tell MPI about our own data representation converter, this would/should be used if extern32 is not supported by the MPI
1088 
1089       Currently not used because it is not supported by MPICH.
1090   */
1091   if (!PetscBinaryBigEndian()) {
1092     ierr = MPI_Register_datarep((char*)"petsc",PetscDataRep_read_conv_fn,PetscDataRep_write_conv_fn,PetscDataRep_extent_fn,NULL);CHKERRQ(ierr);
1093   }
1094 #endif
1095 
1096   /*
1097       Setup building of stack frames for all function calls
1098   */
1099 #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
1100   ierr = PetscStackCreate();CHKERRQ(ierr);
1101 #endif
1102 
1103 #if defined(PETSC_SERIALIZE_FUNCTIONS)
1104   ierr = PetscFPTCreate(10000);CHKERRQ(ierr);
1105 #endif
1106 
1107 #if defined(PETSC_HAVE_HWLOC)
1108   {
1109     PetscViewer viewer;
1110     ierr = PetscOptionsGetViewer(PETSC_COMM_WORLD,NULL,NULL,"-process_view",&viewer,NULL,&flg);CHKERRQ(ierr);
1111     if (flg) {
1112       ierr = PetscProcessPlacementView(viewer);CHKERRQ(ierr);
1113       ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1114     }
1115   }
1116 #endif
1117 
1118   flg = PETSC_TRUE;
1119   ierr = PetscOptionsGetBool(NULL,NULL,"-viewfromoptions",&flg,NULL);CHKERRQ(ierr);
1120   if (!flg) {ierr = PetscOptionsPushGetViewerOff(PETSC_TRUE);CHKERRQ(ierr);}
1121 
1122 #if defined(PETSC_HAVE_ADIOS)
1123   ierr = adios_init_noxml(PETSC_COMM_WORLD);CHKERRQ(ierr);
1124   ierr = adios_declare_group(&Petsc_adios_group,"PETSc","",adios_stat_default);CHKERRQ(ierr);
1125   ierr = adios_select_method(Petsc_adios_group,"MPI","","");CHKERRQ(ierr);
1126   ierr = adios_read_init_method(ADIOS_READ_METHOD_BP,PETSC_COMM_WORLD,"");CHKERRQ(ierr);
1127 #endif
1128 #if defined(PETSC_HAVE_ADIOS2)
1129 #endif
1130 
1131   /*
1132       Set flag that we are completely initialized
1133   */
1134   PetscInitializeCalled = PETSC_TRUE;
1135 
1136   ierr = PetscOptionsHasName(NULL,NULL,"-python",&flg);CHKERRQ(ierr);
1137   if (flg) {ierr = PetscPythonInitialize(NULL,NULL);CHKERRQ(ierr);}
1138   PetscFunctionReturn(0);
1139 }
1140 
1141 #if defined(PETSC_USE_LOG)
1142 PETSC_INTERN PetscObject *PetscObjects;
1143 PETSC_INTERN PetscInt    PetscObjectsCounts;
1144 PETSC_INTERN PetscInt    PetscObjectsMaxCounts;
1145 PETSC_INTERN PetscBool   PetscObjectsLog;
1146 #endif
1147 
1148 /*
1149     Frees all the MPI types and operations that PETSc may have created
1150 */
1151 PetscErrorCode  PetscFreeMPIResources(void)
1152 {
1153   PetscErrorCode ierr;
1154 
1155   PetscFunctionBegin;
1156 #if defined(PETSC_USE_REAL___FLOAT128)
1157   ierr = MPI_Type_free(&MPIU___FLOAT128);CHKERRQ(ierr);
1158 #if defined(PETSC_HAVE_COMPLEX)
1159   ierr = MPI_Type_free(&MPIU___COMPLEX128);CHKERRQ(ierr);
1160 #endif
1161   ierr = MPI_Op_free(&MPIU_MAX);CHKERRQ(ierr);
1162   ierr = MPI_Op_free(&MPIU_MIN);CHKERRQ(ierr);
1163 #elif defined(PETSC_USE_REAL___FP16)
1164   ierr = MPI_Type_free(&MPIU___FP16);CHKERRQ(ierr);
1165   ierr = MPI_Op_free(&MPIU_MAX);CHKERRQ(ierr);
1166   ierr = MPI_Op_free(&MPIU_MIN);CHKERRQ(ierr);
1167 #endif
1168 
1169 #if defined(PETSC_HAVE_COMPLEX)
1170 #if !defined(PETSC_HAVE_MPI_C_DOUBLE_COMPLEX)
1171   ierr = MPI_Type_free(&MPIU_C_DOUBLE_COMPLEX);CHKERRQ(ierr);
1172   ierr = MPI_Type_free(&MPIU_C_COMPLEX);CHKERRQ(ierr);
1173 #endif
1174 #endif
1175 
1176 #if (defined(PETSC_HAVE_COMPLEX) && !defined(PETSC_HAVE_MPI_C_DOUBLE_COMPLEX)) || defined(PETSC_USE_REAL___FLOAT128) || defined(PETSC_USE_REAL___FP16)
1177   ierr = MPI_Op_free(&MPIU_SUM);CHKERRQ(ierr);
1178 #endif
1179 
1180   ierr = MPI_Type_free(&MPIU_2SCALAR);CHKERRQ(ierr);
1181 #if defined(PETSC_USE_64BIT_INDICES)
1182   ierr = MPI_Type_free(&MPIU_2INT);CHKERRQ(ierr);
1183 #endif
1184   ierr = MPI_Op_free(&MPIU_MAXSUM_OP);CHKERRQ(ierr);
1185   PetscFunctionReturn(0);
1186 }
1187 
1188 /*@C
1189    PetscFinalize - Checks for options to be called at the conclusion
1190    of the program. MPI_Finalize() is called only if the user had not
1191    called MPI_Init() before calling PetscInitialize().
1192 
1193    Collective on PETSC_COMM_WORLD
1194 
1195    Options Database Keys:
1196 +  -options_view - Calls PetscOptionsView()
1197 .  -options_left - Prints unused options that remain in the database
1198 .  -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
1199 .  -mpidump - Calls PetscMPIDump()
1200 .  -malloc_dump <optional filename> - Calls PetscMallocDump(), displays all memory allocated that has not been freed
1201 .  -malloc_info - Prints total memory usage
1202 -  -malloc_view <optional filename> - Prints list of all memory allocated and where
1203 
1204    Level: beginner
1205 
1206    Note:
1207    See PetscInitialize() for more general runtime options.
1208 
1209 .seealso: PetscInitialize(), PetscOptionsView(), PetscMallocDump(), PetscMPIDump(), PetscEnd()
1210 @*/
1211 PetscErrorCode  PetscFinalize(void)
1212 {
1213   PetscErrorCode ierr;
1214   PetscMPIInt    rank;
1215   PetscInt       nopt;
1216   PetscBool      flg1 = PETSC_FALSE,flg2 = PETSC_FALSE,flg3 = PETSC_FALSE;
1217   PetscBool      flg;
1218 #if defined(PETSC_USE_LOG)
1219   char           mname[PETSC_MAX_PATH_LEN];
1220 #endif
1221 
1222   if (!PetscInitializeCalled) {
1223     printf("PetscInitialize() must be called before PetscFinalize()\n");
1224     return(PETSC_ERR_ARG_WRONGSTATE);
1225   }
1226   PetscFunctionBegin;
1227   ierr = PetscInfo(NULL,"PetscFinalize() called\n");CHKERRQ(ierr);
1228 
1229   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
1230 #if defined(PETSC_HAVE_ADIOS)
1231   ierr = adios_read_finalize_method(ADIOS_READ_METHOD_BP_AGGREGATE);CHKERRQ(ierr);
1232   ierr = adios_finalize(rank);CHKERRQ(ierr);
1233 #endif
1234 #if defined(PETSC_HAVE_ADIOS2)
1235 #endif
1236   ierr = PetscOptionsHasName(NULL,NULL,"-citations",&flg);CHKERRQ(ierr);
1237   if (flg) {
1238     char  *cits, filename[PETSC_MAX_PATH_LEN];
1239     FILE  *fd = PETSC_STDOUT;
1240 
1241     ierr = PetscOptionsGetString(NULL,NULL,"-citations",filename,sizeof(filename),NULL);CHKERRQ(ierr);
1242     if (filename[0]) {
1243       ierr = PetscFOpen(PETSC_COMM_WORLD,filename,"w",&fd);CHKERRQ(ierr);
1244     }
1245     ierr = PetscSegBufferGet(PetscCitationsList,1,&cits);CHKERRQ(ierr);
1246     cits[0] = 0;
1247     ierr = PetscSegBufferExtractAlloc(PetscCitationsList,&cits);CHKERRQ(ierr);
1248     ierr = PetscFPrintf(PETSC_COMM_WORLD,fd,"If you publish results based on this computation please cite the following:\n");CHKERRQ(ierr);
1249     ierr = PetscFPrintf(PETSC_COMM_WORLD,fd,"===========================================================================\n");CHKERRQ(ierr);
1250     ierr = PetscFPrintf(PETSC_COMM_WORLD,fd,"%s",cits);CHKERRQ(ierr);
1251     ierr = PetscFPrintf(PETSC_COMM_WORLD,fd,"===========================================================================\n");CHKERRQ(ierr);
1252     ierr = PetscFClose(PETSC_COMM_WORLD,fd);CHKERRQ(ierr);
1253     ierr = PetscFree(cits);CHKERRQ(ierr);
1254   }
1255   ierr = PetscSegBufferDestroy(&PetscCitationsList);CHKERRQ(ierr);
1256 
1257 #if defined(PETSC_HAVE_SSL) && defined(PETSC_USE_SOCKET_VIEWER)
1258   /* TextBelt is run for testing purposes only, please do not use this feature often */
1259   {
1260     PetscInt nmax = 2;
1261     char     **buffs;
1262     ierr = PetscMalloc1(2,&buffs);CHKERRQ(ierr);
1263     ierr = PetscOptionsGetStringArray(NULL,NULL,"-textbelt",buffs,&nmax,&flg1);CHKERRQ(ierr);
1264     if (flg1) {
1265       if (!nmax) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_USER,"-textbelt requires either the phone number or number,\"message\"");
1266       if (nmax == 1) {
1267         ierr = PetscMalloc1(128,&buffs[1]);CHKERRQ(ierr);
1268         ierr = PetscGetProgramName(buffs[1],32);CHKERRQ(ierr);
1269         ierr = PetscStrcat(buffs[1]," has completed");CHKERRQ(ierr);
1270       }
1271       ierr = PetscTextBelt(PETSC_COMM_WORLD,buffs[0],buffs[1],NULL);CHKERRQ(ierr);
1272       ierr = PetscFree(buffs[0]);CHKERRQ(ierr);
1273       ierr = PetscFree(buffs[1]);CHKERRQ(ierr);
1274     }
1275     ierr = PetscFree(buffs);CHKERRQ(ierr);
1276   }
1277   {
1278     PetscInt nmax = 2;
1279     char     **buffs;
1280     ierr = PetscMalloc1(2,&buffs);CHKERRQ(ierr);
1281     ierr = PetscOptionsGetStringArray(NULL,NULL,"-tellmycell",buffs,&nmax,&flg1);CHKERRQ(ierr);
1282     if (flg1) {
1283       if (!nmax) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_USER,"-tellmycell requires either the phone number or number,\"message\"");
1284       if (nmax == 1) {
1285         ierr = PetscMalloc1(128,&buffs[1]);CHKERRQ(ierr);
1286         ierr = PetscGetProgramName(buffs[1],32);CHKERRQ(ierr);
1287         ierr = PetscStrcat(buffs[1]," has completed");CHKERRQ(ierr);
1288       }
1289       ierr = PetscTellMyCell(PETSC_COMM_WORLD,buffs[0],buffs[1],NULL);CHKERRQ(ierr);
1290       ierr = PetscFree(buffs[0]);CHKERRQ(ierr);
1291       ierr = PetscFree(buffs[1]);CHKERRQ(ierr);
1292     }
1293     ierr = PetscFree(buffs);CHKERRQ(ierr);
1294   }
1295 #endif
1296 
1297 #if defined(PETSC_SERIALIZE_FUNCTIONS)
1298   ierr = PetscFPTDestroy();CHKERRQ(ierr);
1299 #endif
1300 
1301 #if defined(PETSC_HAVE_SAWS)
1302   flg = PETSC_FALSE;
1303   ierr = PetscOptionsGetBool(NULL,NULL,"-saw_options",&flg,NULL);CHKERRQ(ierr);
1304   if (flg) {
1305     ierr = PetscOptionsSAWsDestroy();CHKERRQ(ierr);
1306   }
1307 #endif
1308 
1309 #if defined(PETSC_HAVE_X)
1310   flg1 = PETSC_FALSE;
1311   ierr = PetscOptionsGetBool(NULL,NULL,"-x_virtual",&flg1,NULL);CHKERRQ(ierr);
1312   if (flg1) {
1313     /*  this is a crude hack, but better than nothing */
1314     ierr = PetscPOpen(PETSC_COMM_WORLD,NULL,"pkill -9 Xvfb","r",NULL);CHKERRQ(ierr);
1315   }
1316 #endif
1317 
1318 #if !defined(PETSC_HAVE_THREADSAFETY)
1319   ierr = PetscOptionsGetBool(NULL,NULL,"-malloc_info",&flg2,NULL);CHKERRQ(ierr);
1320   if (!flg2) {
1321     flg2 = PETSC_FALSE;
1322     ierr = PetscOptionsGetBool(NULL,NULL,"-memory_view",&flg2,NULL);CHKERRQ(ierr);
1323   }
1324   if (flg2) {
1325     ierr = PetscMemoryView(PETSC_VIEWER_STDOUT_WORLD,"Summary of Memory Usage in PETSc\n");CHKERRQ(ierr);
1326   }
1327 #endif
1328 
1329 #if defined(PETSC_USE_LOG)
1330   flg1 = PETSC_FALSE;
1331   ierr = PetscOptionsGetBool(NULL,NULL,"-get_total_flops",&flg1,NULL);CHKERRQ(ierr);
1332   if (flg1) {
1333     PetscLogDouble flops = 0;
1334     ierr = MPI_Reduce(&petsc_TotalFlops,&flops,1,MPI_DOUBLE,MPI_SUM,0,PETSC_COMM_WORLD);CHKERRQ(ierr);
1335     ierr = PetscPrintf(PETSC_COMM_WORLD,"Total flops over all processors %g\n",flops);CHKERRQ(ierr);
1336   }
1337 #endif
1338 
1339 
1340 #if defined(PETSC_USE_LOG)
1341 #if defined(PETSC_HAVE_MPE)
1342   mname[0] = 0;
1343   ierr = PetscOptionsGetString(NULL,NULL,"-log_mpe",mname,sizeof(mname),&flg1);CHKERRQ(ierr);
1344   if (flg1) {
1345     if (mname[0]) {ierr = PetscLogMPEDump(mname);CHKERRQ(ierr);}
1346     else          {ierr = PetscLogMPEDump(0);CHKERRQ(ierr);}
1347   }
1348 #endif
1349 #endif
1350 
1351   /*
1352      Free all objects registered with PetscObjectRegisterDestroy() such as PETSC_VIEWER_XXX_().
1353   */
1354   ierr = PetscObjectRegisterDestroyAll();CHKERRQ(ierr);
1355 
1356 #if defined(PETSC_USE_LOG)
1357   ierr = PetscOptionsPushGetViewerOff(PETSC_FALSE);CHKERRQ(ierr);
1358   ierr = PetscLogViewFromOptions();CHKERRQ(ierr);
1359   ierr = PetscOptionsPopGetViewerOff();CHKERRQ(ierr);
1360 
1361   mname[0] = 0;
1362   ierr = PetscOptionsGetString(NULL,NULL,"-log_summary",mname,sizeof(mname),&flg1);CHKERRQ(ierr);
1363   if (flg1) {
1364     PetscViewer viewer;
1365     ierr = (*PetscHelpPrintf)(PETSC_COMM_WORLD,"\n\n WARNING:   -log_summary is being deprecated; switch to -log_view\n\n\n");CHKERRQ(ierr);
1366     if (mname[0]) {
1367       ierr = PetscViewerASCIIOpen(PETSC_COMM_WORLD,mname,&viewer);CHKERRQ(ierr);
1368       ierr = PetscLogView(viewer);CHKERRQ(ierr);
1369       ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1370     } else {
1371       viewer = PETSC_VIEWER_STDOUT_WORLD;
1372       ierr   = PetscViewerPushFormat(viewer,PETSC_VIEWER_DEFAULT);CHKERRQ(ierr);
1373       ierr   = PetscLogView(viewer);CHKERRQ(ierr);
1374       ierr   = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
1375     }
1376   }
1377 
1378   /*
1379      Free any objects created by the last block of code.
1380   */
1381   ierr = PetscObjectRegisterDestroyAll();CHKERRQ(ierr);
1382 
1383   mname[0] = 0;
1384   ierr = PetscOptionsGetString(NULL,NULL,"-log_all",mname,sizeof(mname),&flg1);CHKERRQ(ierr);
1385   ierr = PetscOptionsGetString(NULL,NULL,"-log",mname,sizeof(mname),&flg2);CHKERRQ(ierr);
1386   if (flg1 || flg2) {ierr = PetscLogDump(mname);CHKERRQ(ierr);}
1387 #endif
1388 
1389   ierr = PetscStackDestroy();CHKERRQ(ierr);
1390 
1391   flg1 = PETSC_FALSE;
1392   ierr = PetscOptionsGetBool(NULL,NULL,"-no_signal_handler",&flg1,NULL);CHKERRQ(ierr);
1393   if (!flg1) { ierr = PetscPopSignalHandler();CHKERRQ(ierr);}
1394   flg1 = PETSC_FALSE;
1395   ierr = PetscOptionsGetBool(NULL,NULL,"-mpidump",&flg1,NULL);CHKERRQ(ierr);
1396   if (flg1) {
1397     ierr = PetscMPIDump(stdout);CHKERRQ(ierr);
1398   }
1399   flg1 = PETSC_FALSE;
1400   flg2 = PETSC_FALSE;
1401   /* preemptive call to avoid listing this option in options table as unused */
1402   ierr = PetscOptionsHasName(NULL,NULL,"-malloc_dump",&flg1);CHKERRQ(ierr);
1403   ierr = PetscOptionsHasName(NULL,NULL,"-objects_dump",&flg1);CHKERRQ(ierr);
1404   ierr = PetscOptionsGetBool(NULL,NULL,"-options_view",&flg2,NULL);CHKERRQ(ierr);
1405 
1406   if (flg2) {
1407     PetscViewer viewer;
1408     ierr = PetscViewerCreate(PETSC_COMM_WORLD,&viewer);CHKERRQ(ierr);
1409     ierr = PetscViewerSetType(viewer,PETSCVIEWERASCII);CHKERRQ(ierr);
1410     ierr = PetscOptionsView(NULL,viewer);CHKERRQ(ierr);
1411     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1412   }
1413 
1414   /* to prevent PETSc -options_left from warning */
1415   ierr = PetscOptionsHasName(NULL,NULL,"-nox",&flg1);CHKERRQ(ierr);
1416   ierr = PetscOptionsHasName(NULL,NULL,"-nox_warning",&flg1);CHKERRQ(ierr);
1417 
1418   flg3 = PETSC_FALSE; /* default value is required */
1419   ierr = PetscOptionsGetBool(NULL,NULL,"-options_left",&flg3,&flg1);CHKERRQ(ierr);
1420   if (PetscUnlikelyDebug(!flg1)) flg3 = PETSC_TRUE;
1421   if (flg3) {
1422     if (!flg2 && flg1) { /* have not yet printed the options */
1423       PetscViewer viewer;
1424       ierr = PetscViewerCreate(PETSC_COMM_WORLD,&viewer);CHKERRQ(ierr);
1425       ierr = PetscViewerSetType(viewer,PETSCVIEWERASCII);CHKERRQ(ierr);
1426       ierr = PetscOptionsView(NULL,viewer);CHKERRQ(ierr);
1427       ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1428     }
1429     ierr = PetscOptionsAllUsed(NULL,&nopt);CHKERRQ(ierr);
1430     if (nopt) {
1431       ierr = PetscPrintf(PETSC_COMM_WORLD,"WARNING! There are options you set that were not used!\n");CHKERRQ(ierr);
1432       ierr = PetscPrintf(PETSC_COMM_WORLD,"WARNING! could be spelling mistake, etc!\n");CHKERRQ(ierr);
1433       if (nopt == 1) {
1434         ierr = PetscPrintf(PETSC_COMM_WORLD,"There is one unused database option. It is:\n");CHKERRQ(ierr);
1435       } else {
1436         ierr = PetscPrintf(PETSC_COMM_WORLD,"There are %D unused database options. They are:\n",nopt);CHKERRQ(ierr);
1437       }
1438     } else if (flg3 && flg1) {
1439       ierr = PetscPrintf(PETSC_COMM_WORLD,"There are no unused options.\n");CHKERRQ(ierr);
1440     }
1441     ierr = PetscOptionsLeft(NULL);CHKERRQ(ierr);
1442   }
1443 
1444 #if defined(PETSC_HAVE_SAWS)
1445   if (!PetscGlobalRank) {
1446     ierr = PetscStackSAWsViewOff();CHKERRQ(ierr);
1447     PetscStackCallSAWs(SAWs_Finalize,());
1448   }
1449 #endif
1450 
1451 #if defined(PETSC_USE_LOG)
1452   /*
1453        List all objects the user may have forgot to free
1454   */
1455   if (PetscObjectsLog) {
1456     ierr = PetscOptionsHasName(NULL,NULL,"-objects_dump",&flg1);CHKERRQ(ierr);
1457     if (flg1) {
1458       MPI_Comm local_comm;
1459       char     string[64];
1460 
1461       ierr = PetscOptionsGetString(NULL,NULL,"-objects_dump",string,sizeof(string),NULL);CHKERRQ(ierr);
1462       ierr = MPI_Comm_dup(MPI_COMM_WORLD,&local_comm);CHKERRQ(ierr);
1463       ierr = PetscSequentialPhaseBegin_Private(local_comm,1);CHKERRQ(ierr);
1464       ierr = PetscObjectsDump(stdout,(string[0] == 'a') ? PETSC_TRUE : PETSC_FALSE);CHKERRQ(ierr);
1465       ierr = PetscSequentialPhaseEnd_Private(local_comm,1);CHKERRQ(ierr);
1466       ierr = MPI_Comm_free(&local_comm);CHKERRQ(ierr);
1467     }
1468   }
1469 #endif
1470 
1471 #if defined(PETSC_USE_LOG)
1472   PetscObjectsCounts    = 0;
1473   PetscObjectsMaxCounts = 0;
1474   ierr = PetscFree(PetscObjects);CHKERRQ(ierr);
1475 #endif
1476 
1477   /*
1478      Destroy any packages that registered a finalize
1479   */
1480   ierr = PetscRegisterFinalizeAll();CHKERRQ(ierr);
1481 
1482 #if defined(PETSC_USE_LOG)
1483   ierr = PetscLogFinalize();CHKERRQ(ierr);
1484 #endif
1485 
1486   /*
1487      Print PetscFunctionLists that have not been properly freed
1488 
1489   ierr = PetscFunctionListPrintAll();CHKERRQ(ierr);
1490   */
1491 
1492   if (petsc_history) {
1493     ierr = PetscCloseHistoryFile(&petsc_history);CHKERRQ(ierr);
1494     petsc_history = NULL;
1495   }
1496   ierr = PetscOptionsHelpPrintedDestroy(&PetscOptionsHelpPrintedSingleton);CHKERRQ(ierr);
1497   ierr = PetscInfoDestroy();CHKERRQ(ierr);
1498 
1499 #if !defined(PETSC_HAVE_THREADSAFETY)
1500   if (!(PETSC_RUNNING_ON_VALGRIND)) {
1501     char fname[PETSC_MAX_PATH_LEN];
1502     char sname[PETSC_MAX_PATH_LEN];
1503     FILE *fd;
1504     int  err;
1505 
1506     flg2 = PETSC_FALSE;
1507     flg3 = PETSC_FALSE;
1508     if (PetscDefined(USE_DEBUG)) {ierr = PetscOptionsGetBool(NULL,NULL,"-malloc_test",&flg2,NULL);CHKERRQ(ierr);}
1509     ierr = PetscOptionsGetBool(NULL,NULL,"-malloc_debug",&flg3,NULL);CHKERRQ(ierr);
1510     fname[0] = 0;
1511     ierr = PetscOptionsGetString(NULL,NULL,"-malloc_dump",fname,sizeof(fname),&flg1);CHKERRQ(ierr);
1512     if (flg1 && fname[0]) {
1513 
1514       PetscSNPrintf(sname,sizeof(sname),"%s_%d",fname,rank);
1515       fd   = fopen(sname,"w"); if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open log file: %s",sname);
1516       ierr = PetscMallocDump(fd);CHKERRQ(ierr);
1517       err  = fclose(fd);
1518       if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
1519     } else if (flg1 || flg2 || flg3) {
1520       MPI_Comm local_comm;
1521 
1522       ierr = MPI_Comm_dup(MPI_COMM_WORLD,&local_comm);CHKERRQ(ierr);
1523       ierr = PetscSequentialPhaseBegin_Private(local_comm,1);CHKERRQ(ierr);
1524       ierr = PetscMallocDump(stdout);CHKERRQ(ierr);
1525       ierr = PetscSequentialPhaseEnd_Private(local_comm,1);CHKERRQ(ierr);
1526       ierr = MPI_Comm_free(&local_comm);CHKERRQ(ierr);
1527     }
1528     fname[0] = 0;
1529     ierr = PetscOptionsGetString(NULL,NULL,"-malloc_view",fname,sizeof(fname),&flg1);CHKERRQ(ierr);
1530     if (flg1 && fname[0]) {
1531 
1532       PetscSNPrintf(sname,sizeof(sname),"%s_%d",fname,rank);
1533       fd   = fopen(sname,"w"); if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open log file: %s",sname);
1534       ierr = PetscMallocView(fd);CHKERRQ(ierr);
1535       err  = fclose(fd);
1536       if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
1537     } else if (flg1) {
1538       MPI_Comm local_comm;
1539 
1540       ierr = MPI_Comm_dup(MPI_COMM_WORLD,&local_comm);CHKERRQ(ierr);
1541       ierr = PetscSequentialPhaseBegin_Private(local_comm,1);CHKERRQ(ierr);
1542       ierr = PetscMallocView(stdout);CHKERRQ(ierr);
1543       ierr = PetscSequentialPhaseEnd_Private(local_comm,1);CHKERRQ(ierr);
1544       ierr = MPI_Comm_free(&local_comm);CHKERRQ(ierr);
1545     }
1546   }
1547 #endif
1548 
1549   /*
1550      Close any open dynamic libraries
1551   */
1552   ierr = PetscFinalize_DynamicLibraries();CHKERRQ(ierr);
1553 
1554   /* Can be destroyed only after all the options are used */
1555   ierr = PetscOptionsDestroyDefault();CHKERRQ(ierr);
1556 
1557   PetscGlobalArgc = 0;
1558   PetscGlobalArgs = NULL;
1559 
1560 #if defined(PETSC_HAVE_KOKKOS)
1561   if (PetscBeganKokkos) {
1562     ierr = PetscKokkosFinalize_Private();CHKERRQ(ierr);
1563     PetscBeganKokkos = PETSC_FALSE;
1564   }
1565 #endif
1566 
1567   ierr = PetscFreeMPIResources();CHKERRQ(ierr);
1568 
1569   /*
1570      Destroy any known inner MPI_Comm's and attributes pointing to them
1571      Note this will not destroy any new communicators the user has created.
1572 
1573      If all PETSc objects were not destroyed those left over objects will have hanging references to
1574      the MPI_Comms that were freed; but that is ok because those PETSc objects will never be used again
1575  */
1576   {
1577     PetscCommCounter *counter;
1578     PetscMPIInt      flg;
1579     MPI_Comm         icomm;
1580     union {MPI_Comm comm; void *ptr;} ucomm;
1581     ierr = MPI_Comm_get_attr(PETSC_COMM_SELF,Petsc_InnerComm_keyval,&ucomm,&flg);CHKERRQ(ierr);
1582     if (flg) {
1583       icomm = ucomm.comm;
1584       ierr = MPI_Comm_get_attr(icomm,Petsc_Counter_keyval,&counter,&flg);CHKERRQ(ierr);
1585       if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Inner MPI_Comm does not have expected tag/name counter, problem with corrupted memory");
1586 
1587       ierr = MPI_Comm_delete_attr(PETSC_COMM_SELF,Petsc_InnerComm_keyval);CHKERRQ(ierr);
1588       ierr = MPI_Comm_delete_attr(icomm,Petsc_Counter_keyval);CHKERRQ(ierr);
1589       ierr = MPI_Comm_free(&icomm);CHKERRQ(ierr);
1590     }
1591     ierr = MPI_Comm_get_attr(PETSC_COMM_WORLD,Petsc_InnerComm_keyval,&ucomm,&flg);CHKERRQ(ierr);
1592     if (flg) {
1593       icomm = ucomm.comm;
1594       ierr = MPI_Comm_get_attr(icomm,Petsc_Counter_keyval,&counter,&flg);CHKERRQ(ierr);
1595       if (!flg) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_ARG_CORRUPT,"Inner MPI_Comm does not have expected tag/name counter, problem with corrupted memory");
1596 
1597       ierr = MPI_Comm_delete_attr(PETSC_COMM_WORLD,Petsc_InnerComm_keyval);CHKERRQ(ierr);
1598       ierr = MPI_Comm_delete_attr(icomm,Petsc_Counter_keyval);CHKERRQ(ierr);
1599       ierr = MPI_Comm_free(&icomm);CHKERRQ(ierr);
1600     }
1601   }
1602 
1603   ierr = MPI_Comm_free_keyval(&Petsc_Counter_keyval);CHKERRQ(ierr);
1604   ierr = MPI_Comm_free_keyval(&Petsc_InnerComm_keyval);CHKERRQ(ierr);
1605   ierr = MPI_Comm_free_keyval(&Petsc_OuterComm_keyval);CHKERRQ(ierr);
1606   ierr = MPI_Comm_free_keyval(&Petsc_ShmComm_keyval);CHKERRQ(ierr);
1607 
1608   ierr = PetscSpinlockDestroy(&PetscViewerASCIISpinLockOpen);CHKERRQ(ierr);
1609   ierr = PetscSpinlockDestroy(&PetscViewerASCIISpinLockStdout);CHKERRQ(ierr);
1610   ierr = PetscSpinlockDestroy(&PetscViewerASCIISpinLockStderr);CHKERRQ(ierr);
1611   ierr = PetscSpinlockDestroy(&PetscCommSpinLock);CHKERRQ(ierr);
1612 
1613   if (PetscBeganMPI) {
1614 #if defined(PETSC_HAVE_MPI_FINALIZED)
1615     PetscMPIInt flag;
1616     ierr = MPI_Finalized(&flag);CHKERRQ(ierr);
1617     if (flag) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"MPI_Finalize() has already been called, even though MPI_Init() was called by PetscInitialize()");
1618 #endif
1619     ierr = MPI_Finalize();CHKERRQ(ierr);
1620   }
1621 /*
1622 
1623      Note: In certain cases PETSC_COMM_WORLD is never MPI_Comm_free()ed because
1624    the communicator has some outstanding requests on it. Specifically if the
1625    flag PETSC_HAVE_BROKEN_REQUEST_FREE is set (for IBM MPI implementation). See
1626    src/vec/utils/vpscat.c. Due to this the memory allocated in PetscCommDuplicate()
1627    is never freed as it should be. Thus one may obtain messages of the form
1628    [ 1] 8 bytes PetscCommDuplicate() line 645 in src/sys/mpiu.c indicating the
1629    memory was not freed.
1630 
1631 */
1632   ierr = PetscMallocClear();CHKERRQ(ierr);
1633 
1634   PetscErrorHandlingInitialized = PETSC_FALSE;
1635   PetscInitializeCalled = PETSC_FALSE;
1636   PetscFinalizeCalled   = PETSC_TRUE;
1637 #if defined(PETSC_USE_GCOV)
1638   /*
1639      flush gcov, otherwise during CI the flushing continues into the next pipeline resulting in git not being able to delete directories since the
1640      gcov files are still being added to the directories as git tries to remove the directories.
1641    */
1642   __gcov_flush();
1643 #endif
1644   PetscFunctionReturn(0);
1645 }
1646 
1647 #if defined(PETSC_MISSING_LAPACK_lsame_)
1648 PETSC_EXTERN int lsame_(char *a,char *b)
1649 {
1650   if (*a == *b) return 1;
1651   if (*a + 32 == *b) return 1;
1652   if (*a - 32 == *b) return 1;
1653   return 0;
1654 }
1655 #endif
1656 
1657 #if defined(PETSC_MISSING_LAPACK_lsame)
1658 PETSC_EXTERN int lsame(char *a,char *b)
1659 {
1660   if (*a == *b) return 1;
1661   if (*a + 32 == *b) return 1;
1662   if (*a - 32 == *b) return 1;
1663   return 0;
1664 }
1665 #endif
1666