Actual source code: pinit.c
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>
6: #include <petscviewer.h>
7: #include <petsc/private/garbagecollector.h>
9: #if !defined(PETSC_HAVE_WINDOWS_COMPILERS)
10: #include <petsc/private/valgrind/valgrind.h>
11: #endif
13: #if defined(PETSC_HAVE_FORTRAN)
14: #include <petsc/private/fortranimpl.h>
15: #endif
17: #if defined(PETSC_USE_GCOV)
18: EXTERN_C_BEGIN
19: #if defined(PETSC_HAVE___GCOV_DUMP)
21: #endif
22: void __gcov_flush(void);
23: EXTERN_C_END
24: #endif
26: #if defined(PETSC_SERIALIZE_FUNCTIONS)
27: PETSC_INTERN PetscFPT PetscFPTData;
28: PetscFPT PetscFPTData = 0;
29: #endif
31: #if PetscDefined(HAVE_SAWS)
32: #include <petscviewersaws.h>
33: #endif
35: /* -----------------------------------------------------------------------------------------*/
37: PETSC_INTERN FILE *petsc_history;
39: PETSC_INTERN PetscErrorCode PetscInitialize_DynamicLibraries(void);
40: PETSC_INTERN PetscErrorCode PetscFinalize_DynamicLibraries(void);
41: PETSC_INTERN PetscErrorCode PetscSequentialPhaseBegin_Private(MPI_Comm, int);
42: PETSC_INTERN PetscErrorCode PetscSequentialPhaseEnd_Private(MPI_Comm, int);
43: PETSC_INTERN PetscErrorCode PetscCloseHistoryFile(FILE **);
45: /* user may set these BEFORE calling PetscInitialize() */
46: MPI_Comm PETSC_COMM_WORLD = MPI_COMM_NULL;
47: #if PetscDefined(HAVE_MPI_INIT_THREAD)
48: PetscMPIInt PETSC_MPI_THREAD_REQUIRED = MPI_THREAD_FUNNELED;
49: #else
50: PetscMPIInt PETSC_MPI_THREAD_REQUIRED = 0;
51: #endif
53: PetscMPIInt Petsc_Counter_keyval = MPI_KEYVAL_INVALID;
54: PetscMPIInt Petsc_InnerComm_keyval = MPI_KEYVAL_INVALID;
55: PetscMPIInt Petsc_OuterComm_keyval = MPI_KEYVAL_INVALID;
56: PetscMPIInt Petsc_ShmComm_keyval = MPI_KEYVAL_INVALID;
57: PetscMPIInt Petsc_CreationIdx_keyval = MPI_KEYVAL_INVALID;
58: PetscMPIInt Petsc_Garbage_HMap_keyval = MPI_KEYVAL_INVALID;
60: /*
61: Declare and set all the string names of the PETSc enums
62: */
63: const char *const PetscBools[] = {"FALSE", "TRUE", "PetscBool", "PETSC_", NULL};
64: const char *const PetscCopyModes[] = {"COPY_VALUES", "OWN_POINTER", "USE_POINTER", "PetscCopyMode", "PETSC_", NULL};
66: PetscBool PetscPreLoadingUsed = PETSC_FALSE;
67: PetscBool PetscPreLoadingOn = PETSC_FALSE;
69: PetscInt PetscHotRegionDepth;
71: PetscBool PETSC_RUNNING_ON_VALGRIND = PETSC_FALSE;
73: #if defined(PETSC_HAVE_THREADSAFETY)
74: PetscSpinlock PetscViewerASCIISpinLockOpen;
75: PetscSpinlock PetscViewerASCIISpinLockStdout;
76: PetscSpinlock PetscViewerASCIISpinLockStderr;
77: PetscSpinlock PetscCommSpinLock;
78: #endif
80: /*
81: PetscInitializeNoPointers - Calls PetscInitialize() from C/C++ without the pointers to argc and args
83: Collective
85: Level: advanced
87: Notes:
88: this is called only by the PETSc Julia interface. Even though it might start MPI it sets the flag to
89: indicate that it did NOT start MPI so that the PetscFinalize() does not end MPI, thus allowing PetscInitialize() to
90: be called multiple times from Julia without the problem of trying to initialize MPI more than once.
92: Developer Note: Turns off PETSc signal handling to allow Julia to manage signals
94: .seealso: `PetscInitialize()`, `PetscInitializeFortran()`, `PetscInitializeNoArguments()`
95: */
96: PetscErrorCode PetscInitializeNoPointers(int argc, char **args, const char *filename, const char *help)
97: {
98: int myargc = argc;
99: char **myargs = args;
101: PetscInitialize(&myargc, &myargs, filename, help);
102: PetscPopSignalHandler();
103: PetscBeganMPI = PETSC_FALSE;
104: return 0;
105: }
107: /*
108: Used by Julia interface to get communicator
109: */
110: PetscErrorCode PetscGetPETSC_COMM_SELF(MPI_Comm *comm)
111: {
113: *comm = PETSC_COMM_SELF;
114: return 0;
115: }
117: /*@C
118: PetscInitializeNoArguments - Calls `PetscInitialize()` from C/C++ without
119: the command line arguments.
121: Collective
123: Level: advanced
125: .seealso: `PetscInitialize()`, `PetscInitializeFortran()`
126: @*/
127: PetscErrorCode PetscInitializeNoArguments(void)
128: {
129: int argc = 0;
130: char **args = NULL;
132: PetscInitialize(&argc, &args, NULL, NULL);
133: return 0;
134: }
136: /*@
137: PetscInitialized - Determine whether PETSc is initialized.
139: Level: beginner
141: .seealso: `PetscInitialize()`, `PetscInitializeNoArguments()`, `PetscInitializeFortran()`
142: @*/
143: PetscErrorCode PetscInitialized(PetscBool *isInitialized)
144: {
146: *isInitialized = PetscInitializeCalled;
147: return 0;
148: }
150: /*@
151: PetscFinalized - Determine whether `PetscFinalize()` has been called yet
153: Level: developer
155: .seealso: `PetscInitialize()`, `PetscInitializeNoArguments()`, `PetscInitializeFortran()`
156: @*/
157: PetscErrorCode PetscFinalized(PetscBool *isFinalized)
158: {
160: *isFinalized = PetscFinalizeCalled;
161: return 0;
162: }
164: PETSC_INTERN PetscErrorCode PetscOptionsCheckInitial_Private(const char[]);
166: /*
167: This function is the MPI reduction operation used to compute the sum of the
168: first half of the datatype and the max of the second half.
169: */
170: MPI_Op MPIU_MAXSUM_OP = 0;
171: MPI_Op Petsc_Garbage_SetIntersectOp = 0;
173: PETSC_INTERN void MPIAPI MPIU_MaxSum_Local(void *in, void *out, int *cnt, MPI_Datatype *datatype)
174: {
175: PetscInt *xin = (PetscInt *)in, *xout = (PetscInt *)out, i, count = *cnt;
177: if (*datatype != MPIU_2INT) {
178: (*PetscErrorPrintf)("Can only handle MPIU_2INT data types");
179: PETSCABORT(MPI_COMM_SELF, PETSC_ERR_ARG_WRONG);
180: }
182: for (i = 0; i < count; i++) {
183: xout[2 * i] = PetscMax(xout[2 * i], xin[2 * i]);
184: xout[2 * i + 1] += xin[2 * i + 1];
185: }
186: return;
187: }
189: /*
190: Returns the max of the first entry owned by this processor and the
191: sum of the second entry.
193: The reason sizes[2*i] contains lengths sizes[2*i+1] contains flag of 1 if length is nonzero
194: is so that the MPIU_MAXSUM_OP() can set TWO values, if we passed in only sizes[i] with lengths
195: there would be no place to store the both needed results.
196: */
197: PetscErrorCode PetscMaxSum(MPI_Comm comm, const PetscInt sizes[], PetscInt *max, PetscInt *sum)
198: {
199: #if defined(PETSC_HAVE_MPI_REDUCE_SCATTER_BLOCK)
200: {
201: struct {
202: PetscInt max, sum;
203: } work;
204: MPI_Reduce_scatter_block((void *)sizes, &work, 1, MPIU_2INT, MPIU_MAXSUM_OP, comm);
205: *max = work.max;
206: *sum = work.sum;
207: }
208: #else
209: {
210: PetscMPIInt size, rank;
211: struct {
212: PetscInt max, sum;
213: } *work;
214: MPI_Comm_size(comm, &size);
215: MPI_Comm_rank(comm, &rank);
216: PetscMalloc1(size, &work);
217: MPIU_Allreduce((void *)sizes, work, size, MPIU_2INT, MPIU_MAXSUM_OP, comm);
218: *max = work[rank].max;
219: *sum = work[rank].sum;
220: PetscFree(work);
221: }
222: #endif
223: return 0;
224: }
226: /* ----------------------------------------------------------------------------*/
228: #if defined(PETSC_HAVE_REAL___FLOAT128) || defined(PETSC_HAVE_REAL___FP16)
229: #if defined(PETSC_HAVE_REAL___FLOAT128)
230: #include <quadmath.h>
231: #endif
232: MPI_Op MPIU_SUM___FP16___FLOAT128 = 0;
233: #if defined(PETSC_USE_REAL___FLOAT128) || defined(PETSC_USE_REAL___FP16)
234: MPI_Op MPIU_SUM = 0;
235: #endif
237: PETSC_EXTERN void MPIAPI PetscSum_Local(void *in, void *out, PetscMPIInt *cnt, MPI_Datatype *datatype)
238: {
239: PetscInt i, count = *cnt;
241: if (*datatype == MPIU_REAL) {
242: PetscReal *xin = (PetscReal *)in, *xout = (PetscReal *)out;
243: for (i = 0; i < count; i++) xout[i] += xin[i];
244: }
245: #if defined(PETSC_HAVE_COMPLEX)
246: else if (*datatype == MPIU_COMPLEX) {
247: PetscComplex *xin = (PetscComplex *)in, *xout = (PetscComplex *)out;
248: for (i = 0; i < count; i++) xout[i] += xin[i];
249: }
250: #endif
251: #if defined(PETSC_HAVE_REAL___FLOAT128)
252: else if (*datatype == MPIU___FLOAT128) {
253: __float128 *xin = (__float128 *)in, *xout = (__float128 *)out;
254: for (i = 0; i < count; i++) xout[i] += xin[i];
255: } else if (*datatype == MPIU___COMPLEX128) {
256: __complex128 *xin = (__complex128 *)in, *xout = (__complex128 *)out;
257: for (i = 0; i < count; i++) xout[i] += xin[i];
258: }
259: #endif
260: #if defined(PETSC_HAVE_REAL___FP16)
261: else if (*datatype == MPIU___FP16) {
262: __fp16 *xin = (__fp16 *)in, *xout = (__fp16 *)out;
263: for (i = 0; i < count; i++) xout[i] += xin[i];
264: }
265: #endif
266: else {
267: #if !defined(PETSC_HAVE_REAL___FLOAT128) && !defined(PETSC_HAVE_REAL___FP16)
268: (*PetscErrorPrintf)("Can only handle MPIU_REAL or MPIU_COMPLEX data types");
269: #elif !defined(PETSC_HAVE_REAL___FP16)
270: (*PetscErrorPrintf)("Can only handle MPIU_REAL, MPIU_COMPLEX, MPIU___FLOAT128, or MPIU___COMPLEX128 data types");
271: #elif !defined(PETSC_HAVE_REAL___FLOAT128)
272: (*PetscErrorPrintf)("Can only handle MPIU_REAL, MPIU_COMPLEX, or MPIU___FP16 data types");
273: #else
274: (*PetscErrorPrintf)("Can only handle MPIU_REAL, MPIU_COMPLEX, MPIU___FLOAT128, MPIU___COMPLEX128, or MPIU___FP16 data types");
275: #endif
276: PETSCABORT(MPI_COMM_SELF, PETSC_ERR_ARG_WRONG);
277: }
278: return;
279: }
280: #endif
282: #if defined(PETSC_USE_REAL___FLOAT128) || defined(PETSC_USE_REAL___FP16)
283: MPI_Op MPIU_MAX = 0;
284: MPI_Op MPIU_MIN = 0;
286: PETSC_EXTERN void MPIAPI PetscMax_Local(void *in, void *out, PetscMPIInt *cnt, MPI_Datatype *datatype)
287: {
288: PetscInt i, count = *cnt;
290: if (*datatype == MPIU_REAL) {
291: PetscReal *xin = (PetscReal *)in, *xout = (PetscReal *)out;
292: for (i = 0; i < count; i++) xout[i] = PetscMax(xout[i], xin[i]);
293: }
294: #if defined(PETSC_HAVE_COMPLEX)
295: else if (*datatype == MPIU_COMPLEX) {
296: PetscComplex *xin = (PetscComplex *)in, *xout = (PetscComplex *)out;
297: for (i = 0; i < count; i++) xout[i] = PetscRealPartComplex(xout[i]) < PetscRealPartComplex(xin[i]) ? xin[i] : xout[i];
298: }
299: #endif
300: else {
301: (*PetscErrorPrintf)("Can only handle MPIU_REAL or MPIU_COMPLEX data types");
302: PETSCABORT(MPI_COMM_SELF, PETSC_ERR_ARG_WRONG);
303: }
304: return;
305: }
307: PETSC_EXTERN void MPIAPI PetscMin_Local(void *in, void *out, PetscMPIInt *cnt, MPI_Datatype *datatype)
308: {
309: PetscInt i, count = *cnt;
311: if (*datatype == MPIU_REAL) {
312: PetscReal *xin = (PetscReal *)in, *xout = (PetscReal *)out;
313: for (i = 0; i < count; i++) xout[i] = PetscMin(xout[i], xin[i]);
314: }
315: #if defined(PETSC_HAVE_COMPLEX)
316: else if (*datatype == MPIU_COMPLEX) {
317: PetscComplex *xin = (PetscComplex *)in, *xout = (PetscComplex *)out;
318: for (i = 0; i < count; i++) xout[i] = PetscRealPartComplex(xout[i]) > PetscRealPartComplex(xin[i]) ? xin[i] : xout[i];
319: }
320: #endif
321: else {
322: (*PetscErrorPrintf)("Can only handle MPIU_REAL or MPIU_SCALAR data (i.e. double or complex) types");
323: PETSCABORT(MPI_COMM_SELF, PETSC_ERR_ARG_WRONG);
324: }
325: return;
326: }
327: #endif
329: /*
330: Private routine to delete internal tag/name counter storage when a communicator is freed.
332: 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.
334: Note: this is declared extern "C" because it is passed to MPI_Comm_create_keyval()
336: */
337: PETSC_EXTERN PetscMPIInt MPIAPI Petsc_Counter_Attr_Delete_Fn(MPI_Comm comm, PetscMPIInt keyval, void *count_val, void *extra_state)
338: {
339: PetscCommCounter *counter = (PetscCommCounter *)count_val;
340: struct PetscCommStash *comms = counter->comms, *pcomm;
342: PetscInfo(NULL, "Deleting counter data in an MPI_Comm %ld\n", (long)comm);
343: PetscFree(counter->iflags);
344: while (comms) {
345: MPI_Comm_free(&comms->comm);
346: pcomm = comms;
347: comms = comms->next;
348: PetscFree(pcomm);
349: }
350: PetscFree(counter);
351: return MPI_SUCCESS;
352: }
354: /*
355: This is invoked on the outer comm as a result of either PetscCommDestroy() (via MPI_Comm_delete_attr) or when the user
356: calls MPI_Comm_free().
358: This is the only entry point for breaking the links between inner and outer comms.
360: This is called by MPI, not by users. This is called when MPI_Comm_free() is called on the communicator.
362: Note: this is declared extern "C" because it is passed to MPI_Comm_create_keyval()
364: */
365: PETSC_EXTERN PetscMPIInt MPIAPI Petsc_InnerComm_Attr_Delete_Fn(MPI_Comm comm, PetscMPIInt keyval, void *attr_val, void *extra_state)
366: {
367: union
368: {
369: MPI_Comm comm;
370: void *ptr;
371: } icomm;
373: if (keyval != Petsc_InnerComm_keyval) SETERRMPI(PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Unexpected keyval");
374: icomm.ptr = attr_val;
375: if (PetscDefined(USE_DEBUG)) {
376: /* Error out if the inner/outer comms are not correctly linked through their Outer/InnterComm attributes */
377: PetscMPIInt flg;
378: union
379: {
380: MPI_Comm comm;
381: void *ptr;
382: } ocomm;
383: MPI_Comm_get_attr(icomm.comm, Petsc_OuterComm_keyval, &ocomm, &flg);
384: if (!flg) SETERRMPI(PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Inner comm does not have OuterComm attribute");
385: if (ocomm.comm != comm) SETERRMPI(PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Inner comm's OuterComm attribute does not point to outer PETSc comm");
386: }
387: MPI_Comm_delete_attr(icomm.comm, Petsc_OuterComm_keyval);
388: PetscInfo(NULL, "User MPI_Comm %ld is being unlinked from inner PETSc comm %ld\n", (long)comm, (long)icomm.comm);
389: return MPI_SUCCESS;
390: }
392: /*
393: * 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.
394: */
395: PETSC_EXTERN PetscMPIInt MPIAPI Petsc_OuterComm_Attr_Delete_Fn(MPI_Comm comm, PetscMPIInt keyval, void *attr_val, void *extra_state)
396: {
397: PetscInfo(NULL, "Removing reference to PETSc communicator embedded in a user MPI_Comm %ld\n", (long)comm);
398: return MPI_SUCCESS;
399: }
401: PETSC_EXTERN PetscMPIInt MPIAPI Petsc_ShmComm_Attr_Delete_Fn(MPI_Comm, PetscMPIInt, void *, void *);
403: #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
404: PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype, MPI_Aint *, void *);
405: PETSC_EXTERN PetscMPIInt PetscDataRep_read_conv_fn(void *, MPI_Datatype, PetscMPIInt, void *, MPI_Offset, void *);
406: PETSC_EXTERN PetscMPIInt PetscDataRep_write_conv_fn(void *, MPI_Datatype, PetscMPIInt, void *, MPI_Offset, void *);
407: #endif
409: PetscMPIInt PETSC_MPI_ERROR_CLASS = MPI_ERR_LASTCODE, PETSC_MPI_ERROR_CODE;
411: PETSC_INTERN int PetscGlobalArgc;
412: PETSC_INTERN char **PetscGlobalArgs;
413: int PetscGlobalArgc = 0;
414: char **PetscGlobalArgs = NULL;
415: PetscSegBuffer PetscCitationsList;
417: PetscErrorCode PetscCitationsInitialize(void)
418: {
419: PetscSegBufferCreate(1, 10000, &PetscCitationsList);
421: PetscCall(PetscCitationsRegister("@TechReport{petsc-user-ref,\n\
422: Author = {Satish Balay and Shrirang Abhyankar and Mark~F. Adams and Steven Benson and Jed Brown\n\
423: and Peter Brune and Kris Buschelman and Emil Constantinescu and Lisandro Dalcin and Alp Dener\n\
424: and Victor Eijkhout and Jacob Faibussowitsch and William~D. Gropp and V\'{a}clav Hapla and Tobin Isaac and Pierre Jolivet\n\
425: and Dmitry Karpeev and Dinesh Kaushik and Matthew~G. Knepley and Fande Kong and Scott Kruger\n\
426: and Dave~A. May and Lois Curfman McInnes and Richard Tran Mills and Lawrence Mitchell and Todd Munson\n\
427: and Jose~E. Roman and Karl Rupp and Patrick Sanan and Jason Sarich and Barry~F. Smith\n\
428: and Stefano Zampini and Hong Zhang and Hong Zhang and Junchao Zhang},\n\
429: Title = {{PETSc/TAO} Users Manual},\n\
430: Number = {ANL-21/39 - Revision 3.18},\n\
431: Institution = {Argonne National Laboratory},\n\
432: Year = {2022}\n}\n",
433: NULL));
435: PetscCall(PetscCitationsRegister("@InProceedings{petsc-efficient,\n\
436: Author = {Satish Balay and William D. Gropp and Lois Curfman McInnes and Barry F. Smith},\n\
437: Title = {Efficient Management of Parallelism in Object Oriented Numerical Software Libraries},\n\
438: Booktitle = {Modern Software Tools in Scientific Computing},\n\
439: Editor = {E. Arge and A. M. Bruaset and H. P. Langtangen},\n\
440: Pages = {163--202},\n\
441: Publisher = {Birkh{\\\"{a}}user Press},\n\
442: Year = {1997}\n}\n",
443: NULL));
445: return 0;
446: }
448: static char programname[PETSC_MAX_PATH_LEN] = ""; /* HP includes entire path in name */
450: PetscErrorCode PetscSetProgramName(const char name[])
451: {
452: PetscStrncpy(programname, name, sizeof(programname));
453: return 0;
454: }
456: /*@C
457: PetscGetProgramName - Gets the name of the running program.
459: Not Collective
461: Input Parameter:
462: . len - length of the string name
464: Output Parameter:
465: . name - the name of the running program, provide a string of length `PETSC_MAX_PATH_LEN`
467: Level: advanced
469: @*/
470: PetscErrorCode PetscGetProgramName(char name[], size_t len)
471: {
472: PetscStrncpy(name, programname, len);
473: return 0;
474: }
476: /*@C
477: PetscGetArgs - Allows you to access the raw command line arguments anywhere
478: after PetscInitialize() is called but before `PetscFinalize()`.
480: Not Collective
482: Output Parameters:
483: + argc - count of number of command line arguments
484: - args - the command line arguments
486: Level: intermediate
488: Notes:
489: This is usually used to pass the command line arguments into other libraries
490: that are called internally deep in PETSc or the application.
492: The first argument contains the program name as is normal for C arguments.
494: .seealso: `PetscFinalize()`, `PetscInitializeFortran()`, `PetscGetArguments()`
495: @*/
496: PetscErrorCode PetscGetArgs(int *argc, char ***args)
497: {
499: *argc = PetscGlobalArgc;
500: *args = PetscGlobalArgs;
501: return 0;
502: }
504: /*@C
505: PetscGetArguments - Allows you to access the command line arguments anywhere
506: after `PetscInitialize()` is called but before `PetscFinalize()`.
508: Not Collective
510: Output Parameters:
511: . args - the command line arguments
513: Level: intermediate
515: Notes:
516: This does NOT start with the program name and IS null terminated (final arg is void)
518: .seealso: `PetscFinalize()`, `PetscInitializeFortran()`, `PetscGetArgs()`, `PetscFreeArguments()`
519: @*/
520: PetscErrorCode PetscGetArguments(char ***args)
521: {
522: PetscInt i, argc = PetscGlobalArgc;
525: if (!argc) {
526: *args = NULL;
527: return 0;
528: }
529: PetscMalloc1(argc, args);
530: for (i = 0; i < argc - 1; i++) PetscStrallocpy(PetscGlobalArgs[i + 1], &(*args)[i]);
531: (*args)[argc - 1] = NULL;
532: return 0;
533: }
535: /*@C
536: PetscFreeArguments - Frees the memory obtained with `PetscGetArguments()`
538: Not Collective
540: Output Parameters:
541: . args - the command line arguments
543: Level: intermediate
545: .seealso: `PetscFinalize()`, `PetscInitializeFortran()`, `PetscGetArgs()`, `PetscGetArguments()`
546: @*/
547: PetscErrorCode PetscFreeArguments(char **args)
548: {
549: if (args) {
550: PetscInt i = 0;
552: while (args[i]) PetscFree(args[i++]);
553: PetscFree(args);
554: }
555: return 0;
556: }
558: #if PetscDefined(HAVE_SAWS)
559: #include <petscconfiginfo.h>
561: PETSC_INTERN PetscErrorCode PetscInitializeSAWs(const char help[])
562: {
563: if (!PetscGlobalRank) {
564: char cert[PETSC_MAX_PATH_LEN], root[PETSC_MAX_PATH_LEN], *intro, programname[64], *appline, *options, version[64];
565: int port;
566: PetscBool flg, rootlocal = PETSC_FALSE, flg2, selectport = PETSC_FALSE;
567: size_t applinelen, introlen;
568: char sawsurl[256];
570: PetscOptionsHasName(NULL, NULL, "-saws_log", &flg);
571: if (flg) {
572: char sawslog[PETSC_MAX_PATH_LEN];
574: PetscOptionsGetString(NULL, NULL, "-saws_log", sawslog, sizeof(sawslog), NULL);
575: if (sawslog[0]) {
576: SAWs_Set_Use_Logfile, (sawslog);
577: } else {
578: SAWs_Set_Use_Logfile, (NULL);
579: }
580: }
581: PetscOptionsGetString(NULL, NULL, "-saws_https", cert, sizeof(cert), &flg);
582: if (flg) SAWs_Set_Use_HTTPS, (cert);
583: PetscOptionsGetBool(NULL, NULL, "-saws_port_auto_select", &selectport, NULL);
584: if (selectport) {
585: SAWs_Get_Available_Port, (&port);
586: SAWs_Set_Port, (port);
587: } else {
588: PetscOptionsGetInt(NULL, NULL, "-saws_port", &port, &flg);
589: if (flg) SAWs_Set_Port, (port);
590: }
591: PetscOptionsGetString(NULL, NULL, "-saws_root", root, sizeof(root), &flg);
592: if (flg) {
593: SAWs_Set_Document_Root, (root);
594: PetscStrcmp(root, ".", &rootlocal);
595: } else {
596: PetscOptionsHasName(NULL, NULL, "-saws_options", &flg);
597: if (flg) {
598: PetscStrreplace(PETSC_COMM_WORLD, "${PETSC_DIR}/share/petsc/saws", root, sizeof(root));
599: SAWs_Set_Document_Root, (root);
600: }
601: }
602: PetscOptionsHasName(NULL, NULL, "-saws_local", &flg2);
603: if (flg2) {
604: char jsdir[PETSC_MAX_PATH_LEN];
606: PetscSNPrintf(jsdir, sizeof(jsdir), "%s/js", root);
607: PetscTestDirectory(jsdir, 'r', &flg);
609: SAWs_Push_Local_Header, ();
610: }
611: PetscGetProgramName(programname, sizeof(programname));
612: PetscStrlen(help, &applinelen);
613: introlen = 4096 + applinelen;
614: applinelen += 1024;
615: PetscMalloc(applinelen, &appline);
616: PetscMalloc(introlen, &intro);
618: if (rootlocal) {
619: PetscSNPrintf(appline, applinelen, "%s.c.html", programname);
620: PetscTestFile(appline, 'r', &rootlocal);
621: }
622: PetscOptionsGetAll(NULL, &options);
623: if (rootlocal && help) {
624: 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);
625: } else if (help) {
626: PetscSNPrintf(appline, applinelen, "<center>Running %s %s</center><br><center><pre>%s</pre></center><br>", programname, options, help);
627: } else {
628: PetscSNPrintf(appline, applinelen, "<center> Running %s %s</center><br>\n", programname, options);
629: }
630: PetscFree(options);
631: PetscGetVersion(version, sizeof(version));
632: PetscCall(PetscSNPrintf(intro, introlen,
633: "<body>\n"
634: "<center><h2> <a href=\"https://petsc.org/\">PETSc</a> Application Web server powered by <a href=\"https://bitbucket.org/saws/saws\">SAWs</a> </h2></center>\n"
635: "<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"
636: "%s",
637: version, petscconfigureoptions, appline));
638: SAWs_Push_Body, ("index.html", 0, intro);
639: PetscFree(intro);
640: PetscFree(appline);
641: if (selectport) {
642: PetscBool silent;
644: /* another process may have grabbed the port so keep trying */
645: while (SAWs_Initialize()) {
646: SAWs_Get_Available_Port, (&port);
647: SAWs_Set_Port, (port);
648: }
650: PetscOptionsGetBool(NULL, NULL, "-saws_port_auto_select_silent", &silent, NULL);
651: if (!silent) {
652: SAWs_Get_FullURL, (sizeof(sawsurl), sawsurl);
653: PetscPrintf(PETSC_COMM_WORLD, "Point your browser to %s for SAWs\n", sawsurl);
654: }
655: } else {
656: SAWs_Initialize, ();
657: }
658: PetscCall(PetscCitationsRegister("@TechReport{ saws,\n"
659: " Author = {Matt Otten and Jed Brown and Barry Smith},\n"
660: " Title = {Scientific Application Web Server (SAWs) Users Manual},\n"
661: " Institution = {Argonne National Laboratory},\n"
662: " Year = 2013\n}\n",
663: NULL));
664: }
665: return 0;
666: }
667: #endif
669: /* Things must be done before MPI_Init() when MPI is not yet initialized, and can be shared between C init and Fortran init */
670: PETSC_INTERN PetscErrorCode PetscPreMPIInit_Private(void)
671: {
672: #if defined(PETSC_HAVE_HWLOC_SOLARIS_BUG)
673: /* see MPI.py for details on this bug */
674: (void)setenv("HWLOC_COMPONENTS", "-x86", 1);
675: #endif
676: return 0;
677: }
679: #if PetscDefined(HAVE_ADIOS)
680: #include <adios.h>
681: #include <adios_read.h>
682: int64_t Petsc_adios_group;
683: #endif
684: #if PetscDefined(HAVE_OPENMP)
685: #include <omp.h>
686: PetscInt PetscNumOMPThreads;
687: #endif
689: #include <petsc/private/deviceimpl.h>
690: #if PetscDefined(HAVE_CUDA)
691: #include <petscdevice_cuda.h>
692: // REMOVE ME
693: cudaStream_t PetscDefaultCudaStream = NULL;
694: #endif
695: #if PetscDefined(HAVE_HIP)
696: #include <petscdevice_hip.h>
697: // REMOVE ME
698: hipStream_t PetscDefaultHipStream = NULL;
699: #endif
701: #if PetscDefined(HAVE_DLFCN_H)
702: #include <dlfcn.h>
703: #endif
704: #if PetscDefined(USE_LOG)
705: PETSC_INTERN PetscErrorCode PetscLogInitialize(void);
706: #endif
707: #if PetscDefined(HAVE_VIENNACL)
708: PETSC_EXTERN PetscErrorCode PetscViennaCLInit(void);
709: PetscBool PetscViennaCLSynchronize = PETSC_FALSE;
710: #endif
712: PetscBool PetscCIEnabled = PETSC_FALSE, PetscCIEnabledPortableErrorOutput = PETSC_FALSE;
714: /*
715: PetscInitialize_Common - shared code between C and Fortran initialization
717: prog: program name
718: file: optional PETSc database file name. Might be in Fortran string format when 'ftn' is true
719: help: program help message
720: ftn: is it called from Fortran initialization (petscinitializef_)?
721: readarguments,len: used when fortran is true
722: */
723: PETSC_INTERN PetscErrorCode PetscInitialize_Common(const char *prog, const char *file, const char *help, PetscBool ftn, PetscBool readarguments, PetscInt len)
724: {
725: PetscMPIInt size;
726: PetscBool flg = PETSC_TRUE;
727: char hostname[256];
729: if (PetscInitializeCalled) return 0;
730: /* these must be initialized in a routine, not as a constant declaration */
731: PETSC_STDOUT = stdout;
732: PETSC_STDERR = stderr;
734: /* PetscCall can be used from now */
735: PetscErrorHandlingInitialized = PETSC_TRUE;
737: /*
738: The checking over compatible runtime libraries is complicated by the MPI ABI initiative
739: https://wiki.mpich.org/mpich/index.php/ABI_Compatibility_Initiative which started with
740: MPICH v3.1 (Released February 2014)
741: IBM MPI v2.1 (December 2014)
742: Intel MPI Library v5.0 (2014)
743: Cray MPT v7.0.0 (June 2014)
744: As of July 31, 2017 the ABI number still appears to be 12, that is all of the versions
745: listed above and since that time are compatible.
747: Unfortunately the MPI ABI initiative has not defined a way to determine the ABI number
748: at compile time or runtime. Thus we will need to systematically track the allowed versions
749: and how they are represented in the mpi.h and MPI_Get_library_version() output in order
750: to perform the checking.
752: Currently we only check for pre MPI ABI versions (and packages that do not follow the MPI ABI).
754: Questions:
756: Should the checks for ABI incompatibility be only on the major version number below?
757: Presumably the output to stderr will be removed before a release.
758: */
760: #if defined(PETSC_HAVE_MPI_GET_LIBRARY_VERSION)
761: {
762: char mpilibraryversion[MPI_MAX_LIBRARY_VERSION_STRING];
763: PetscMPIInt mpilibraryversionlength;
765: MPI_Get_library_version(mpilibraryversion, &mpilibraryversionlength);
766: /* check for MPICH versions before MPI ABI initiative */
767: #if defined(MPICH_VERSION)
768: #if MPICH_NUMVERSION < 30100000
769: {
770: char *ver, *lf;
771: PetscBool flg = PETSC_FALSE;
773: PetscStrstr(mpilibraryversion, "MPICH Version:", &ver);
774: if (ver) {
775: PetscStrchr(ver, '\n', &lf);
776: if (lf) {
777: *lf = 0;
778: PetscStrendswith(ver, MPICH_VERSION, &flg);
779: }
780: }
781: if (!flg) {
782: PetscInfo(NULL, "PETSc warning --- MPICH library version \n%s does not match what PETSc was compiled with %s.\n", mpilibraryversion, MPICH_VERSION);
783: flg = PETSC_TRUE;
784: }
785: }
786: #endif
787: /* check for OpenMPI version, it is not part of the MPI ABI initiative (is it part of another initiative that needs to be handled?) */
788: #elif defined(OMPI_MAJOR_VERSION)
789: {
790: char *ver, bs[MPI_MAX_LIBRARY_VERSION_STRING], *bsf;
791: PetscBool flg = PETSC_FALSE;
792: #define PSTRSZ 2
793: char ompistr1[PSTRSZ][MPI_MAX_LIBRARY_VERSION_STRING] = {"Open MPI", "FUJITSU MPI"};
794: char ompistr2[PSTRSZ][MPI_MAX_LIBRARY_VERSION_STRING] = {"v", "Library "};
795: int i;
796: for (i = 0; i < PSTRSZ; i++) {
797: PetscStrstr(mpilibraryversion, ompistr1[i], &ver);
798: if (ver) {
799: PetscSNPrintf(bs, MPI_MAX_LIBRARY_VERSION_STRING, "%s%d.%d", ompistr2[i], OMPI_MAJOR_VERSION, OMPI_MINOR_VERSION);
800: PetscStrstr(ver, bs, &bsf);
801: if (bsf) flg = PETSC_TRUE;
802: break;
803: }
804: }
805: if (!flg) {
806: PetscInfo(NULL, "PETSc warning --- Open MPI library version \n%s does not match what PETSc was compiled with %d.%d.\n", mpilibraryversion, OMPI_MAJOR_VERSION, OMPI_MINOR_VERSION);
807: flg = PETSC_TRUE;
808: }
809: }
810: #endif
811: }
812: #endif
814: #if defined(PETSC_HAVE_DLADDR) && !(defined(__cray__) && defined(__clang__))
815: /* 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 */
817: #endif
819: /* on Windows - set printf to default to printing 2 digit exponents */
820: #if defined(PETSC_HAVE__SET_OUTPUT_FORMAT)
821: _set_output_format(_TWO_DIGIT_EXPONENT);
822: #endif
824: PetscOptionsCreateDefault();
826: PetscFinalizeCalled = PETSC_FALSE;
828: PetscSetProgramName(prog);
829: PetscSpinlockCreate(&PetscViewerASCIISpinLockOpen);
830: PetscSpinlockCreate(&PetscViewerASCIISpinLockStdout);
831: PetscSpinlockCreate(&PetscViewerASCIISpinLockStderr);
832: PetscSpinlockCreate(&PetscCommSpinLock);
834: if (PETSC_COMM_WORLD == MPI_COMM_NULL) PETSC_COMM_WORLD = MPI_COMM_WORLD;
835: MPI_Comm_set_errhandler(PETSC_COMM_WORLD, MPI_ERRORS_RETURN);
837: if (PETSC_MPI_ERROR_CLASS == MPI_ERR_LASTCODE) {
838: MPI_Add_error_class(&PETSC_MPI_ERROR_CLASS);
839: MPI_Add_error_code(PETSC_MPI_ERROR_CLASS, &PETSC_MPI_ERROR_CODE);
840: }
842: /* Done after init due to a bug in MPICH-GM? */
843: PetscErrorPrintfInitialize();
845: MPI_Comm_rank(MPI_COMM_WORLD, &PetscGlobalRank);
846: MPI_Comm_size(MPI_COMM_WORLD, &PetscGlobalSize);
848: MPIU_BOOL = MPI_INT;
849: MPIU_ENUM = MPI_INT;
850: MPIU_FORTRANADDR = (sizeof(void *) == sizeof(int)) ? MPI_INT : MPIU_INT64;
851: if (sizeof(size_t) == sizeof(unsigned)) MPIU_SIZE_T = MPI_UNSIGNED;
852: else if (sizeof(size_t) == sizeof(unsigned long)) MPIU_SIZE_T = MPI_UNSIGNED_LONG;
853: #if defined(PETSC_SIZEOF_LONG_LONG)
854: else if (sizeof(size_t) == sizeof(unsigned long long)) MPIU_SIZE_T = MPI_UNSIGNED_LONG_LONG;
855: #endif
856: else SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS, "Could not find MPI type for size_t");
858: /*
859: Initialized the global complex variable; this is because with
860: shared libraries the constructors for global variables
861: are not called; at least on IRIX.
862: */
863: #if defined(PETSC_HAVE_COMPLEX)
864: {
865: #if defined(PETSC_CLANGUAGE_CXX) && !defined(PETSC_USE_REAL___FLOAT128)
866: PetscComplex ic(0.0, 1.0);
867: PETSC_i = ic;
868: #else
869: PETSC_i = _Complex_I;
870: #endif
871: }
872: #endif /* PETSC_HAVE_COMPLEX */
874: /*
875: Create the PETSc MPI reduction operator that sums of the first
876: half of the entries and maxes the second half.
877: */
878: MPI_Op_create(MPIU_MaxSum_Local, 1, &MPIU_MAXSUM_OP);
880: #if defined(PETSC_HAVE_REAL___FLOAT128)
881: MPI_Type_contiguous(2, MPI_DOUBLE, &MPIU___FLOAT128);
882: MPI_Type_commit(&MPIU___FLOAT128);
883: MPI_Type_contiguous(4, MPI_DOUBLE, &MPIU___COMPLEX128);
884: MPI_Type_commit(&MPIU___COMPLEX128);
885: #endif
886: #if defined(PETSC_HAVE_REAL___FP16)
887: MPI_Type_contiguous(2, MPI_CHAR, &MPIU___FP16);
888: MPI_Type_commit(&MPIU___FP16);
889: #endif
891: #if defined(PETSC_USE_REAL___FLOAT128) || defined(PETSC_USE_REAL___FP16)
892: MPI_Op_create(PetscSum_Local, 1, &MPIU_SUM);
893: MPI_Op_create(PetscMax_Local, 1, &MPIU_MAX);
894: MPI_Op_create(PetscMin_Local, 1, &MPIU_MIN);
895: #elif defined(PETSC_HAVE_REAL___FLOAT128) || defined(PETSC_HAVE_REAL___FP16)
896: MPI_Op_create(PetscSum_Local, 1, &MPIU_SUM___FP16___FLOAT128);
897: #endif
899: MPI_Type_contiguous(2, MPIU_SCALAR, &MPIU_2SCALAR);
900: MPI_Op_create(PetscGarbageKeySortedIntersect, 1, &Petsc_Garbage_SetIntersectOp);
901: MPI_Type_commit(&MPIU_2SCALAR);
903: /* create datatypes used by MPIU_MAXLOC, MPIU_MINLOC and PetscSplitReduction_Op */
904: #if !defined(PETSC_HAVE_MPIUNI)
905: {
906: PetscMPIInt blockSizes[2] = {1, 1};
907: MPI_Aint blockOffsets[2] = {offsetof(struct petsc_mpiu_real_int, v), offsetof(struct petsc_mpiu_real_int, i)};
908: MPI_Datatype blockTypes[2] = {MPIU_REAL, MPIU_INT}, tmpStruct;
910: MPI_Type_create_struct(2, blockSizes, blockOffsets, blockTypes, &tmpStruct);
911: MPI_Type_create_resized(tmpStruct, 0, sizeof(struct petsc_mpiu_real_int), &MPIU_REAL_INT);
912: MPI_Type_free(&tmpStruct);
913: MPI_Type_commit(&MPIU_REAL_INT);
914: }
915: {
916: PetscMPIInt blockSizes[2] = {1, 1};
917: MPI_Aint blockOffsets[2] = {offsetof(struct petsc_mpiu_scalar_int, v), offsetof(struct petsc_mpiu_scalar_int, i)};
918: MPI_Datatype blockTypes[2] = {MPIU_SCALAR, MPIU_INT}, tmpStruct;
920: MPI_Type_create_struct(2, blockSizes, blockOffsets, blockTypes, &tmpStruct);
921: MPI_Type_create_resized(tmpStruct, 0, sizeof(struct petsc_mpiu_scalar_int), &MPIU_SCALAR_INT);
922: MPI_Type_free(&tmpStruct);
923: MPI_Type_commit(&MPIU_SCALAR_INT);
924: }
925: #endif
927: #if defined(PETSC_USE_64BIT_INDICES)
928: MPI_Type_contiguous(2, MPIU_INT, &MPIU_2INT);
929: MPI_Type_commit(&MPIU_2INT);
930: #endif
931: MPI_Type_contiguous(4, MPI_INT, &MPI_4INT);
932: MPI_Type_commit(&MPI_4INT);
933: MPI_Type_contiguous(4, MPIU_INT, &MPIU_4INT);
934: MPI_Type_commit(&MPIU_4INT);
936: /*
937: Attributes to be set on PETSc communicators
938: */
939: MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_Counter_Attr_Delete_Fn, &Petsc_Counter_keyval, (void *)0);
940: MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_InnerComm_Attr_Delete_Fn, &Petsc_InnerComm_keyval, (void *)0);
941: MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_OuterComm_Attr_Delete_Fn, &Petsc_OuterComm_keyval, (void *)0);
942: MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_ShmComm_Attr_Delete_Fn, &Petsc_ShmComm_keyval, (void *)0);
943: MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_CreationIdx_keyval, (void *)0);
944: MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Garbage_HMap_keyval, (void *)0);
946: #if defined(PETSC_HAVE_FORTRAN)
947: if (ftn) PetscInitFortran_Private(readarguments, file, len);
948: else
949: #endif
950: PetscOptionsInsert(NULL, &PetscGlobalArgc, &PetscGlobalArgs, file);
952: /* call a second time so it can look in the options database */
953: PetscErrorPrintfInitialize();
955: /*
956: Check system options and print help
957: */
958: PetscOptionsCheckInitial_Private(help);
960: /*
961: Creates the logging data structures; this is enabled even if logging is not turned on
962: This is the last thing we do before returning to the user code to prevent having the
963: logging numbers contaminated by any startup time associated with MPI
964: */
965: #if defined(PETSC_USE_LOG)
966: PetscLogInitialize();
967: #endif
969: /*
970: Initialize PetscDevice and PetscDeviceContext
972: Note to any future devs thinking of moving this, proper initialization requires:
973: 1. MPI initialized
974: 2. Options DB initialized
975: 3. Petsc error handling initialized, specifically signal handlers. This expects to set up
976: its own SIGSEV handler via the push/pop interface.
977: 4. Logging initialized
978: */
979: PetscDeviceInitializeFromOptions_Internal(PETSC_COMM_WORLD);
981: #if PetscDefined(HAVE_VIENNACL)
982: flg = PETSC_FALSE;
983: PetscOptionsHasName(NULL, NULL, "-log_summary", &flg);
984: if (!flg) PetscOptionsHasName(NULL, NULL, "-log_view", &flg);
985: if (!flg) PetscOptionsGetBool(NULL, NULL, "-viennacl_synchronize", &flg, NULL);
986: PetscViennaCLSynchronize = flg;
987: PetscViennaCLInit();
988: #endif
990: PetscCitationsInitialize();
992: #if defined(PETSC_HAVE_SAWS)
993: PetscInitializeSAWs(ftn ? NULL : help);
994: flg = PETSC_FALSE;
995: PetscOptionsHasName(NULL, NULL, "-stack_view", &flg);
996: if (flg) PetscStackViewSAWs();
997: #endif
999: /*
1000: Load the dynamic libraries (on machines that support them), this registers all
1001: the solvers etc. (On non-dynamic machines this initializes the PetscDraw and PetscViewer classes)
1002: */
1003: PetscInitialize_DynamicLibraries();
1005: MPI_Comm_size(PETSC_COMM_WORLD, &size);
1006: PetscInfo(NULL, "PETSc successfully started: number of processors = %d\n", size);
1007: PetscGetHostName(hostname, sizeof(hostname));
1008: PetscInfo(NULL, "Running on machine: %s\n", hostname);
1009: #if defined(PETSC_HAVE_OPENMP)
1010: {
1011: PetscBool omp_view_flag;
1012: char *threads = getenv("OMP_NUM_THREADS");
1014: if (threads) {
1015: PetscInfo(NULL, "Number of OpenMP threads %s (as given by OMP_NUM_THREADS)\n", threads);
1016: (void)sscanf(threads, "%" PetscInt_FMT, &PetscNumOMPThreads);
1017: } else {
1018: PetscNumOMPThreads = (PetscInt)omp_get_max_threads();
1019: PetscInfo(NULL, "Number of OpenMP threads %" PetscInt_FMT " (as given by omp_get_max_threads())\n", PetscNumOMPThreads);
1020: }
1021: PetscOptionsBegin(PETSC_COMM_WORLD, NULL, "OpenMP options", "Sys");
1022: PetscOptionsInt("-omp_num_threads", "Number of OpenMP threads to use (can also use environmental variable OMP_NUM_THREADS", "None", PetscNumOMPThreads, &PetscNumOMPThreads, &flg);
1023: PetscOptionsName("-omp_view", "Display OpenMP number of threads", NULL, &omp_view_flag);
1024: PetscOptionsEnd();
1025: if (flg) {
1026: PetscInfo(NULL, "Number of OpenMP theads %" PetscInt_FMT " (given by -omp_num_threads)\n", PetscNumOMPThreads);
1027: omp_set_num_threads((int)PetscNumOMPThreads);
1028: }
1029: if (omp_view_flag) PetscPrintf(PETSC_COMM_WORLD, "OpenMP: number of threads %" PetscInt_FMT "\n", PetscNumOMPThreads);
1030: }
1031: #endif
1033: #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
1034: /*
1035: Tell MPI about our own data representation converter, this would/should be used if extern32 is not supported by the MPI
1037: Currently not used because it is not supported by MPICH.
1038: */
1039: if (!PetscBinaryBigEndian()) MPI_Register_datarep((char *)"petsc", PetscDataRep_read_conv_fn, PetscDataRep_write_conv_fn, PetscDataRep_extent_fn, NULL);
1040: #endif
1042: #if defined(PETSC_SERIALIZE_FUNCTIONS)
1043: PetscFPTCreate(10000);
1044: #endif
1046: #if defined(PETSC_HAVE_HWLOC)
1047: {
1048: PetscViewer viewer;
1049: PetscOptionsGetViewer(PETSC_COMM_WORLD, NULL, NULL, "-process_view", &viewer, NULL, &flg);
1050: if (flg) {
1051: PetscProcessPlacementView(viewer);
1052: PetscViewerDestroy(&viewer);
1053: }
1054: }
1055: #endif
1057: flg = PETSC_TRUE;
1058: PetscOptionsGetBool(NULL, NULL, "-viewfromoptions", &flg, NULL);
1059: if (!flg) PetscOptionsPushGetViewerOff(PETSC_TRUE);
1061: #if defined(PETSC_HAVE_ADIOS)
1062: adios_init_noxml(PETSC_COMM_WORLD);
1063: adios_declare_group(&Petsc_adios_group, "PETSc", "", adios_stat_default);
1064: adios_select_method(Petsc_adios_group, "MPI", "", "");
1065: adios_read_init_method(ADIOS_READ_METHOD_BP, PETSC_COMM_WORLD, "");
1066: #endif
1068: #if defined(__VALGRIND_H)
1069: PETSC_RUNNING_ON_VALGRIND = RUNNING_ON_VALGRIND ? PETSC_TRUE : PETSC_FALSE;
1070: #if defined(PETSC_USING_DARWIN) && defined(PETSC_BLASLAPACK_SDOT_RETURNS_DOUBLE)
1071: if (PETSC_RUNNING_ON_VALGRIND) PetscPrintf(PETSC_COMM_WORLD, "WARNING: Running valgrind with the MacOS native BLAS and LAPACK can fail. If it fails suggest configuring with --download-fblaslapack or --download-f2cblaslapack");
1072: #endif
1073: #endif
1074: /*
1075: Set flag that we are completely initialized
1076: */
1077: PetscInitializeCalled = PETSC_TRUE;
1079: PetscOptionsHasName(NULL, NULL, "-python", &flg);
1080: if (flg) PetscPythonInitialize(NULL, NULL);
1082: PetscOptionsHasName(NULL, NULL, "-mpi_linear_solver_server", &flg);
1083: if (PetscDefined(USE_SINGLE_LIBRARY) && flg) PCMPIServerBegin();
1085: return 0;
1086: }
1088: /*@C
1089: PetscInitialize - Initializes the PETSc database and MPI.
1090: `PetscInitialize()` calls MPI_Init() if that has yet to be called,
1091: so this routine should always be called near the beginning of
1092: your program -- usually the very first line!
1094: Collective on `MPI_COMM_WORLD` or `PETSC_COMM_WORLD` if it has been set
1096: Input Parameters:
1097: + argc - count of number of command line arguments
1098: . args - the command line arguments
1099: . file - [optional] PETSc database file, append ":yaml" to filename to specify YAML options format.
1100: Use NULL or empty string to not check for code specific file.
1101: Also checks ~/.petscrc, .petscrc and petscrc.
1102: Use -skip_petscrc in the code specific file (or command line) to skip ~/.petscrc, .petscrc and petscrc files.
1103: - help - [optional] Help message to print, use NULL for no message
1105: If you wish PETSc code to run ONLY on a subcommunicator of `MPI_COMM_WORLD`, create that
1106: communicator first and assign it to `PETSC_COMM_WORLD` BEFORE calling `PetscInitialize()`. Thus if you are running a
1107: four process job and two processes will run PETSc and have `PetscInitialize()` and PetscFinalize() and two process will not,
1108: then do this. If ALL processes in the job are using `PetscInitialize()` and `PetscFinalize()` then you don't need to do this, even
1109: if different subcommunicators of the job are doing different things with PETSc.
1111: Options Database Keys:
1112: + -help [intro] - prints help method for each option; if intro is given the program stops after printing the introductory help message
1113: . -start_in_debugger [noxterm,dbx,xdb,gdb,...] - Starts program in debugger
1114: . -on_error_attach_debugger [noxterm,dbx,xdb,gdb,...] - Starts debugger when error detected
1115: . -on_error_emacs <machinename> - causes emacsclient to jump to error file
1116: . -on_error_abort - calls `abort()` when error detected (no traceback)
1117: . -on_error_mpiabort - calls `MPI_abort()` when error detected
1118: . -error_output_stdout - prints PETSc error messages to stdout instead of the default stderr
1119: . -error_output_none - does not print the error messages (but handles errors in the same way as if this was not called)
1120: . -debugger_ranks [rank1,rank2,...] - Indicates ranks to start in debugger
1121: . -debugger_pause [sleeptime] (in seconds) - Pauses debugger
1122: . -stop_for_debugger - Print message on how to attach debugger manually to
1123: process and wait (-debugger_pause) seconds for attachment
1124: . -malloc - Indicates use of PETSc error-checking malloc (on by default for debug version of libraries) (deprecated, use -malloc_debug)
1125: . -malloc no - Indicates not to use error-checking malloc (deprecated, use -malloc_debug no)
1126: . -malloc_debug - check for memory corruption at EVERY malloc or free, see `PetscMallocSetDebug()`
1127: . -malloc_dump - prints a list of all unfreed memory at the end of the run
1128: . -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
1129: . -malloc_view - show a list of all allocated memory during `PetscFinalize()`
1130: . -malloc_view_threshold <t> - only list memory allocations of size greater than t with -malloc_view
1131: . -malloc_requested_size - malloc logging will record the requested size rather than size after alignment
1132: . -fp_trap - Stops on floating point exceptions
1133: . -no_signal_handler - Indicates not to trap error signals
1134: . -shared_tmp - indicates /tmp directory is shared by all processors
1135: . -not_shared_tmp - each processor has own /tmp
1136: . -tmp - alternative name of /tmp directory
1137: . -get_total_flops - returns total flops done by all processors
1138: - -memory_view - Print memory usage at end of run
1140: Options Database Keys for Option Database:
1141: + -skip_petscrc - skip the default option files ~/.petscrc, .petscrc, petscrc
1142: . -options_monitor - monitor all set options to standard output for the whole program run
1143: - -options_monitor_cancel - cancel options monitoring hard-wired using `PetscOptionsMonitorSet()`
1145: Options -options_monitor_{all,cancel} are
1146: position-independent and apply to all options set since the PETSc start.
1147: They can be used also in option files.
1149: See `PetscOptionsMonitorSet()` to do monitoring programmatically.
1151: Options Database Keys for Profiling:
1152: See Users-Manual: ch_profiling for details.
1153: + -info [filename][:[~]<list,of,classnames>[:[~]self]] - Prints verbose information. See `PetscInfo()`.
1154: . -log_sync - Enable barrier synchronization for all events. This option is useful to debug imbalance within each event,
1155: however it slows things down and gives a distorted view of the overall runtime.
1156: . -log_trace [filename] - Print traces of all PETSc calls to the screen (useful to determine where a program
1157: hangs without running in the debugger). See `PetscLogTraceBegin()`.
1158: . -log_view [:filename:format] - Prints summary of flop and timing information to screen or file, see `PetscLogView()`.
1159: . -log_view_memory - Includes in the summary from -log_view the memory used in each event, see `PetscLogView()`.
1160: . -log_view_gpu_time - Includes in the summary from -log_view the time used in each GPU kernel, see `PetscLogView().
1161: . -log_summary [filename] - (Deprecated, use -log_view) Prints summary of flop and timing information to screen. If the filename is specified the
1162: summary is written to the file. See PetscLogView().
1163: . -log_exclude: <vec,mat,pc,ksp,snes> - excludes subset of object classes from logging
1164: . -log_all [filename] - Logs extensive profiling information See `PetscLogDump()`.
1165: . -log [filename] - Logs basic profiline information See `PetscLogDump()`.
1166: . -log_mpe [filename] - Creates a logfile viewable by the utility Jumpshot (in MPICH distribution)
1167: . -viewfromoptions on,off - Enable or disable `XXXSetFromOptions()` calls, for applications with many small solves turn this off
1168: - -check_pointer_intensity 0,1,2 - if pointers are checked for validity (debug version only), using 0 will result in faster code
1170: Only one of -log_trace, -log_view, -log_all, -log, or -log_mpe may be used at a time
1172: Options Database Keys for SAWs:
1173: + -saws_port <portnumber> - port number to publish SAWs data, default is 8080
1174: . -saws_port_auto_select - have SAWs select a new unique port number where it publishes the data, the URL is printed to the screen
1175: this is useful when you are running many jobs that utilize SAWs at the same time
1176: . -saws_log <filename> - save a log of all SAWs communication
1177: . -saws_https <certificate file> - have SAWs use HTTPS instead of HTTP
1178: - -saws_root <directory> - allow SAWs to have access to the given directory to search for requested resources and files
1180: Environmental Variables:
1181: + `PETSC_TMP` - alternative tmp directory
1182: . `PETSC_SHARED_TMP` - tmp is shared by all processes
1183: . `PETSC_NOT_SHARED_TMP` - each process has its own private tmp
1184: . `PETSC_OPTIONS` - a string containing additional options for petsc in the form of command line "-key value" pairs
1185: . `PETSC_OPTIONS_YAML` - (requires configuring PETSc to use libyaml) a string containing additional options for petsc in the form of a YAML document
1186: . `PETSC_VIEWER_SOCKET_PORT` - socket number to use for socket viewer
1187: - `PETSC_VIEWER_SOCKET_MACHINE` - machine to use for socket viewer to connect to
1189: Level: beginner
1191: Note:
1192: If for some reason you must call `MPI_Init()` separately, call
1193: it before `PetscInitialize()`.
1195: Fortran Notes:
1196: In Fortran this routine can be called with
1197: .vb
1198: call PetscInitialize(ierr)
1199: call PetscInitialize(file,ierr) or
1200: call PetscInitialize(file,help,ierr)
1201: .ve
1203: If your main program is C but you call Fortran code that also uses PETSc you need to call `PetscInitializeFortran()` soon after
1204: calling `PetscInitialize()`.
1206: .seealso: `PetscFinalize()`, `PetscInitializeFortran()`, `PetscGetArgs()`, `PetscInitializeNoArguments()`, `PetscLogGpuTime()`
1207: @*/
1208: PetscErrorCode PetscInitialize(int *argc, char ***args, const char file[], const char help[])
1209: {
1210: PetscMPIInt flag;
1211: const char *prog = "Unknown Name", *mpienv;
1213: if (PetscInitializeCalled) return 0;
1214: MPI_Initialized(&flag);
1215: if (!flag) {
1217: PetscPreMPIInit_Private();
1218: #if defined(PETSC_HAVE_MPI_INIT_THREAD)
1219: {
1220: PetscMPIInt PETSC_UNUSED provided;
1221: MPI_Init_thread(argc, args, PETSC_MPI_THREAD_REQUIRED, &provided);
1222: }
1223: #else
1224: MPI_Init(argc, args);
1225: #endif
1226: if (PetscDefined(HAVE_MPIUNI)) {
1227: mpienv = getenv("PMI_SIZE");
1228: if (!mpienv) mpienv = getenv("OMPI_COMM_WORLD_SIZE");
1229: if (mpienv) {
1230: PetscInt isize;
1231: PetscOptionsStringToInt(mpienv, &isize);
1232: if (isize != 1) printf("You are using an MPI-uni (sequential) install of PETSc but trying to launch parallel jobs; you need full MPI version of PETSc\n");
1234: }
1235: }
1236: PetscBeganMPI = PETSC_TRUE;
1237: }
1239: if (argc && *argc) prog = **args;
1240: if (argc && args) {
1241: PetscGlobalArgc = *argc;
1242: PetscGlobalArgs = *args;
1243: }
1244: PetscInitialize_Common(prog, file, help, PETSC_FALSE, PETSC_FALSE, 0);
1245: return 0;
1246: }
1248: #if PetscDefined(USE_LOG)
1249: PETSC_INTERN PetscObject *PetscObjects;
1250: PETSC_INTERN PetscInt PetscObjectsCounts;
1251: PETSC_INTERN PetscInt PetscObjectsMaxCounts;
1252: PETSC_INTERN PetscBool PetscObjectsLog;
1253: #endif
1255: /*
1256: Frees all the MPI types and operations that PETSc may have created
1257: */
1258: PetscErrorCode PetscFreeMPIResources(void)
1259: {
1260: #if defined(PETSC_HAVE_REAL___FLOAT128)
1261: MPI_Type_free(&MPIU___FLOAT128);
1262: MPI_Type_free(&MPIU___COMPLEX128);
1263: #endif
1264: #if defined(PETSC_HAVE_REAL___FP16)
1265: MPI_Type_free(&MPIU___FP16);
1266: #endif
1268: #if defined(PETSC_USE_REAL___FLOAT128) || defined(PETSC_USE_REAL___FP16)
1269: MPI_Op_free(&MPIU_SUM);
1270: MPI_Op_free(&MPIU_MAX);
1271: MPI_Op_free(&MPIU_MIN);
1272: #elif defined(PETSC_HAVE_REAL___FLOAT128) || defined(PETSC_HAVE_REAL___FP16)
1273: MPI_Op_free(&MPIU_SUM___FP16___FLOAT128);
1274: #endif
1276: MPI_Type_free(&MPIU_2SCALAR);
1277: MPI_Type_free(&MPIU_REAL_INT);
1278: MPI_Type_free(&MPIU_SCALAR_INT);
1279: #if defined(PETSC_USE_64BIT_INDICES)
1280: MPI_Type_free(&MPIU_2INT);
1281: #endif
1282: MPI_Type_free(&MPI_4INT);
1283: MPI_Type_free(&MPIU_4INT);
1284: MPI_Op_free(&MPIU_MAXSUM_OP);
1285: MPI_Op_free(&Petsc_Garbage_SetIntersectOp);
1286: return 0;
1287: }
1289: #if PetscDefined(USE_LOG)
1290: PETSC_INTERN PetscErrorCode PetscLogFinalize(void);
1291: #endif
1293: /*@C
1294: PetscFinalize - Checks for options to be called at the conclusion
1295: of the program. `MPI_Finalize()` is called only if the user had not
1296: called `MPI_Init()` before calling `PetscInitialize()`.
1298: Collective on `PETSC_COMM_WORLD`
1300: Options Database Keys:
1301: + -options_view - Calls `PetscOptionsView()`
1302: . -options_left - Prints unused options that remain in the database
1303: . -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
1304: . -mpidump - Calls PetscMPIDump()
1305: . -malloc_dump <optional filename> - Calls `PetscMallocDump()`, displays all memory allocated that has not been freed
1306: . -malloc_info - Prints total memory usage
1307: - -malloc_view <optional filename> - Prints list of all memory allocated and where
1309: Level: beginner
1311: Note:
1312: See `PetscInitialize()` for other runtime options.
1314: .seealso: `PetscInitialize()`, `PetscOptionsView()`, `PetscMallocDump()`, `PetscMPIDump()`, `PetscEnd()`
1315: @*/
1316: PetscErrorCode PetscFinalize(void)
1317: {
1318: PetscMPIInt rank;
1319: PetscInt nopt;
1320: PetscBool flg1 = PETSC_FALSE, flg2 = PETSC_FALSE, flg3 = PETSC_FALSE;
1321: PetscBool flg;
1322: #if defined(PETSC_USE_LOG)
1323: char mname[PETSC_MAX_PATH_LEN];
1324: #endif
1327: PetscInfo(NULL, "PetscFinalize() called\n");
1329: PetscOptionsHasName(NULL, NULL, "-mpi_linear_solver_server", &flg);
1330: if (PetscDefined(USE_SINGLE_LIBRARY) && flg) PCMPIServerEnd();
1332: /* Clean up Garbage automatically on COMM_SELF and COMM_WORLD at finalize */
1333: {
1334: union
1335: {
1336: MPI_Comm comm;
1337: void *ptr;
1338: } ucomm;
1339: PetscMPIInt flg;
1340: void *tmp;
1342: MPI_Comm_get_attr(PETSC_COMM_SELF, Petsc_InnerComm_keyval, &ucomm, &flg);
1343: if (flg) MPI_Comm_get_attr(ucomm.comm, Petsc_Garbage_HMap_keyval, &tmp, &flg);
1344: if (flg) PetscGarbageCleanup(PETSC_COMM_SELF);
1345: MPI_Comm_get_attr(PETSC_COMM_WORLD, Petsc_InnerComm_keyval, &ucomm, &flg);
1346: if (flg) MPI_Comm_get_attr(ucomm.comm, Petsc_Garbage_HMap_keyval, &tmp, &flg);
1347: if (flg) PetscGarbageCleanup(PETSC_COMM_WORLD);
1348: }
1350: MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
1351: #if defined(PETSC_HAVE_ADIOS)
1352: adios_read_finalize_method(ADIOS_READ_METHOD_BP_AGGREGATE);
1353: adios_finalize(rank);
1354: #endif
1355: PetscOptionsHasName(NULL, NULL, "-citations", &flg);
1356: if (flg) {
1357: char *cits, filename[PETSC_MAX_PATH_LEN];
1358: FILE *fd = PETSC_STDOUT;
1360: PetscOptionsGetString(NULL, NULL, "-citations", filename, sizeof(filename), NULL);
1361: if (filename[0]) PetscFOpen(PETSC_COMM_WORLD, filename, "w", &fd);
1362: PetscSegBufferGet(PetscCitationsList, 1, &cits);
1363: cits[0] = 0;
1364: PetscSegBufferExtractAlloc(PetscCitationsList, &cits);
1365: PetscFPrintf(PETSC_COMM_WORLD, fd, "If you publish results based on this computation please cite the following:\n");
1366: PetscFPrintf(PETSC_COMM_WORLD, fd, "===========================================================================\n");
1367: PetscFPrintf(PETSC_COMM_WORLD, fd, "%s", cits);
1368: PetscFPrintf(PETSC_COMM_WORLD, fd, "===========================================================================\n");
1369: PetscFClose(PETSC_COMM_WORLD, fd);
1370: PetscFree(cits);
1371: }
1372: PetscSegBufferDestroy(&PetscCitationsList);
1374: #if defined(PETSC_HAVE_SSL) && defined(PETSC_USE_SOCKET_VIEWER)
1375: /* TextBelt is run for testing purposes only, please do not use this feature often */
1376: {
1377: PetscInt nmax = 2;
1378: char **buffs;
1379: PetscMalloc1(2, &buffs);
1380: PetscOptionsGetStringArray(NULL, NULL, "-textbelt", buffs, &nmax, &flg1);
1381: if (flg1) {
1383: if (nmax == 1) {
1384: PetscMalloc1(128, &buffs[1]);
1385: PetscGetProgramName(buffs[1], 32);
1386: PetscStrcat(buffs[1], " has completed");
1387: }
1388: PetscTextBelt(PETSC_COMM_WORLD, buffs[0], buffs[1], NULL);
1389: PetscFree(buffs[0]);
1390: PetscFree(buffs[1]);
1391: }
1392: PetscFree(buffs);
1393: }
1394: {
1395: PetscInt nmax = 2;
1396: char **buffs;
1397: PetscMalloc1(2, &buffs);
1398: PetscOptionsGetStringArray(NULL, NULL, "-tellmycell", buffs, &nmax, &flg1);
1399: if (flg1) {
1401: if (nmax == 1) {
1402: PetscMalloc1(128, &buffs[1]);
1403: PetscGetProgramName(buffs[1], 32);
1404: PetscStrcat(buffs[1], " has completed");
1405: }
1406: PetscTellMyCell(PETSC_COMM_WORLD, buffs[0], buffs[1], NULL);
1407: PetscFree(buffs[0]);
1408: PetscFree(buffs[1]);
1409: }
1410: PetscFree(buffs);
1411: }
1412: #endif
1414: #if defined(PETSC_SERIALIZE_FUNCTIONS)
1415: PetscFPTDestroy();
1416: #endif
1418: #if defined(PETSC_HAVE_SAWS)
1419: flg = PETSC_FALSE;
1420: PetscOptionsGetBool(NULL, NULL, "-saw_options", &flg, NULL);
1421: if (flg) PetscOptionsSAWsDestroy();
1422: #endif
1424: #if defined(PETSC_HAVE_X)
1425: flg1 = PETSC_FALSE;
1426: PetscOptionsGetBool(NULL, NULL, "-x_virtual", &flg1, NULL);
1427: if (flg1) {
1428: /* this is a crude hack, but better than nothing */
1429: PetscPOpen(PETSC_COMM_WORLD, NULL, "pkill -9 Xvfb", "r", NULL);
1430: }
1431: #endif
1433: #if !defined(PETSC_HAVE_THREADSAFETY)
1434: PetscOptionsGetBool(NULL, NULL, "-malloc_info", &flg2, NULL);
1435: if (!flg2) {
1436: flg2 = PETSC_FALSE;
1437: PetscOptionsGetBool(NULL, NULL, "-memory_view", &flg2, NULL);
1438: }
1439: if (flg2) PetscMemoryView(PETSC_VIEWER_STDOUT_WORLD, "Summary of Memory Usage in PETSc\n");
1440: #endif
1442: #if defined(PETSC_USE_LOG)
1443: flg1 = PETSC_FALSE;
1444: PetscOptionsGetBool(NULL, NULL, "-get_total_flops", &flg1, NULL);
1445: if (flg1) {
1446: PetscLogDouble flops = 0;
1447: MPI_Reduce(&petsc_TotalFlops, &flops, 1, MPI_DOUBLE, MPI_SUM, 0, PETSC_COMM_WORLD);
1448: PetscPrintf(PETSC_COMM_WORLD, "Total flops over all processors %g\n", flops);
1449: }
1450: #endif
1452: #if defined(PETSC_USE_LOG)
1453: #if defined(PETSC_HAVE_MPE)
1454: mname[0] = 0;
1455: PetscOptionsGetString(NULL, NULL, "-log_mpe", mname, sizeof(mname), &flg1);
1456: if (flg1) {
1457: if (mname[0]) PetscLogMPEDump(mname);
1458: else PetscLogMPEDump(0);
1459: }
1460: #endif
1461: #endif
1463: /*
1464: Free all objects registered with PetscObjectRegisterDestroy() such as PETSC_VIEWER_XXX_().
1465: */
1466: PetscObjectRegisterDestroyAll();
1468: #if defined(PETSC_USE_LOG)
1469: PetscOptionsPushGetViewerOff(PETSC_FALSE);
1470: PetscLogViewFromOptions();
1471: PetscOptionsPopGetViewerOff();
1473: mname[0] = 0;
1474: PetscOptionsGetString(NULL, NULL, "-log_summary", mname, sizeof(mname), &flg1);
1475: if (flg1) {
1476: PetscViewer viewer;
1477: (*PetscHelpPrintf)(PETSC_COMM_WORLD, "\n\n WARNING: -log_summary is being deprecated; switch to -log_view\n\n\n");
1478: if (mname[0]) {
1479: PetscViewerASCIIOpen(PETSC_COMM_WORLD, mname, &viewer);
1480: PetscLogView(viewer);
1481: PetscViewerDestroy(&viewer);
1482: } else {
1483: viewer = PETSC_VIEWER_STDOUT_WORLD;
1484: PetscViewerPushFormat(viewer, PETSC_VIEWER_DEFAULT);
1485: PetscLogView(viewer);
1486: PetscViewerPopFormat(viewer);
1487: }
1488: }
1490: /*
1491: Free any objects created by the last block of code.
1492: */
1493: PetscObjectRegisterDestroyAll();
1495: mname[0] = 0;
1496: PetscOptionsGetString(NULL, NULL, "-log_all", mname, sizeof(mname), &flg1);
1497: PetscOptionsGetString(NULL, NULL, "-log", mname, sizeof(mname), &flg2);
1498: if (flg1 || flg2) PetscLogDump(mname);
1499: #endif
1501: flg1 = PETSC_FALSE;
1502: PetscOptionsGetBool(NULL, NULL, "-no_signal_handler", &flg1, NULL);
1503: if (!flg1) PetscPopSignalHandler();
1504: flg1 = PETSC_FALSE;
1505: PetscOptionsGetBool(NULL, NULL, "-mpidump", &flg1, NULL);
1506: if (flg1) PetscMPIDump(stdout);
1507: flg1 = PETSC_FALSE;
1508: flg2 = PETSC_FALSE;
1509: /* preemptive call to avoid listing this option in options table as unused */
1510: PetscOptionsHasName(NULL, NULL, "-malloc_dump", &flg1);
1511: PetscOptionsHasName(NULL, NULL, "-objects_dump", &flg1);
1512: PetscOptionsGetBool(NULL, NULL, "-options_view", &flg2, NULL);
1514: if (flg2) {
1515: PetscViewer viewer;
1516: PetscViewerCreate(PETSC_COMM_WORLD, &viewer);
1517: PetscViewerSetType(viewer, PETSCVIEWERASCII);
1518: PetscOptionsView(NULL, viewer);
1519: PetscViewerDestroy(&viewer);
1520: }
1522: /* to prevent PETSc -options_left from warning */
1523: PetscOptionsHasName(NULL, NULL, "-nox", &flg1);
1524: PetscOptionsHasName(NULL, NULL, "-nox_warning", &flg1);
1526: flg3 = PETSC_FALSE; /* default value is required */
1527: PetscOptionsGetBool(NULL, NULL, "-options_left", &flg3, &flg1);
1528: if (PetscUnlikelyDebug(!flg1)) flg3 = PETSC_TRUE;
1529: if (flg3) {
1530: if (!flg2 && flg1) { /* have not yet printed the options */
1531: PetscViewer viewer;
1532: PetscViewerCreate(PETSC_COMM_WORLD, &viewer);
1533: PetscViewerSetType(viewer, PETSCVIEWERASCII);
1534: PetscOptionsView(NULL, viewer);
1535: PetscViewerDestroy(&viewer);
1536: }
1537: PetscOptionsAllUsed(NULL, &nopt);
1538: if (nopt) {
1539: PetscPrintf(PETSC_COMM_WORLD, "WARNING! There are options you set that were not used!\n");
1540: PetscPrintf(PETSC_COMM_WORLD, "WARNING! could be spelling mistake, etc!\n");
1541: if (nopt == 1) {
1542: PetscPrintf(PETSC_COMM_WORLD, "There is one unused database option. It is:\n");
1543: } else {
1544: PetscPrintf(PETSC_COMM_WORLD, "There are %" PetscInt_FMT " unused database options. They are:\n", nopt);
1545: }
1546: } else if (flg3 && flg1) {
1547: PetscPrintf(PETSC_COMM_WORLD, "There are no unused options.\n");
1548: }
1549: PetscOptionsLeft(NULL);
1550: }
1552: #if defined(PETSC_HAVE_SAWS)
1553: if (!PetscGlobalRank) {
1554: PetscStackSAWsViewOff();
1555: SAWs_Finalize, ();
1556: }
1557: #endif
1559: #if defined(PETSC_USE_LOG)
1560: /*
1561: List all objects the user may have forgot to free
1562: */
1563: if (PetscObjectsLog) {
1564: PetscOptionsHasName(NULL, NULL, "-objects_dump", &flg1);
1565: if (flg1) {
1566: MPI_Comm local_comm;
1567: char string[64];
1569: PetscOptionsGetString(NULL, NULL, "-objects_dump", string, sizeof(string), NULL);
1570: MPI_Comm_dup(PETSC_COMM_WORLD, &local_comm);
1571: PetscSequentialPhaseBegin_Private(local_comm, 1);
1572: PetscObjectsDump(stdout, (string[0] == 'a') ? PETSC_TRUE : PETSC_FALSE);
1573: PetscSequentialPhaseEnd_Private(local_comm, 1);
1574: MPI_Comm_free(&local_comm);
1575: }
1576: }
1577: #endif
1579: #if defined(PETSC_USE_LOG)
1580: PetscObjectsCounts = 0;
1581: PetscObjectsMaxCounts = 0;
1582: PetscFree(PetscObjects);
1583: #endif
1585: /*
1586: Destroy any packages that registered a finalize
1587: */
1588: PetscRegisterFinalizeAll();
1590: #if defined(PETSC_USE_LOG)
1591: PetscLogFinalize();
1592: #endif
1594: /*
1595: Print PetscFunctionLists that have not been properly freed
1596: */
1597: if (PetscPrintFunctionList) PetscFunctionListPrintAll();
1599: if (petsc_history) {
1600: PetscCloseHistoryFile(&petsc_history);
1601: petsc_history = NULL;
1602: }
1603: PetscOptionsHelpPrintedDestroy(&PetscOptionsHelpPrintedSingleton);
1604: PetscInfoDestroy();
1606: #if !defined(PETSC_HAVE_THREADSAFETY)
1607: if (!(PETSC_RUNNING_ON_VALGRIND)) {
1608: char fname[PETSC_MAX_PATH_LEN];
1609: char sname[PETSC_MAX_PATH_LEN];
1610: FILE *fd;
1611: int err;
1613: flg2 = PETSC_FALSE;
1614: flg3 = PETSC_FALSE;
1615: if (PetscDefined(USE_DEBUG)) PetscOptionsGetBool(NULL, NULL, "-malloc_test", &flg2, NULL);
1616: PetscOptionsGetBool(NULL, NULL, "-malloc_debug", &flg3, NULL);
1617: fname[0] = 0;
1618: PetscOptionsGetString(NULL, NULL, "-malloc_dump", fname, sizeof(fname), &flg1);
1619: if (flg1 && fname[0]) {
1620: PetscSNPrintf(sname, sizeof(sname), "%s_%d", fname, rank);
1621: fd = fopen(sname, "w");
1623: PetscMallocDump(fd);
1624: err = fclose(fd);
1626: } else if (flg1 || flg2 || flg3) {
1627: MPI_Comm local_comm;
1629: MPI_Comm_dup(PETSC_COMM_WORLD, &local_comm);
1630: PetscSequentialPhaseBegin_Private(local_comm, 1);
1631: PetscMallocDump(stdout);
1632: PetscSequentialPhaseEnd_Private(local_comm, 1);
1633: MPI_Comm_free(&local_comm);
1634: }
1635: fname[0] = 0;
1636: PetscOptionsGetString(NULL, NULL, "-malloc_view", fname, sizeof(fname), &flg1);
1637: if (flg1 && fname[0]) {
1638: PetscSNPrintf(sname, sizeof(sname), "%s_%d", fname, rank);
1639: fd = fopen(sname, "w");
1641: PetscMallocView(fd);
1642: err = fclose(fd);
1644: } else if (flg1) {
1645: MPI_Comm local_comm;
1647: MPI_Comm_dup(PETSC_COMM_WORLD, &local_comm);
1648: PetscSequentialPhaseBegin_Private(local_comm, 1);
1649: PetscMallocView(stdout);
1650: PetscSequentialPhaseEnd_Private(local_comm, 1);
1651: MPI_Comm_free(&local_comm);
1652: }
1653: }
1654: #endif
1656: /*
1657: Close any open dynamic libraries
1658: */
1659: PetscFinalize_DynamicLibraries();
1661: /* Can be destroyed only after all the options are used */
1662: PetscOptionsDestroyDefault();
1664: PetscGlobalArgc = 0;
1665: PetscGlobalArgs = NULL;
1667: #if defined(PETSC_HAVE_KOKKOS)
1668: if (PetscBeganKokkos) {
1669: PetscKokkosFinalize_Private();
1670: PetscBeganKokkos = PETSC_FALSE;
1671: PetscKokkosInitialized = PETSC_FALSE;
1672: }
1673: #endif
1675: #if defined(PETSC_HAVE_NVSHMEM)
1676: if (PetscBeganNvshmem) {
1677: PetscNvshmemFinalize();
1678: PetscBeganNvshmem = PETSC_FALSE;
1679: }
1680: #endif
1682: PetscFreeMPIResources();
1684: /*
1685: Destroy any known inner MPI_Comm's and attributes pointing to them
1686: Note this will not destroy any new communicators the user has created.
1688: If all PETSc objects were not destroyed those left over objects will have hanging references to
1689: the MPI_Comms that were freed; but that is ok because those PETSc objects will never be used again
1690: */
1691: {
1692: PetscCommCounter *counter;
1693: PetscMPIInt flg;
1694: MPI_Comm icomm;
1695: union
1696: {
1697: MPI_Comm comm;
1698: void *ptr;
1699: } ucomm;
1700: MPI_Comm_get_attr(PETSC_COMM_SELF, Petsc_InnerComm_keyval, &ucomm, &flg);
1701: if (flg) {
1702: icomm = ucomm.comm;
1703: MPI_Comm_get_attr(icomm, Petsc_Counter_keyval, &counter, &flg);
1706: MPI_Comm_delete_attr(PETSC_COMM_SELF, Petsc_InnerComm_keyval);
1707: MPI_Comm_delete_attr(icomm, Petsc_Counter_keyval);
1708: MPI_Comm_free(&icomm);
1709: }
1710: MPI_Comm_get_attr(PETSC_COMM_WORLD, Petsc_InnerComm_keyval, &ucomm, &flg);
1711: if (flg) {
1712: icomm = ucomm.comm;
1713: MPI_Comm_get_attr(icomm, Petsc_Counter_keyval, &counter, &flg);
1716: MPI_Comm_delete_attr(PETSC_COMM_WORLD, Petsc_InnerComm_keyval);
1717: MPI_Comm_delete_attr(icomm, Petsc_Counter_keyval);
1718: MPI_Comm_free(&icomm);
1719: }
1720: }
1722: MPI_Comm_free_keyval(&Petsc_Counter_keyval);
1723: MPI_Comm_free_keyval(&Petsc_InnerComm_keyval);
1724: MPI_Comm_free_keyval(&Petsc_OuterComm_keyval);
1725: MPI_Comm_free_keyval(&Petsc_ShmComm_keyval);
1726: MPI_Comm_free_keyval(&Petsc_CreationIdx_keyval);
1727: MPI_Comm_free_keyval(&Petsc_Garbage_HMap_keyval);
1729: PetscSpinlockDestroy(&PetscViewerASCIISpinLockOpen);
1730: PetscSpinlockDestroy(&PetscViewerASCIISpinLockStdout);
1731: PetscSpinlockDestroy(&PetscViewerASCIISpinLockStderr);
1732: PetscSpinlockDestroy(&PetscCommSpinLock);
1734: if (PetscBeganMPI) {
1735: PetscMPIInt flag;
1736: MPI_Finalized(&flag);
1738: /* wait until the very last moment to disable error handling */
1739: PetscErrorHandlingInitialized = PETSC_FALSE;
1740: MPI_Finalize();
1741: } else PetscErrorHandlingInitialized = PETSC_FALSE;
1743: /*
1745: Note: In certain cases PETSC_COMM_WORLD is never MPI_Comm_free()ed because
1746: the communicator has some outstanding requests on it. Specifically if the
1747: flag PETSC_HAVE_BROKEN_REQUEST_FREE is set (for IBM MPI implementation). See
1748: src/vec/utils/vpscat.c. Due to this the memory allocated in PetscCommDuplicate()
1749: is never freed as it should be. Thus one may obtain messages of the form
1750: [ 1] 8 bytes PetscCommDuplicate() line 645 in src/sys/mpiu.c indicating the
1751: memory was not freed.
1753: */
1754: PetscMallocClear();
1755: PetscStackReset();
1757: PetscInitializeCalled = PETSC_FALSE;
1758: PetscFinalizeCalled = PETSC_TRUE;
1759: #if defined(PETSC_USE_GCOV)
1760: /*
1761: flush gcov, otherwise during CI the flushing continues into the next pipeline resulting in git not being able to delete directories since the
1762: gcov files are still being added to the directories as git tries to remove the directories.
1763: */
1764: __gcov_flush();
1765: #endif
1767: PetscStackClearTop;
1768: return 0;
1769: }
1771: #if defined(PETSC_MISSING_LAPACK_lsame_)
1772: PETSC_EXTERN int lsame_(char *a, char *b)
1773: {
1774: if (*a == *b) return 1;
1775: if (*a + 32 == *b) return 1;
1776: if (*a - 32 == *b) return 1;
1777: return 0;
1778: }
1779: #endif
1781: #if defined(PETSC_MISSING_LAPACK_lsame)
1782: PETSC_EXTERN int lsame(char *a, char *b)
1783: {
1784: if (*a == *b) return 1;
1785: if (*a + 32 == *b) return 1;
1786: if (*a - 32 == *b) return 1;
1787: return 0;
1788: }
1789: #endif