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