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