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