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