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