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