xref: /petsc/src/sys/objects/pinit.c (revision f0865b086e8f4c34d750388762e5421e85fbf8f1)
1 #define PETSC_DLL
2 /*
3    This file defines the initialization of PETSc, including PetscInitialize()
4 */
5 
6 #include "petscsys.h"        /*I  "petscsys.h"   I*/
7 
8 #if defined(PETSC_HAVE_CUDA)
9 #include <cublas.h>
10 #endif
11 
12 #if defined(PETSC_USE_LOG)
13 extern PetscErrorCode PetscLogBegin_Private(void);
14 #endif
15 extern PetscBool  PetscOpenMPWorker;
16 
17 /* -----------------------------------------------------------------------------------------*/
18 
19 extern FILE *petsc_history;
20 
21 extern PetscErrorCode PetscInitialize_DynamicLibraries(void);
22 extern PetscErrorCode PetscFinalize_DynamicLibraries(void);
23 extern PetscErrorCode PetscFListDestroyAll(void);
24 extern PetscErrorCode PetscSequentialPhaseBegin_Private(MPI_Comm,int);
25 extern PetscErrorCode PetscSequentialPhaseEnd_Private(MPI_Comm,int);
26 extern PetscErrorCode PetscCloseHistoryFile(FILE **);
27 
28 /* this is used by the _, __, and ___ macros (see include/petscerror.h) */
29 PetscErrorCode __gierr = 0;
30 
31 /* user may set this BEFORE calling PetscInitialize() */
32 MPI_Comm PETSC_COMM_WORLD = MPI_COMM_NULL;
33 
34 PetscMPIInt Petsc_Counter_keyval   = MPI_KEYVAL_INVALID;
35 PetscMPIInt Petsc_InnerComm_keyval = MPI_KEYVAL_INVALID;
36 PetscMPIInt Petsc_OuterComm_keyval = MPI_KEYVAL_INVALID;
37 
38 /*
39      Declare and set all the string names of the PETSc enums
40 */
41 const char *PetscBools[]     = {"FALSE","TRUE","PetscBool","PETSC_",0};
42 const char *PetscCopyModes[] = {"COPY_VALUES","OWN_POINTER","USE_POINTER","PetscCopyMode","PETSC_",0};
43 const char *PetscDataTypes[] = {"INT","DOUBLE","COMPLEX","LONG","SHORT","FLOAT",
44                                 "CHAR","LOGICAL","ENUM","BOOL","LONGDOUBLE","PetscDataType","PETSC_",0};
45 
46 PetscBool  PetscPreLoadingUsed = PETSC_FALSE;
47 PetscBool  PetscPreLoadingOn   = PETSC_FALSE;
48 
49 /*
50        Checks the options database for initializations related to the
51     PETSc components
52 */
53 #undef __FUNCT__
54 #define __FUNCT__ "PetscOptionsCheckInitial_Components"
55 PetscErrorCode  PetscOptionsCheckInitial_Components(void)
56 {
57   PetscBool  flg1;
58   PetscErrorCode ierr;
59 
60   PetscFunctionBegin;
61   ierr = PetscOptionsHasName(PETSC_NULL,"-help",&flg1);CHKERRQ(ierr);
62   if (flg1) {
63 #if defined (PETSC_USE_LOG)
64     MPI_Comm   comm = PETSC_COMM_WORLD;
65     ierr = (*PetscHelpPrintf)(comm,"------Additional PETSc component options--------\n");CHKERRQ(ierr);
66     ierr = (*PetscHelpPrintf)(comm," -log_summary_exclude: <vec,mat,pc.ksp,snes>\n");CHKERRQ(ierr);
67     ierr = (*PetscHelpPrintf)(comm," -info_exclude: <null,vec,mat,pc,ksp,snes,ts>\n");CHKERRQ(ierr);
68     ierr = (*PetscHelpPrintf)(comm,"-----------------------------------------------\n");CHKERRQ(ierr);
69 #endif
70   }
71   PetscFunctionReturn(0);
72 }
73 
74 #undef __FUNCT__
75 #define __FUNCT__ "PetscInitializeNonPointers"
76 /*@C
77       PetscInitializeNonPointers - Calls PetscInitialize() from C/C++ without the pointers to argc and args
78 
79    Collective
80 
81    Level: advanced
82 
83 .seealso: PetscInitialize(), PetscInitializeFortran(), PetscInitializeNoArguments()
84 @*/
85 PetscErrorCode  PetscInitializeNonPointers(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);
93   PetscFunctionReturn(ierr);
94 }
95 
96 #undef __FUNCT__
97 #define __FUNCT__ "PetscGetPETSC_COMM_SELF"
98 /*
99       Used by Matlab interface to get communicator
100 */
101 PetscErrorCode  PetscGetPETSC_COMM_SELF(MPI_Comm *comm)
102 {
103   PetscFunctionBegin;
104   *comm = PETSC_COMM_SELF;
105   PetscFunctionReturn(0);
106 }
107 
108 #undef __FUNCT__
109 #define __FUNCT__ "PetscInitializeNoArguments"
110 /*@C
111       PetscInitializeNoArguments - Calls PetscInitialize() from C/C++ without
112         the command line arguments.
113 
114    Collective
115 
116    Level: advanced
117 
118 .seealso: PetscInitialize(), PetscInitializeFortran()
119 @*/
120 PetscErrorCode  PetscInitializeNoArguments(void)
121 {
122   PetscErrorCode ierr;
123   int            argc = 0;
124   char           **args = 0;
125 
126   PetscFunctionBegin;
127   ierr = PetscInitialize(&argc,&args,PETSC_NULL,PETSC_NULL);
128   PetscFunctionReturn(ierr);
129 }
130 
131 #undef __FUNCT__
132 #define __FUNCT__ "PetscInitialized"
133 /*@
134       PetscInitialized - Determine whether PETSc is initialized.
135 
136 7   Level: beginner
137 
138 .seealso: PetscInitialize(), PetscInitializeNoArguments(), PetscInitializeFortran()
139 @*/
140 PetscErrorCode  PetscInitialized(PetscBool  *isInitialized)
141 {
142   PetscFunctionBegin;
143   PetscValidPointer(isInitialized, 1);
144   *isInitialized = PetscInitializeCalled;
145   PetscFunctionReturn(0);
146 }
147 
148 #undef __FUNCT__
149 #define __FUNCT__ "PetscFinalized"
150 /*@
151       PetscFinalized - Determine whether PetscFinalize() has been called yet
152 
153    Level: developer
154 
155 .seealso: PetscInitialize(), PetscInitializeNoArguments(), PetscInitializeFortran()
156 @*/
157 PetscErrorCode  PetscFinalized(PetscBool  *isFinalized)
158 {
159   PetscFunctionBegin;
160   PetscValidPointer(isFinalized, 1);
161   *isFinalized = PetscFinalizeCalled;
162   PetscFunctionReturn(0);
163 }
164 
165 extern PetscErrorCode        PetscOptionsCheckInitial_Private(void);
166 extern PetscBool  PetscBeganMPI;
167 
168 /*
169        This function is the MPI reduction operation used to compute the sum of the
170    first half of the datatype and the max of the second half.
171 */
172 MPI_Op PetscMaxSum_Op = 0;
173 
174 EXTERN_C_BEGIN
175 #undef __FUNCT__
176 #define __FUNCT__ "PetscMaxSum_Local"
177 void  MPIAPI PetscMaxSum_Local(void *in,void *out,int *cnt,MPI_Datatype *datatype)
178 {
179   PetscInt *xin = (PetscInt*)in,*xout = (PetscInt*)out,i,count = *cnt;
180 
181   PetscFunctionBegin;
182   if (*datatype != MPIU_2INT) {
183     (*PetscErrorPrintf)("Can only handle MPIU_2INT data types");
184     MPI_Abort(MPI_COMM_WORLD,1);
185   }
186 
187   for (i=0; i<count; i++) {
188     xout[2*i]    = PetscMax(xout[2*i],xin[2*i]);
189     xout[2*i+1] += xin[2*i+1];
190   }
191   PetscFunctionReturnVoid();
192 }
193 EXTERN_C_END
194 
195 /*
196     Returns the max of the first entry owned by this processor and the
197 sum of the second entry.
198 
199     The reason nprocs[2*i] contains lengths nprocs[2*i+1] contains flag of 1 if length is nonzero
200 is so that the PetscMaxSum_Op() can set TWO values, if we passed in only nprocs[i] with lengths
201 there would be no place to store the both needed results.
202 */
203 #undef __FUNCT__
204 #define __FUNCT__ "PetscMaxSum"
205 PetscErrorCode  PetscMaxSum(MPI_Comm comm,const PetscInt nprocs[],PetscInt *max,PetscInt *sum)
206 {
207   PetscMPIInt    size,rank;
208   PetscInt       *work;
209   PetscErrorCode ierr;
210 
211   PetscFunctionBegin;
212   ierr   = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
213   ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
214   ierr   = PetscMalloc(2*size*sizeof(PetscInt),&work);CHKERRQ(ierr);
215   ierr   = MPI_Allreduce((void*)nprocs,work,size,MPIU_2INT,PetscMaxSum_Op,comm);CHKERRQ(ierr);
216   *max   = work[2*rank];
217   *sum   = work[2*rank+1];
218   ierr   = PetscFree(work);CHKERRQ(ierr);
219   PetscFunctionReturn(0);
220 }
221 
222 /* ----------------------------------------------------------------------------*/
223 MPI_Op  PetscADMax_Op = 0;
224 
225 EXTERN_C_BEGIN
226 #undef __FUNCT__
227 #define __FUNCT__ "PetscADMax_Local"
228 void  MPIAPI PetscADMax_Local(void *in,void *out,PetscMPIInt *cnt,MPI_Datatype *datatype)
229 {
230   PetscScalar *xin = (PetscScalar *)in,*xout = (PetscScalar*)out;
231   PetscInt    i,count = *cnt;
232 
233   PetscFunctionBegin;
234   if (*datatype != MPIU_2SCALAR) {
235     (*PetscErrorPrintf)("Can only handle MPIU_2SCALAR data (i.e. double or complex) types");
236     MPI_Abort(MPI_COMM_WORLD,1);
237   }
238 
239   for (i=0; i<count; i++) {
240     if (PetscRealPart(xout[2*i]) < PetscRealPart(xin[2*i])) {
241       xout[2*i]   = xin[2*i];
242       xout[2*i+1] = xin[2*i+1];
243     }
244   }
245   PetscFunctionReturnVoid();
246 }
247 EXTERN_C_END
248 
249 MPI_Op  PetscADMin_Op = 0;
250 
251 EXTERN_C_BEGIN
252 #undef __FUNCT__
253 #define __FUNCT__ "PetscADMin_Local"
254 void  MPIAPI PetscADMin_Local(void *in,void *out,PetscMPIInt *cnt,MPI_Datatype *datatype)
255 {
256   PetscScalar *xin = (PetscScalar *)in,*xout = (PetscScalar*)out;
257   PetscInt    i,count = *cnt;
258 
259   PetscFunctionBegin;
260   if (*datatype != MPIU_2SCALAR) {
261     (*PetscErrorPrintf)("Can only handle MPIU_2SCALAR data (i.e. double or complex) types");
262     MPI_Abort(MPI_COMM_WORLD,1);
263   }
264 
265   for (i=0; i<count; i++) {
266     if (PetscRealPart(xout[2*i]) > PetscRealPart(xin[2*i])) {
267       xout[2*i]   = xin[2*i];
268       xout[2*i+1] = xin[2*i+1];
269     }
270   }
271   PetscFunctionReturnVoid();
272 }
273 EXTERN_C_END
274 /* ---------------------------------------------------------------------------------------*/
275 
276 #if defined(PETSC_USE_COMPLEX)
277 
278 /*
279     This operation is only needed when using complex numbers with older MPI that does not support complex numbers
280 */
281 #if !defined(PETSC_HAVE_MPI_C_DOUBLE_COMPLEX)
282 MPI_Op MPIU_SUM = 0;
283 
284 EXTERN_C_BEGIN
285 #undef __FUNCT__
286 #define __FUNCT__ "PetscSum_Local"
287 void  PetscSum_Local(void *in,void *out,PetscMPIInt *cnt,MPI_Datatype *datatype)
288 {
289   PetscScalar *xin = (PetscScalar *)in,*xout = (PetscScalar*)out;
290   PetscInt    i,count = *cnt;
291 
292   PetscFunctionBegin;
293   if (*datatype != MPIU_SCALAR) {
294     (*PetscErrorPrintf)("Can only handle MPIU_SCALAR data (i.e. double or complex) types");
295     MPI_Abort(MPI_COMM_WORLD,1);
296   }
297 
298   for (i=0; i<count; i++) {
299     xout[i] += xin[i];
300   }
301   PetscFunctionReturnVoid();
302 }
303 EXTERN_C_END
304 #endif
305 #endif
306 
307 EXTERN_C_BEGIN
308 #undef __FUNCT__
309 #define __FUNCT__ "Petsc_DelCounter"
310 /*
311    Private routine to delete internal tag/name counter storage when a communicator is freed.
312 
313    This is called by MPI, not by users.
314 
315    Note: this is declared extern "C" because it is passed to MPI_Keyval_create()
316 
317 */
318 PetscMPIInt  MPIAPI Petsc_DelCounter(MPI_Comm comm,PetscMPIInt keyval,void *count_val,void *extra_state)
319 {
320   PetscErrorCode ierr;
321 
322   PetscFunctionBegin;
323   ierr = PetscInfo1(0,"Deleting counter data in an MPI_Comm %ld\n",(long)comm);if (ierr) PetscFunctionReturn((PetscMPIInt)ierr);
324   ierr = PetscFree(count_val);if (ierr) PetscFunctionReturn((PetscMPIInt)ierr);
325   PetscFunctionReturn(MPI_SUCCESS);
326 }
327 EXTERN_C_END
328 
329 EXTERN_C_BEGIN
330 #undef __FUNCT__
331 #define __FUNCT__ "Petsc_DelComm"
332 /*
333   This does not actually free anything, it simply marks when a reference count to an internal MPI_Comm reaches zero and the
334   the external MPI_Comm drops its reference to the internal MPI_Comm
335 
336   This is called by MPI, not by users.
337 
338   Note: this is declared extern "C" because it is passed to MPI_Keyval_create()
339 
340 */
341 PetscMPIInt  MPIAPI Petsc_DelComm(MPI_Comm comm,PetscMPIInt keyval,void *attr_val,void *extra_state)
342 {
343   PetscErrorCode ierr;
344 
345   PetscFunctionBegin;
346   ierr = PetscInfo1(0,"Deleting PETSc communicator imbedded in a user MPI_Comm %ld\n",(long)comm);if (ierr) PetscFunctionReturn((PetscMPIInt)ierr);
347   /* actually don't delete anything because we cannot increase the reference count of the communicator anyways */
348   PetscFunctionReturn(MPI_SUCCESS);
349 }
350 EXTERN_C_END
351 
352 #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
353 #if !defined(PETSC_WORDS_BIGENDIAN)
354 EXTERN_C_BEGIN
355 extern PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype,MPI_Aint*,void*);
356 extern PetscMPIInt PetscDataRep_read_conv_fn(void*, MPI_Datatype,PetscMPIInt,void*,MPI_Offset,void*);
357 extern PetscMPIInt PetscDataRep_write_conv_fn(void*, MPI_Datatype,PetscMPIInt,void*,MPI_Offset,void*);
358 EXTERN_C_END
359 #endif
360 #endif
361 
362 int  PetscGlobalArgc   = 0;
363 char **PetscGlobalArgs = 0;
364 
365 #undef __FUNCT__
366 #define __FUNCT__ "PetscGetArgs"
367 /*@C
368    PetscGetArgs - Allows you to access the raw command line arguments anywhere
369      after PetscInitialize() is called but before PetscFinalize().
370 
371    Not Collective
372 
373    Output Parameters:
374 +  argc - count of number of command line arguments
375 -  args - the command line arguments
376 
377    Level: intermediate
378 
379    Notes:
380       This is usually used to pass the command line arguments into other libraries
381    that are called internally deep in PETSc or the application.
382 
383       The first argument contains the program name as is normal for C arguments.
384 
385    Concepts: command line arguments
386 
387 .seealso: PetscFinalize(), PetscInitializeFortran(), PetscGetArguments()
388 
389 @*/
390 PetscErrorCode  PetscGetArgs(int *argc,char ***args)
391 {
392   PetscFunctionBegin;
393   if (!PetscInitializeCalled && PetscFinalizeCalled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"You must call after PetscInitialize() but before PetscFinalize()");
394   *argc = PetscGlobalArgc;
395   *args = PetscGlobalArgs;
396   PetscFunctionReturn(0);
397 }
398 
399 #undef __FUNCT__
400 #define __FUNCT__ "PetscGetArguments"
401 /*@C
402    PetscGetArguments - Allows you to access the  command line arguments anywhere
403      after PetscInitialize() is called but before PetscFinalize().
404 
405    Not Collective
406 
407    Output Parameters:
408 .  args - the command line arguments
409 
410    Level: intermediate
411 
412    Notes:
413       This does NOT start with the program name and IS null terminated (final arg is void)
414 
415    Concepts: command line arguments
416 
417 .seealso: PetscFinalize(), PetscInitializeFortran(), PetscGetArgs(), PetscFreeArguments()
418 
419 @*/
420 PetscErrorCode  PetscGetArguments(char ***args)
421 {
422   PetscInt       i,argc = PetscGlobalArgc;
423   PetscErrorCode ierr;
424 
425   PetscFunctionBegin;
426   if (!PetscInitializeCalled && PetscFinalizeCalled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"You must call after PetscInitialize() but before PetscFinalize()");
427   if (!argc) {*args = 0; PetscFunctionReturn(0);}
428   ierr = PetscMalloc(argc*sizeof(char*),args);CHKERRQ(ierr);
429   for (i=0; i<argc-1; i++) {
430     ierr = PetscStrallocpy(PetscGlobalArgs[i+1],&(*args)[i]);CHKERRQ(ierr);
431   }
432   (*args)[argc-1] = 0;
433   PetscFunctionReturn(0);
434 }
435 
436 #undef __FUNCT__
437 #define __FUNCT__ "PetscFreeArguments"
438 /*@C
439    PetscFreeArguments - Frees the memory obtained with PetscGetArguments()
440 
441    Not Collective
442 
443    Output Parameters:
444 .  args - the command line arguments
445 
446    Level: intermediate
447 
448    Concepts: command line arguments
449 
450 .seealso: PetscFinalize(), PetscInitializeFortran(), PetscGetArgs(), PetscGetArguments()
451 
452 @*/
453 PetscErrorCode  PetscFreeArguments(char **args)
454 {
455   PetscInt       i = 0;
456   PetscErrorCode ierr;
457 
458   PetscFunctionBegin;
459   if (!args) {PetscFunctionReturn(0);}
460   while (args[i]) {
461     ierr = PetscFree(args[i]);CHKERRQ(ierr);
462     i++;
463   }
464   ierr = PetscFree(args);CHKERRQ(ierr);
465   PetscFunctionReturn(0);
466 }
467 
468 #undef __FUNCT__
469 #define __FUNCT__ "PetscInitialize"
470 /*@C
471    PetscInitialize - Initializes the PETSc database and MPI.
472    PetscInitialize() calls MPI_Init() if that has yet to be called,
473    so this routine should always be called near the beginning of
474    your program -- usually the very first line!
475 
476    Collective on MPI_COMM_WORLD or PETSC_COMM_WORLD if it has been set
477 
478    Input Parameters:
479 +  argc - count of number of command line arguments
480 .  args - the command line arguments
481 .  file - [optional] PETSc database file, also checks ~username/.petscrc and .petscrc use PETSC_NULL to not check for
482           code specific file. Use -skip_petscrc in the code specific file to skip the .petscrc files
483 -  help - [optional] Help message to print, use PETSC_NULL for no message
484 
485    If you wish PETSc code to run ONLY on a subcommunicator of MPI_COMM_WORLD, create that
486    communicator first and assign it to PETSC_COMM_WORLD BEFORE calling PetscInitialize(). Thus if you are running a
487    four process job and two processes will run PETSc and have PetscInitialize() and PetscFinalize() and two process will not,
488    then do this. If ALL processes in the job are using PetscInitialize() and PetscFinalize() then you don't need to do this, even
489    if different subcommunicators of the job are doing different things with PETSc.
490 
491    Options Database Keys:
492 +  -start_in_debugger [noxterm,dbx,xdb,gdb,...] - Starts program in debugger
493 .  -on_error_attach_debugger [noxterm,dbx,xdb,gdb,...] - Starts debugger when error detected
494 .  -on_error_emacs <machinename> causes emacsclient to jump to error file
495 .  -on_error_abort calls abort() when error detected (no traceback)
496 .  -on_error_mpiabort calls MPI_abort() when error detected
497 .  -error_output_stderr prints error messages to stderr instead of the default stdout
498 .  -error_output_none does not print the error messages (but handles errors in the same way as if this was not called)
499 .  -debugger_nodes [node1,node2,...] - Indicates nodes to start in debugger
500 .  -debugger_pause [sleeptime] (in seconds) - Pauses debugger
501 .  -stop_for_debugger - Print message on how to attach debugger manually to
502                         process and wait (-debugger_pause) seconds for attachment
503 .  -malloc - Indicates use of PETSc error-checking malloc (on by default for debug version of libraries)
504 .  -malloc no - Indicates not to use error-checking malloc
505 .  -malloc_debug - check for memory corruption at EVERY malloc or free
506 .  -fp_trap - Stops on floating point exceptions (Note that on the
507               IBM RS6000 this slows code by at least a factor of 10.)
508 .  -no_signal_handler - Indicates not to trap error signals
509 .  -shared_tmp - indicates /tmp directory is shared by all processors
510 .  -not_shared_tmp - each processor has own /tmp
511 .  -tmp - alternative name of /tmp directory
512 .  -get_total_flops - returns total flops done by all processors
513 -  -memory_info - Print memory usage at end of run
514 
515    Options Database Keys for Profiling:
516    See the <a href="../../docs/manual.pdf#nameddest=ch_profiling">profiling chapter of the users manual</a> for details.
517 +  -log_trace [filename] - Print traces of all PETSc calls
518         to the screen (useful to determine where a program
519         hangs without running in the debugger).  See PetscLogTraceBegin().
520 .  -info <optional filename> - Prints verbose information to the screen
521 -  -info_exclude <null,vec,mat,pc,ksp,snes,ts> - Excludes some of the verbose messages
522 
523    Environmental Variables:
524 +   PETSC_TMP - alternative tmp directory
525 .   PETSC_SHARED_TMP - tmp is shared by all processes
526 .   PETSC_NOT_SHARED_TMP - each process has its own private tmp
527 .   PETSC_VIEWER_SOCKET_PORT - socket number to use for socket viewer
528 -   PETSC_VIEWER_SOCKET_MACHINE - machine to use for socket viewer to connect to
529 
530 
531    Level: beginner
532 
533    Notes:
534    If for some reason you must call MPI_Init() separately, call
535    it before PetscInitialize().
536 
537    Fortran Version:
538    In Fortran this routine has the format
539 $       call PetscInitialize(file,ierr)
540 
541 +   ierr - error return code
542 -  file - [optional] PETSc database file, also checks ~username/.petscrc and .petscrc use PETSC_NULL_CHARACTER to not check for
543           code specific file. Use -skip_petscrc in the code specific file to skip the .petscrc files
544 
545    Important Fortran Note:
546    In Fortran, you MUST use PETSC_NULL_CHARACTER to indicate a
547    null character string; you CANNOT just use PETSC_NULL as
548    in the C version. See the <a href="../../docs/manual.pdf">users manual</a> for details.
549 
550    If your main program is C but you call Fortran code that also uses PETSc you need to call PetscInitializeFortran() soon after
551    calling PetscInitialize().
552 
553    Concepts: initializing PETSc
554 
555 .seealso: PetscFinalize(), PetscInitializeFortran(), PetscGetArgs(), PetscInitializeNoArguments()
556 
557 @*/
558 PetscErrorCode  PetscInitialize(int *argc,char ***args,const char file[],const char help[])
559 {
560   PetscErrorCode ierr;
561   PetscMPIInt    flag, size;
562   PetscInt       nodesize;
563   PetscBool      flg;
564   char           hostname[256];
565 
566   PetscFunctionBegin;
567   if (PetscInitializeCalled) PetscFunctionReturn(0);
568 
569   /* these must be initialized in a routine, not as a constant declaration*/
570   PETSC_STDOUT = stdout;
571   PETSC_STDERR = stderr;
572 
573   ierr = PetscOptionsCreate();CHKERRQ(ierr);
574 
575   /*
576      We initialize the program name here (before MPI_Init()) because MPICH has a bug in
577      it that it sets args[0] on all processors to be args[0] on the first processor.
578   */
579   if (argc && *argc) {
580     ierr = PetscSetProgramName(**args);CHKERRQ(ierr);
581   } else {
582     ierr = PetscSetProgramName("Unknown Name");CHKERRQ(ierr);
583   }
584 
585   ierr = MPI_Initialized(&flag);CHKERRQ(ierr);
586   if (!flag) {
587     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");
588     ierr          = MPI_Init(argc,args);CHKERRQ(ierr);
589     PetscBeganMPI = PETSC_TRUE;
590   }
591   if (argc && args) {
592     PetscGlobalArgc = *argc;
593     PetscGlobalArgs = *args;
594   }
595   PetscFinalizeCalled   = PETSC_FALSE;
596 
597   if (PETSC_COMM_WORLD == MPI_COMM_NULL) {
598     PETSC_COMM_WORLD = MPI_COMM_WORLD;
599   }
600   ierr = MPI_Errhandler_set(PETSC_COMM_WORLD,MPI_ERRORS_RETURN);CHKERRQ(ierr);
601 
602   /* Done after init due to a bug in MPICH-GM? */
603   ierr = PetscErrorPrintfInitialize();CHKERRQ(ierr);
604 
605   ierr = MPI_Comm_rank(MPI_COMM_WORLD,&PetscGlobalRank);CHKERRQ(ierr);
606   ierr = MPI_Comm_size(MPI_COMM_WORLD,&PetscGlobalSize);CHKERRQ(ierr);
607 
608 #if defined(PETSC_USE_COMPLEX)
609   /*
610      Initialized the global complex variable; this is because with
611      shared libraries the constructors for global variables
612      are not called; at least on IRIX.
613   */
614   {
615 #if defined(PETSC_CLANGUAGE_CXX)
616     PetscScalar ic(0.0,1.0);
617     PETSC_i = ic;
618 #else
619     PETSC_i = I;
620 #endif
621   }
622 
623 #if !defined(PETSC_HAVE_MPI_C_DOUBLE_COMPLEX)
624   ierr = MPI_Type_contiguous(2,MPIU_REAL,&MPI_C_DOUBLE_COMPLEX);CHKERRQ(ierr);
625   ierr = MPI_Type_commit(&MPI_C_DOUBLE_COMPLEX);CHKERRQ(ierr);
626   ierr = MPI_Type_contiguous(2,MPI_FLOAT,&MPI_C_COMPLEX);CHKERRQ(ierr);
627   ierr = MPI_Type_commit(&MPI_C_COMPLEX);CHKERRQ(ierr);
628   ierr = MPI_Op_create(PetscSum_Local,1,&MPIU_SUM);CHKERRQ(ierr);
629 #endif
630 #endif
631 
632   /*
633      Create the PETSc MPI reduction operator that sums of the first
634      half of the entries and maxes the second half.
635   */
636   ierr = MPI_Op_create(PetscMaxSum_Local,1,&PetscMaxSum_Op);CHKERRQ(ierr);
637 
638   ierr = MPI_Type_contiguous(2,MPIU_SCALAR,&MPIU_2SCALAR);CHKERRQ(ierr);
639   ierr = MPI_Type_commit(&MPIU_2SCALAR);CHKERRQ(ierr);
640   ierr = MPI_Op_create(PetscADMax_Local,1,&PetscADMax_Op);CHKERRQ(ierr);
641   ierr = MPI_Op_create(PetscADMin_Local,1,&PetscADMin_Op);CHKERRQ(ierr);
642 
643   ierr = MPI_Type_contiguous(2,MPIU_INT,&MPIU_2INT);CHKERRQ(ierr);
644   ierr = MPI_Type_commit(&MPIU_2INT);CHKERRQ(ierr);
645 
646   /*
647      Attributes to be set on PETSc communicators
648   */
649   ierr = MPI_Keyval_create(MPI_NULL_COPY_FN,Petsc_DelCounter,&Petsc_Counter_keyval,(void*)0);CHKERRQ(ierr);
650   ierr = MPI_Keyval_create(MPI_NULL_COPY_FN,Petsc_DelComm,&Petsc_InnerComm_keyval,(void*)0);CHKERRQ(ierr);
651   ierr = MPI_Keyval_create(MPI_NULL_COPY_FN,Petsc_DelComm,&Petsc_OuterComm_keyval,(void*)0);CHKERRQ(ierr);
652 
653   /*
654      Build the options database
655   */
656   ierr = PetscOptionsInsert(argc,args,file);CHKERRQ(ierr);
657 
658 
659   /*
660      Print main application help message
661   */
662   ierr = PetscOptionsHasName(PETSC_NULL,"-help",&flg);CHKERRQ(ierr);
663   if (help && flg) {
664     ierr = PetscPrintf(PETSC_COMM_WORLD,help);CHKERRQ(ierr);
665   }
666   ierr = PetscOptionsCheckInitial_Private();CHKERRQ(ierr);
667 
668   /* SHOULD PUT IN GUARDS: Make sure logging is initialized, even if we do not print it out */
669 #if defined(PETSC_USE_LOG)
670   ierr = PetscLogBegin_Private();CHKERRQ(ierr);
671 #endif
672 
673   /*
674      Load the dynamic libraries (on machines that support them), this registers all
675      the solvers etc. (On non-dynamic machines this initializes the PetscDraw and PetscViewer classes)
676   */
677   ierr = PetscInitialize_DynamicLibraries();CHKERRQ(ierr);
678 
679   ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr);
680   ierr = PetscInfo1(0,"PETSc successfully started: number of processors = %d\n",size);CHKERRQ(ierr);
681   ierr = PetscGetHostName(hostname,256);CHKERRQ(ierr);
682   ierr = PetscInfo1(0,"Running on machine: %s\n",hostname);CHKERRQ(ierr);
683 
684   ierr = PetscOptionsCheckInitial_Components();CHKERRQ(ierr);
685   /* Check the options database for options related to the options database itself */
686   ierr = PetscOptionsSetFromOptions();CHKERRQ(ierr);
687 
688 #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
689   /*
690       Tell MPI about our own data representation converter, this would/should be used if extern32 is not supported by the MPI
691 
692       Currently not used because it is not supported by MPICH.
693   */
694 #if !defined(PETSC_WORDS_BIGENDIAN)
695   ierr = MPI_Register_datarep((char *)"petsc",PetscDataRep_read_conv_fn,PetscDataRep_write_conv_fn,PetscDataRep_extent_fn,PETSC_NULL);CHKERRQ(ierr);
696 #endif
697 #endif
698 
699   ierr = PetscOptionsGetInt(PETSC_NULL,"-openmp_spawn_size",&nodesize,&flg);CHKERRQ(ierr);
700   if (flg) {
701 #if defined(PETSC_HAVE_MPI_COMM_SPAWN)
702     ierr = PetscOpenMPSpawn((PetscMPIInt) nodesize);CHKERRQ(ierr); /* worker nodes never return from here; they go directly to PetscEnd() */
703 #else
704     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"PETSc built without MPI 2 (MPI_Comm_spawn) support, use -openmp_merge_size instead");
705 #endif
706   } else {
707     ierr = PetscOptionsGetInt(PETSC_NULL,"-openmp_merge_size",&nodesize,&flg);CHKERRQ(ierr);
708     if (flg) {
709       ierr = PetscOpenMPMerge((PetscMPIInt) nodesize,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
710       if (PetscOpenMPWorker) { /* if worker then never enter user code */
711         ierr = PetscEnd();
712       }
713     }
714   }
715   flg  = PETSC_FALSE;
716   ierr = PetscOptionsGetBool(PETSC_NULL,"-python",&flg,PETSC_NULL);CHKERRQ(ierr);
717   if (flg) {ierr = PetscPythonInitialize(PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);}
718 
719 #if defined(PETSC_HAVE_CUDA)
720   cublasInit();
721 #endif
722 
723 #if defined(PETSC_HAVE_AMS)
724   ierr = PetscOptionsHasName(PETSC_NULL,"-ams_publish_objects",&flg);CHKERRQ(ierr);
725   if (flg) {
726     PetscAMSPublishAll = PETSC_TRUE;
727   }
728 #endif
729 
730   /*
731       Once we are completedly initialized then we can set this variables
732   */
733   PetscInitializeCalled = PETSC_TRUE;
734   PetscFunctionReturn(0);
735 }
736 
737 
738 #undef __FUNCT__
739 #define __FUNCT__ "PetscFinalize"
740 /*@C
741    PetscFinalize - Checks for options to be called at the conclusion
742    of the program. MPI_Finalize() is called only if the user had not
743    called MPI_Init() before calling PetscInitialize().
744 
745    Collective on PETSC_COMM_WORLD
746 
747    Options Database Keys:
748 +  -options_table - Calls PetscOptionsPrint()
749 .  -options_left - Prints unused options that remain in the database
750 .  -options_left no - Does not print unused options that remain in the database
751 .  -mpidump - Calls PetscMPIDump()
752 .  -malloc_dump - Calls PetscMallocDump()
753 .  -malloc_info - Prints total memory usage
754 -  -malloc_log - Prints summary of memory usage
755 
756    Options Database Keys for Profiling:
757    See the <a href="../../docs/manual.pdf#nameddest=ch_profiling">profiling chapter of the users manual</a> for details.
758 +  -log_summary [filename] - Prints summary of flop and timing
759         information to screen. If the filename is specified the
760         summary is written to the file.  See PetscLogPrintSummary().
761 .  -log_summary_python [filename] - Prints data on of flop and timing usage to a file or screen.
762         See PetscLogPrintSummaryPy().
763 .  -log_all [filename] - Logs extensive profiling information
764         See PetscLogDump().
765 .  -log [filename] - Logs basic profiline information  See PetscLogDump().
766 .  -log_sync - Log the synchronization in scatters, inner products
767         and norms
768 -  -log_mpe [filename] - Creates a logfile viewable by the
769       utility Upshot/Nupshot (in MPICH distribution)
770 
771    Level: beginner
772 
773    Note:
774    See PetscInitialize() for more general runtime options.
775 
776 .seealso: PetscInitialize(), PetscOptionsPrint(), PetscMallocDump(), PetscMPIDump(), PetscEnd()
777 @*/
778 PetscErrorCode  PetscFinalize(void)
779 {
780   PetscErrorCode ierr;
781   PetscMPIInt    rank;
782   int            nopt;
783   PetscBool      flg1 = PETSC_FALSE,flg2 = PETSC_FALSE,flg3 = PETSC_FALSE;
784 #if defined(PETSC_HAVE_AMS)
785   PetscBool      flg = PETSC_FALSE;
786 #endif
787 
788   PetscFunctionBegin;
789 
790   if (!PetscInitializeCalled) {
791     printf("PetscInitialize() must be called before PetscFinalize()\n");
792     PetscFunctionReturn(PETSC_ERR_ARG_WRONGSTATE);
793   }
794   ierr = PetscInfo(PETSC_NULL,"PetscFinalize() called\n");
795 
796 #if defined(PETSC_HAVE_AMS)
797   ierr = PetscOptionsGetBool(PETSC_NULL,"-options_gui",&flg,PETSC_NULL);CHKERRQ(ierr);
798   if (flg) {
799     ierr = PetscOptionsAMSDestroy();CHKERRQ(ierr);
800   }
801 #endif
802 
803   ierr = PetscOpenMPFinalize();CHKERRQ(ierr);
804 
805   ierr = PetscOptionsGetBool(PETSC_NULL,"-python",&flg1,PETSC_NULL);CHKERRQ(ierr);
806   if (flg1) {ierr = PetscPythonFinalize();CHKERRQ(ierr);}
807 
808   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
809   ierr = PetscOptionsGetBool(PETSC_NULL,"-malloc_info",&flg2,PETSC_NULL);CHKERRQ(ierr);
810   if (!flg2) {
811     flg2 = PETSC_FALSE;
812     ierr = PetscOptionsGetBool(PETSC_NULL,"-memory_info",&flg2,PETSC_NULL);CHKERRQ(ierr);
813   }
814   if (flg2) {
815     ierr = PetscMemoryShowUsage(PETSC_VIEWER_STDOUT_WORLD,"Summary of Memory Usage in PETSc\n");CHKERRQ(ierr);
816   }
817 
818   /*
819      Free all objects registered with PetscObjectRegisterDestroy() such as PETSC_VIEWER_XXX_().
820   */
821   ierr = PetscObjectRegisterDestroyAll();CHKERRQ(ierr);
822 
823   /*
824        Free all the registered create functions, such as KSPList, VecList, SNESList, etc
825   */
826   ierr = PetscFListDestroyAll();CHKERRQ(ierr);
827 
828   /*
829      Destroy any packages that registered a finalize
830   */
831   ierr = PetscRegisterFinalizeAll();CHKERRQ(ierr);
832 
833   /*
834      Destroy all the function registration lists created
835   */
836   ierr = PetscFinalize_DynamicLibraries();CHKERRQ(ierr);
837 
838 #if defined(PETSC_USE_LOG)
839   flg1 = PETSC_FALSE;
840   ierr = PetscOptionsGetBool(PETSC_NULL,"-get_total_flops",&flg1,PETSC_NULL);CHKERRQ(ierr);
841   if (flg1) {
842     PetscLogDouble flops = 0;
843     ierr = MPI_Reduce(&_TotalFlops,&flops,1,MPI_DOUBLE,MPI_SUM,0,PETSC_COMM_WORLD);CHKERRQ(ierr);
844     ierr = PetscPrintf(PETSC_COMM_WORLD,"Total flops over all processors %g\n",flops);CHKERRQ(ierr);
845   }
846 #endif
847 
848 #if defined(PETSC_USE_DEBUG) && !defined(PETSC_USE_PTHREAD)
849   if (PetscStackActive) {
850     ierr = PetscStackDestroy();CHKERRQ(ierr);
851   }
852 #endif
853 
854 #if defined(PETSC_USE_LOG)
855   {
856     char mname[PETSC_MAX_PATH_LEN];
857 #if defined(PETSC_HAVE_MPE)
858     mname[0] = 0;
859     ierr = PetscOptionsGetString(PETSC_NULL,"-log_mpe",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr);
860     if (flg1){
861       if (mname[0]) {ierr = PetscLogMPEDump(mname);CHKERRQ(ierr);}
862       else          {ierr = PetscLogMPEDump(0);CHKERRQ(ierr);}
863     }
864 #endif
865     mname[0] = 0;
866     ierr = PetscOptionsGetString(PETSC_NULL,"-log_summary",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr);
867     if (flg1) {
868       if (mname[0])  {ierr = PetscLogPrintSummary(PETSC_COMM_WORLD,mname);CHKERRQ(ierr);}
869       else           {ierr = PetscLogPrintSummary(PETSC_COMM_WORLD,0);CHKERRQ(ierr);}
870     }
871 
872     mname[0] = 0;
873     ierr = PetscOptionsGetString(PETSC_NULL,"-log_summary_python",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr);
874     if (flg1) {
875       PetscViewer viewer;
876       if (mname[0])  {
877         ierr = PetscViewerASCIIOpen(PETSC_COMM_WORLD,mname,&viewer);CHKERRQ(ierr);
878       } else {
879         viewer = PETSC_VIEWER_STDOUT_WORLD;
880       }
881       ierr = PetscLogPrintSummaryPython(viewer);CHKERRQ(ierr);
882       ierr = PetscViewerDestroy(viewer);CHKERRQ(ierr);
883     }
884 
885     ierr = PetscOptionsGetString(PETSC_NULL,"-log_detailed",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr);
886     if (flg1) {
887       if (mname[0])  {ierr = PetscLogPrintDetailed(PETSC_COMM_WORLD,mname);CHKERRQ(ierr);}
888       else           {ierr = PetscLogPrintDetailed(PETSC_COMM_WORLD,0);CHKERRQ(ierr);}
889     }
890 
891     mname[0] = 0;
892     ierr = PetscOptionsGetString(PETSC_NULL,"-log_all",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr);
893     ierr = PetscOptionsGetString(PETSC_NULL,"-log",mname,PETSC_MAX_PATH_LEN,&flg2);CHKERRQ(ierr);
894     if (flg1 || flg2){
895       if (mname[0]) PetscLogDump(mname);
896       else          PetscLogDump(0);
897     }
898     ierr = PetscLogDestroy();CHKERRQ(ierr);
899   }
900 #endif
901   flg1 = PETSC_FALSE;
902   ierr = PetscOptionsGetBool(PETSC_NULL,"-no_signal_handler",&flg1,PETSC_NULL);CHKERRQ(ierr);
903   if (!flg1) { ierr = PetscPopSignalHandler();CHKERRQ(ierr);}
904   flg1 = PETSC_FALSE;
905   ierr = PetscOptionsGetBool(PETSC_NULL,"-mpidump",&flg1,PETSC_NULL);CHKERRQ(ierr);
906   if (flg1) {
907     ierr = PetscMPIDump(stdout);CHKERRQ(ierr);
908   }
909   flg1 = PETSC_FALSE;
910   flg2 = PETSC_FALSE;
911   /* preemptive call to avoid listing this option in options table as unused */
912   ierr = PetscOptionsHasName(PETSC_NULL,"-malloc_dump",&flg1);CHKERRQ(ierr);
913   ierr = PetscOptionsGetBool(PETSC_NULL,"-options_table",&flg2,PETSC_NULL);CHKERRQ(ierr);
914 
915   if (flg2) {
916     if (!rank) {ierr = PetscOptionsPrint(stdout);CHKERRQ(ierr);}
917   }
918 
919   /* to prevent PETSc -options_left from warning */
920   ierr = PetscOptionsHasName(PETSC_NULL,"-nox",&flg1);CHKERRQ(ierr);
921   ierr = PetscOptionsHasName(PETSC_NULL,"-nox_warning",&flg1);CHKERRQ(ierr);
922 
923   if (!PetscOpenMPWorker) { /* worker processes skip this because they do not usually process options */
924     flg3 = PETSC_FALSE; /* default value is required */
925     ierr = PetscOptionsGetBool(PETSC_NULL,"-options_left",&flg3,&flg1);CHKERRQ(ierr);
926     ierr = PetscOptionsAllUsed(&nopt);CHKERRQ(ierr);
927     if (flg3) {
928       if (!flg2) { /* have not yet printed the options */
929 	ierr = PetscOptionsPrint(stdout);CHKERRQ(ierr);
930       }
931       if (!nopt) {
932 	ierr = PetscPrintf(PETSC_COMM_WORLD,"There are no unused options.\n");CHKERRQ(ierr);
933       } else if (nopt == 1) {
934 	ierr = PetscPrintf(PETSC_COMM_WORLD,"There is one unused database option. It is:\n");CHKERRQ(ierr);
935       } else {
936 	ierr = PetscPrintf(PETSC_COMM_WORLD,"There are %d unused database options. They are:\n",nopt);CHKERRQ(ierr);
937       }
938     }
939 #if defined(PETSC_USE_DEBUG)
940     if (nopt && !flg3 && !flg1) {
941       ierr = PetscPrintf(PETSC_COMM_WORLD,"WARNING! There are options you set that were not used!\n");CHKERRQ(ierr);
942       ierr = PetscPrintf(PETSC_COMM_WORLD,"WARNING! could be spelling mistake, etc!\n");CHKERRQ(ierr);
943       ierr = PetscOptionsLeft();CHKERRQ(ierr);
944     } else if (nopt && flg3) {
945 #else
946     if (nopt && flg3) {
947 #endif
948       ierr = PetscOptionsLeft();CHKERRQ(ierr);
949     }
950   }
951 
952   if (petsc_history) {
953     ierr = PetscCloseHistoryFile(&petsc_history);CHKERRQ(ierr);
954     petsc_history = 0;
955   }
956 
957   ierr = PetscInfoAllow(PETSC_FALSE,PETSC_NULL);CHKERRQ(ierr);
958 
959   {
960     char fname[PETSC_MAX_PATH_LEN];
961     FILE *fd;
962     int  err;
963 
964     fname[0] = 0;
965     ierr = PetscOptionsGetString(PETSC_NULL,"-malloc_dump",fname,250,&flg1);CHKERRQ(ierr);
966     if (flg1 && fname[0]) {
967       char sname[PETSC_MAX_PATH_LEN];
968 
969       sprintf(sname,"%s_%d",fname,rank);
970       fd   = fopen(sname,"w"); if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open log file: %s",sname);
971       ierr = PetscMallocDump(fd);CHKERRQ(ierr);
972       err = fclose(fd);
973       if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
974     } else if (flg1) {
975       MPI_Comm local_comm;
976 
977       ierr = MPI_Comm_dup(MPI_COMM_WORLD,&local_comm);CHKERRQ(ierr);
978       ierr = PetscSequentialPhaseBegin_Private(local_comm,1);CHKERRQ(ierr);
979         ierr = PetscMallocDump(stdout);CHKERRQ(ierr);
980       ierr = PetscSequentialPhaseEnd_Private(local_comm,1);CHKERRQ(ierr);
981       ierr = MPI_Comm_free(&local_comm);CHKERRQ(ierr);
982     }
983   }
984   {
985     char fname[PETSC_MAX_PATH_LEN];
986     FILE *fd;
987 
988     fname[0] = 0;
989     ierr = PetscOptionsGetString(PETSC_NULL,"-malloc_log",fname,250,&flg1);CHKERRQ(ierr);
990     if (flg1 && fname[0]) {
991       char sname[PETSC_MAX_PATH_LEN];
992       int  err;
993 
994       sprintf(sname,"%s_%d",fname,rank);
995       fd   = fopen(sname,"w"); if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open log file: %s",sname);
996       ierr = PetscMallocDumpLog(fd);CHKERRQ(ierr);
997       err = fclose(fd);
998       if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
999     } else if (flg1) {
1000       ierr = PetscMallocDumpLog(stdout);CHKERRQ(ierr);
1001     }
1002   }
1003   /* Can be destroyed only after all the options are used */
1004   ierr = PetscOptionsDestroy();CHKERRQ(ierr);
1005 
1006   PetscGlobalArgc = 0;
1007   PetscGlobalArgs = 0;
1008 
1009 #if defined(PETSC_USE_COMPLEX)
1010 #if !defined(PETSC_HAVE_MPI_C_DOUBLE_COMPLEX)
1011   ierr = MPI_Op_free(&MPIU_SUM);CHKERRQ(ierr);
1012   ierr = MPI_Type_free(&MPI_C_DOUBLE_COMPLEX);CHKERRQ(ierr);
1013   ierr = MPI_Type_free(&MPI_C_COMPLEX);CHKERRQ(ierr);
1014 #endif
1015 #endif
1016   ierr = MPI_Type_free(&MPIU_2SCALAR);CHKERRQ(ierr);
1017   ierr = MPI_Type_free(&MPIU_2INT);CHKERRQ(ierr);
1018   ierr = MPI_Op_free(&PetscMaxSum_Op);CHKERRQ(ierr);
1019   ierr = MPI_Op_free(&PetscADMax_Op);CHKERRQ(ierr);
1020   ierr = MPI_Op_free(&PetscADMin_Op);CHKERRQ(ierr);
1021 
1022   ierr = MPI_Keyval_free(&Petsc_Counter_keyval);CHKERRQ(ierr);
1023   ierr = MPI_Keyval_free(&Petsc_InnerComm_keyval);CHKERRQ(ierr);
1024   ierr = MPI_Keyval_free(&Petsc_OuterComm_keyval);CHKERRQ(ierr);
1025 
1026   ierr = PetscInfo(0,"PETSc successfully ended!\n");CHKERRQ(ierr);
1027   if (PetscBeganMPI) {
1028 #if defined(PETSC_HAVE_MPI_FINALIZED)
1029     PetscMPIInt flag;
1030     ierr = MPI_Finalized(&flag);CHKERRQ(ierr);
1031     if (flag) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"MPI_Finalize() has already been called, even though MPI_Init() was called by PetscInitialize()");
1032 #endif
1033     ierr = MPI_Finalize();CHKERRQ(ierr);
1034   }
1035 
1036   if (PETSC_ZOPEFD){
1037     if (PETSC_ZOPEFD != PETSC_STDOUT) fprintf(PETSC_ZOPEFD, "<<<end>>>");
1038     else fprintf(PETSC_STDOUT, "<<<end>>>");
1039   }
1040 
1041 #if defined(PETSC_HAVE_CUDA)
1042   cublasShutdown();
1043 #endif
1044 /*
1045 
1046      Note: In certain cases PETSC_COMM_WORLD is never MPI_Comm_free()ed because
1047    the communicator has some outstanding requests on it. Specifically if the
1048    flag PETSC_HAVE_BROKEN_REQUEST_FREE is set (for IBM MPI implementation). See
1049    src/vec/utils/vpscat.c. Due to this the memory allocated in PetscCommDuplicate()
1050    is never freed as it should be. Thus one may obtain messages of the form
1051    [ 1] 8 bytes PetscCommDuplicate() line 645 in src/sys/mpiu.c indicating the
1052    memory was not freed.
1053 
1054 */
1055   ierr = PetscMallocClear();CHKERRQ(ierr);
1056   PetscInitializeCalled = PETSC_FALSE;
1057   PetscFinalizeCalled   = PETSC_TRUE;
1058   PetscFunctionReturn(ierr);
1059 }
1060 
1061