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