xref: /petsc/src/sys/objects/pinit.c (revision e3c5b3bad8a8c55ce6fdc25c1dde664f52a31a1c)
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 extern PetscObject *PetscObjects;
741 extern PetscInt    PetscObjectsCounts, PetscObjectsMaxCounts;
742 
743 #undef __FUNCT__
744 #define __FUNCT__ "PetscFinalize"
745 /*@C
746    PetscFinalize - Checks for options to be called at the conclusion
747    of the program. MPI_Finalize() is called only if the user had not
748    called MPI_Init() before calling PetscInitialize().
749 
750    Collective on PETSC_COMM_WORLD
751 
752    Options Database Keys:
753 +  -options_table - Calls PetscOptionsView()
754 .  -options_left - Prints unused options that remain in the database
755 .  -options_left no - Does not print unused options that remain in the database
756 .  -mpidump - Calls PetscMPIDump()
757 .  -malloc_dump - Calls PetscMallocDump()
758 .  -malloc_info - Prints total memory usage
759 -  -malloc_log - Prints summary of memory usage
760 
761    Options Database Keys for Profiling:
762    See the <a href="../../docs/manual.pdf#nameddest=ch_profiling">profiling chapter of the users manual</a> for details.
763 +  -log_summary [filename] - Prints summary of flop and timing
764         information to screen. If the filename is specified the
765         summary is written to the file.  See PetscLogView().
766 .  -log_summary_python [filename] - Prints data on of flop and timing usage to a file or screen.
767         See PetscLogPrintSViewPython().
768 .  -log_all [filename] - Logs extensive profiling information
769         See PetscLogDump().
770 .  -log [filename] - Logs basic profiline information  See PetscLogDump().
771 .  -log_sync - Log the synchronization in scatters, inner products
772         and norms
773 -  -log_mpe [filename] - Creates a logfile viewable by the
774       utility Upshot/Nupshot (in MPICH distribution)
775 
776    Level: beginner
777 
778    Note:
779    See PetscInitialize() for more general runtime options.
780 
781 .seealso: PetscInitialize(), PetscOptionsView(), PetscMallocDump(), PetscMPIDump(), PetscEnd()
782 @*/
783 PetscErrorCode  PetscFinalize(void)
784 {
785   PetscErrorCode ierr;
786   PetscMPIInt    rank;
787   PetscInt       i,nopt;
788   PetscBool      flg1 = PETSC_FALSE,flg2 = PETSC_FALSE,flg3 = PETSC_FALSE;
789 #if defined(PETSC_HAVE_AMS)
790   PetscBool      flg = PETSC_FALSE;
791 #endif
792 #if defined(PETSC_USE_LOG)
793   char           mname[PETSC_MAX_PATH_LEN];
794 #endif
795 
796   PetscFunctionBegin;
797 
798   if (!PetscInitializeCalled) {
799     printf("PetscInitialize() must be called before PetscFinalize()\n");
800     PetscFunctionReturn(PETSC_ERR_ARG_WRONGSTATE);
801   }
802   ierr = PetscInfo(PETSC_NULL,"PetscFinalize() called\n");
803 
804 #if defined(PETSC_HAVE_AMS)
805   ierr = PetscOptionsGetBool(PETSC_NULL,"-options_gui",&flg,PETSC_NULL);CHKERRQ(ierr);
806   if (flg) {
807     ierr = PetscOptionsAMSDestroy();CHKERRQ(ierr);
808   }
809 #endif
810 
811   ierr = PetscOpenMPFinalize();CHKERRQ(ierr);
812 
813   ierr = PetscOptionsGetBool(PETSC_NULL,"-python",&flg1,PETSC_NULL);CHKERRQ(ierr);
814   if (flg1) {ierr = PetscPythonFinalize();CHKERRQ(ierr);}
815 
816   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
817   ierr = PetscOptionsGetBool(PETSC_NULL,"-malloc_info",&flg2,PETSC_NULL);CHKERRQ(ierr);
818   if (!flg2) {
819     flg2 = PETSC_FALSE;
820     ierr = PetscOptionsGetBool(PETSC_NULL,"-memory_info",&flg2,PETSC_NULL);CHKERRQ(ierr);
821   }
822   if (flg2) {
823     ierr = PetscMemoryShowUsage(PETSC_VIEWER_STDOUT_WORLD,"Summary of Memory Usage in PETSc\n");CHKERRQ(ierr);
824   }
825 
826 #if defined(PETSC_USE_LOG)
827   flg1 = PETSC_FALSE;
828   ierr = PetscOptionsGetBool(PETSC_NULL,"-get_total_flops",&flg1,PETSC_NULL);CHKERRQ(ierr);
829   if (flg1) {
830     PetscLogDouble flops = 0;
831     ierr = MPI_Reduce(&_TotalFlops,&flops,1,MPI_DOUBLE,MPI_SUM,0,PETSC_COMM_WORLD);CHKERRQ(ierr);
832     ierr = PetscPrintf(PETSC_COMM_WORLD,"Total flops over all processors %g\n",flops);CHKERRQ(ierr);
833   }
834 #endif
835 
836 
837 #if defined(PETSC_USE_LOG)
838 #if defined(PETSC_HAVE_MPE)
839   mname[0] = 0;
840   ierr = PetscOptionsGetString(PETSC_NULL,"-log_mpe",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr);
841   if (flg1){
842     if (mname[0]) {ierr = PetscLogMPEDump(mname);CHKERRQ(ierr);}
843     else          {ierr = PetscLogMPEDump(0);CHKERRQ(ierr);}
844   }
845 #endif
846   mname[0] = 0;
847   ierr = PetscOptionsGetString(PETSC_NULL,"-log_summary",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr);
848   if (flg1) {
849     PetscViewer viewer;
850     if (mname[0])  {
851       ierr = PetscViewerASCIIOpen(PETSC_COMM_WORLD,mname,&viewer);CHKERRQ(ierr);
852       ierr = PetscLogView(viewer);CHKERRQ(ierr);
853       ierr = PetscViewerDestroy(viewer);CHKERRQ(ierr);
854     } else {
855       viewer = PETSC_VIEWER_STDOUT_WORLD;
856       ierr = PetscLogView(viewer);CHKERRQ(ierr);
857     }
858   }
859 
860   mname[0] = 0;
861   ierr = PetscOptionsGetString(PETSC_NULL,"-log_summary_python",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr);
862   if (flg1) {
863     PetscViewer viewer;
864     if (mname[0])  {
865       ierr = PetscViewerASCIIOpen(PETSC_COMM_WORLD,mname,&viewer);CHKERRQ(ierr);
866       ierr = PetscLogViewPython(viewer);CHKERRQ(ierr);
867       ierr = PetscViewerDestroy(viewer);CHKERRQ(ierr);
868     } else {
869       viewer = PETSC_VIEWER_STDOUT_WORLD;
870       ierr = PetscLogViewPython(viewer);CHKERRQ(ierr);
871     }
872   }
873 
874   ierr = PetscOptionsGetString(PETSC_NULL,"-log_detailed",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr);
875   if (flg1) {
876     if (mname[0])  {ierr = PetscLogPrintDetailed(PETSC_COMM_WORLD,mname);CHKERRQ(ierr);}
877     else           {ierr = PetscLogPrintDetailed(PETSC_COMM_WORLD,0);CHKERRQ(ierr);}
878   }
879 
880   mname[0] = 0;
881   ierr = PetscOptionsGetString(PETSC_NULL,"-log_all",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr);
882   ierr = PetscOptionsGetString(PETSC_NULL,"-log",mname,PETSC_MAX_PATH_LEN,&flg2);CHKERRQ(ierr);
883   if (flg1 || flg2){
884     if (mname[0]) PetscLogDump(mname);
885     else          PetscLogDump(0);
886   }
887 #endif
888 
889 #if defined(PETSC_USE_DEBUG) && !defined(PETSC_USE_PTHREAD)
890   if (PetscStackActive) {
891     ierr = PetscStackDestroy();CHKERRQ(ierr);
892   }
893 #endif
894 
895   flg1 = PETSC_FALSE;
896   ierr = PetscOptionsGetBool(PETSC_NULL,"-no_signal_handler",&flg1,PETSC_NULL);CHKERRQ(ierr);
897   if (!flg1) { ierr = PetscPopSignalHandler();CHKERRQ(ierr);}
898   flg1 = PETSC_FALSE;
899   ierr = PetscOptionsGetBool(PETSC_NULL,"-mpidump",&flg1,PETSC_NULL);CHKERRQ(ierr);
900   if (flg1) {
901     ierr = PetscMPIDump(stdout);CHKERRQ(ierr);
902   }
903   flg1 = PETSC_FALSE;
904   flg2 = PETSC_FALSE;
905   /* preemptive call to avoid listing this option in options table as unused */
906   ierr = PetscOptionsHasName(PETSC_NULL,"-malloc_dump",&flg1);CHKERRQ(ierr);
907   ierr = PetscOptionsGetBool(PETSC_NULL,"-options_table",&flg2,PETSC_NULL);CHKERRQ(ierr);
908 
909   if (flg2) {
910     if (!rank) {ierr = PetscOptionsView(PETSC_NULL);CHKERRQ(ierr);}
911   }
912 
913   /* to prevent PETSc -options_left from warning */
914   ierr = PetscOptionsHasName(PETSC_NULL,"-nox",&flg1);CHKERRQ(ierr);
915   ierr = PetscOptionsHasName(PETSC_NULL,"-nox_warning",&flg1);CHKERRQ(ierr);
916 
917   if (!PetscOpenMPWorker) { /* worker processes skip this because they do not usually process options */
918     flg3 = PETSC_FALSE; /* default value is required */
919     ierr = PetscOptionsGetBool(PETSC_NULL,"-options_left",&flg3,&flg1);CHKERRQ(ierr);
920     ierr = PetscOptionsAllUsed(&nopt);CHKERRQ(ierr);
921     if (flg3) {
922       if (!flg2) { /* have not yet printed the options */
923 	ierr = PetscOptionsView(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
924       }
925       if (!nopt) {
926 	ierr = PetscPrintf(PETSC_COMM_WORLD,"There are no unused options.\n");CHKERRQ(ierr);
927       } else if (nopt == 1) {
928 	ierr = PetscPrintf(PETSC_COMM_WORLD,"There is one unused database option. It is:\n");CHKERRQ(ierr);
929       } else {
930 	ierr = PetscPrintf(PETSC_COMM_WORLD,"There are %d unused database options. They are:\n",nopt);CHKERRQ(ierr);
931       }
932     }
933 #if defined(PETSC_USE_DEBUG)
934     if (nopt && !flg3 && !flg1) {
935       ierr = PetscPrintf(PETSC_COMM_WORLD,"WARNING! There are options you set that were not used!\n");CHKERRQ(ierr);
936       ierr = PetscPrintf(PETSC_COMM_WORLD,"WARNING! could be spelling mistake, etc!\n");CHKERRQ(ierr);
937       ierr = PetscOptionsLeft();CHKERRQ(ierr);
938     } else if (nopt && flg3) {
939 #else
940     if (nopt && flg3) {
941 #endif
942       ierr = PetscOptionsLeft();CHKERRQ(ierr);
943     }
944   }
945 
946   /*
947      Free all objects registered with PetscObjectRegisterDestroy() such as PETSC_VIEWER_XXX_().
948   */
949   ierr = PetscObjectRegisterDestroyAll();CHKERRQ(ierr);
950 
951   /*
952        Free all objects the user forgot to free
953    */
954   for (i=0; i<PetscObjectsMaxCounts; i++) {
955     if (PetscObjects[i]) {
956       ierr = PetscObjectDestroy(PetscObjects[i]);CHKERRQ(ierr);
957     }
958   }
959 
960 
961 #if defined(PETSC_USE_LOG)
962   ierr = PetscLogDestroy();CHKERRQ(ierr);
963 #endif
964 
965   /*
966        Free all the registered create functions, such as KSPList, VecList, SNESList, etc
967   */
968   ierr = PetscFListDestroyAll();CHKERRQ(ierr);
969 
970   /*
971      Destroy any packages that registered a finalize
972   */
973   ierr = PetscRegisterFinalizeAll();CHKERRQ(ierr);
974 
975   /*
976      Destroy all the function registration lists created
977   */
978   ierr = PetscFinalize_DynamicLibraries();CHKERRQ(ierr);
979 
980   if (petsc_history) {
981     ierr = PetscCloseHistoryFile(&petsc_history);CHKERRQ(ierr);
982     petsc_history = 0;
983   }
984 
985   ierr = PetscInfoAllow(PETSC_FALSE,PETSC_NULL);CHKERRQ(ierr);
986 
987   {
988     char fname[PETSC_MAX_PATH_LEN];
989     FILE *fd;
990     int  err;
991 
992     fname[0] = 0;
993     ierr = PetscOptionsGetString(PETSC_NULL,"-malloc_dump",fname,250,&flg1);CHKERRQ(ierr);
994     if (flg1 && fname[0]) {
995       char sname[PETSC_MAX_PATH_LEN];
996 
997       sprintf(sname,"%s_%d",fname,rank);
998       fd   = fopen(sname,"w"); if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open log file: %s",sname);
999       ierr = PetscMallocDump(fd);CHKERRQ(ierr);
1000       err = fclose(fd);
1001       if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
1002     } else if (flg1) {
1003       MPI_Comm local_comm;
1004 
1005       ierr = MPI_Comm_dup(MPI_COMM_WORLD,&local_comm);CHKERRQ(ierr);
1006       ierr = PetscSequentialPhaseBegin_Private(local_comm,1);CHKERRQ(ierr);
1007         ierr = PetscMallocDump(stdout);CHKERRQ(ierr);
1008       ierr = PetscSequentialPhaseEnd_Private(local_comm,1);CHKERRQ(ierr);
1009       ierr = MPI_Comm_free(&local_comm);CHKERRQ(ierr);
1010     }
1011   }
1012   {
1013     char fname[PETSC_MAX_PATH_LEN];
1014     FILE *fd;
1015 
1016     fname[0] = 0;
1017     ierr = PetscOptionsGetString(PETSC_NULL,"-malloc_log",fname,250,&flg1);CHKERRQ(ierr);
1018     if (flg1 && fname[0]) {
1019       char sname[PETSC_MAX_PATH_LEN];
1020       int  err;
1021 
1022       sprintf(sname,"%s_%d",fname,rank);
1023       fd   = fopen(sname,"w"); if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open log file: %s",sname);
1024       ierr = PetscMallocDumpLog(fd);CHKERRQ(ierr);
1025       err = fclose(fd);
1026       if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
1027     } else if (flg1) {
1028       ierr = PetscMallocDumpLog(stdout);CHKERRQ(ierr);
1029     }
1030   }
1031   /* Can be destroyed only after all the options are used */
1032   ierr = PetscOptionsDestroy();CHKERRQ(ierr);
1033 
1034   PetscGlobalArgc = 0;
1035   PetscGlobalArgs = 0;
1036 
1037 #if defined(PETSC_USE_COMPLEX)
1038 #if !defined(PETSC_HAVE_MPI_C_DOUBLE_COMPLEX)
1039   ierr = MPI_Op_free(&MPIU_SUM);CHKERRQ(ierr);
1040   ierr = MPI_Type_free(&MPI_C_DOUBLE_COMPLEX);CHKERRQ(ierr);
1041   ierr = MPI_Type_free(&MPI_C_COMPLEX);CHKERRQ(ierr);
1042 #endif
1043 #endif
1044   ierr = MPI_Type_free(&MPIU_2SCALAR);CHKERRQ(ierr);
1045   ierr = MPI_Type_free(&MPIU_2INT);CHKERRQ(ierr);
1046   ierr = MPI_Op_free(&PetscMaxSum_Op);CHKERRQ(ierr);
1047   ierr = MPI_Op_free(&PetscADMax_Op);CHKERRQ(ierr);
1048   ierr = MPI_Op_free(&PetscADMin_Op);CHKERRQ(ierr);
1049 
1050   ierr = MPI_Keyval_free(&Petsc_Counter_keyval);CHKERRQ(ierr);
1051   ierr = MPI_Keyval_free(&Petsc_InnerComm_keyval);CHKERRQ(ierr);
1052   ierr = MPI_Keyval_free(&Petsc_OuterComm_keyval);CHKERRQ(ierr);
1053 
1054   ierr = PetscInfo(0,"PETSc successfully ended!\n");CHKERRQ(ierr);
1055   if (PetscBeganMPI) {
1056 #if defined(PETSC_HAVE_MPI_FINALIZED)
1057     PetscMPIInt flag;
1058     ierr = MPI_Finalized(&flag);CHKERRQ(ierr);
1059     if (flag) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"MPI_Finalize() has already been called, even though MPI_Init() was called by PetscInitialize()");
1060 #endif
1061     ierr = MPI_Finalize();CHKERRQ(ierr);
1062   }
1063 
1064   if (PETSC_ZOPEFD){
1065     if (PETSC_ZOPEFD != PETSC_STDOUT) fprintf(PETSC_ZOPEFD, "<<<end>>>");
1066     else fprintf(PETSC_STDOUT, "<<<end>>>");
1067   }
1068 
1069 #if defined(PETSC_HAVE_CUDA)
1070   cublasShutdown();
1071 #endif
1072 /*
1073 
1074      Note: In certain cases PETSC_COMM_WORLD is never MPI_Comm_free()ed because
1075    the communicator has some outstanding requests on it. Specifically if the
1076    flag PETSC_HAVE_BROKEN_REQUEST_FREE is set (for IBM MPI implementation). See
1077    src/vec/utils/vpscat.c. Due to this the memory allocated in PetscCommDuplicate()
1078    is never freed as it should be. Thus one may obtain messages of the form
1079    [ 1] 8 bytes PetscCommDuplicate() line 645 in src/sys/mpiu.c indicating the
1080    memory was not freed.
1081 
1082 */
1083   ierr = PetscMallocClear();CHKERRQ(ierr);
1084   PetscInitializeCalled = PETSC_FALSE;
1085   PetscFinalizeCalled   = PETSC_TRUE;
1086   PetscFunctionReturn(ierr);
1087 }
1088 
1089