xref: /petsc/src/sys/objects/pinit.c (revision 10463e74fcdf5dce2bd6884510fe4d3dd14ea3d8)
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 #if defined(PETSC_USE_LOG)
791     char mname[PETSC_MAX_PATH_LEN];
792 #endif
793 
794   PetscFunctionBegin;
795 
796   if (!PetscInitializeCalled) {
797     printf("PetscInitialize() must be called before PetscFinalize()\n");
798     PetscFunctionReturn(PETSC_ERR_ARG_WRONGSTATE);
799   }
800   ierr = PetscInfo(PETSC_NULL,"PetscFinalize() called\n");
801 
802 #if defined(PETSC_HAVE_AMS)
803   ierr = PetscOptionsGetBool(PETSC_NULL,"-options_gui",&flg,PETSC_NULL);CHKERRQ(ierr);
804   if (flg) {
805     ierr = PetscOptionsAMSDestroy();CHKERRQ(ierr);
806   }
807 #endif
808 
809   ierr = PetscOpenMPFinalize();CHKERRQ(ierr);
810 
811   ierr = PetscOptionsGetBool(PETSC_NULL,"-python",&flg1,PETSC_NULL);CHKERRQ(ierr);
812   if (flg1) {ierr = PetscPythonFinalize();CHKERRQ(ierr);}
813 
814   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
815   ierr = PetscOptionsGetBool(PETSC_NULL,"-malloc_info",&flg2,PETSC_NULL);CHKERRQ(ierr);
816   if (!flg2) {
817     flg2 = PETSC_FALSE;
818     ierr = PetscOptionsGetBool(PETSC_NULL,"-memory_info",&flg2,PETSC_NULL);CHKERRQ(ierr);
819   }
820   if (flg2) {
821     ierr = PetscMemoryShowUsage(PETSC_VIEWER_STDOUT_WORLD,"Summary of Memory Usage in PETSc\n");CHKERRQ(ierr);
822   }
823 
824   /*
825      Free all objects registered with PetscObjectRegisterDestroy() such as PETSC_VIEWER_XXX_().
826   */
827   ierr = PetscObjectRegisterDestroyAll();CHKERRQ(ierr);
828 
829   /*
830        Free all the registered create functions, such as KSPList, VecList, SNESList, etc
831   */
832   ierr = PetscFListDestroyAll();CHKERRQ(ierr);
833 
834   /*
835      Destroy any packages that registered a finalize
836   */
837   ierr = PetscRegisterFinalizeAll();CHKERRQ(ierr);
838 
839 
840 #if defined(PETSC_USE_LOG)
841   flg1 = PETSC_FALSE;
842   ierr = PetscOptionsGetBool(PETSC_NULL,"-get_total_flops",&flg1,PETSC_NULL);CHKERRQ(ierr);
843   if (flg1) {
844     PetscLogDouble flops = 0;
845     ierr = MPI_Reduce(&_TotalFlops,&flops,1,MPI_DOUBLE,MPI_SUM,0,PETSC_COMM_WORLD);CHKERRQ(ierr);
846     ierr = PetscPrintf(PETSC_COMM_WORLD,"Total flops over all processors %g\n",flops);CHKERRQ(ierr);
847   }
848 #endif
849 
850 #if defined(PETSC_USE_DEBUG) && !defined(PETSC_USE_PTHREAD)
851   if (PetscStackActive) {
852     ierr = PetscStackDestroy();CHKERRQ(ierr);
853   }
854 #endif
855 
856 #if defined(PETSC_USE_LOG)
857 #if defined(PETSC_HAVE_MPE)
858   mname[0] = 0;
859   ierr = PetscOptionsGetString(PETSC_NULL,"-log_mpe",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr);
860   if (flg1){
861     if (mname[0]) {ierr = PetscLogMPEDump(mname);CHKERRQ(ierr);}
862     else          {ierr = PetscLogMPEDump(0);CHKERRQ(ierr);}
863   }
864 #endif
865   mname[0] = 0;
866   ierr = PetscOptionsGetString(PETSC_NULL,"-log_summary",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr);
867   if (flg1) {
868     PetscViewer viewer;
869     if (mname[0])  {
870       ierr = PetscViewerASCIIOpen(PETSC_COMM_WORLD,mname,&viewer);CHKERRQ(ierr);
871     } else {
872       viewer = PETSC_VIEWER_STDOUT_WORLD;
873     }
874     ierr = PetscLogView(viewer);CHKERRQ(ierr);
875     ierr = PetscViewerDestroy(viewer);CHKERRQ(ierr);
876   }
877 
878   mname[0] = 0;
879   ierr = PetscOptionsGetString(PETSC_NULL,"-log_summary_python",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr);
880   if (flg1) {
881     PetscViewer viewer;
882     if (mname[0])  {
883       ierr = PetscViewerASCIIOpen(PETSC_COMM_WORLD,mname,&viewer);CHKERRQ(ierr);
884     } else {
885       viewer = PETSC_VIEWER_STDOUT_WORLD;
886     }
887     ierr = PetscLogViewPython(viewer);CHKERRQ(ierr);
888     ierr = PetscViewerDestroy(viewer);CHKERRQ(ierr);
889   }
890 
891   ierr = PetscOptionsGetString(PETSC_NULL,"-log_detailed",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr);
892   if (flg1) {
893     if (mname[0])  {ierr = PetscLogPrintDetailed(PETSC_COMM_WORLD,mname);CHKERRQ(ierr);}
894     else           {ierr = PetscLogPrintDetailed(PETSC_COMM_WORLD,0);CHKERRQ(ierr);}
895   }
896 
897   mname[0] = 0;
898   ierr = PetscOptionsGetString(PETSC_NULL,"-log_all",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr);
899   ierr = PetscOptionsGetString(PETSC_NULL,"-log",mname,PETSC_MAX_PATH_LEN,&flg2);CHKERRQ(ierr);
900   if (flg1 || flg2){
901     if (mname[0]) PetscLogDump(mname);
902     else          PetscLogDump(0);
903   }
904   ierr = PetscLogDestroy();CHKERRQ(ierr);
905 #endif
906 
907 
908   flg1 = PETSC_FALSE;
909   ierr = PetscOptionsGetBool(PETSC_NULL,"-no_signal_handler",&flg1,PETSC_NULL);CHKERRQ(ierr);
910   if (!flg1) { ierr = PetscPopSignalHandler();CHKERRQ(ierr);}
911   flg1 = PETSC_FALSE;
912   ierr = PetscOptionsGetBool(PETSC_NULL,"-mpidump",&flg1,PETSC_NULL);CHKERRQ(ierr);
913   if (flg1) {
914     ierr = PetscMPIDump(stdout);CHKERRQ(ierr);
915   }
916   flg1 = PETSC_FALSE;
917   flg2 = PETSC_FALSE;
918   /* preemptive call to avoid listing this option in options table as unused */
919   ierr = PetscOptionsHasName(PETSC_NULL,"-malloc_dump",&flg1);CHKERRQ(ierr);
920   ierr = PetscOptionsGetBool(PETSC_NULL,"-options_table",&flg2,PETSC_NULL);CHKERRQ(ierr);
921 
922   if (flg2) {
923     if (!rank) {ierr = PetscOptionsView(PETSC_NULL);CHKERRQ(ierr);}
924   }
925 
926   /* to prevent PETSc -options_left from warning */
927   ierr = PetscOptionsHasName(PETSC_NULL,"-nox",&flg1);CHKERRQ(ierr);
928   ierr = PetscOptionsHasName(PETSC_NULL,"-nox_warning",&flg1);CHKERRQ(ierr);
929 
930   if (!PetscOpenMPWorker) { /* worker processes skip this because they do not usually process options */
931     flg3 = PETSC_FALSE; /* default value is required */
932     ierr = PetscOptionsGetBool(PETSC_NULL,"-options_left",&flg3,&flg1);CHKERRQ(ierr);
933     ierr = PetscOptionsAllUsed(&nopt);CHKERRQ(ierr);
934     if (flg3) {
935       if (!flg2) { /* have not yet printed the options */
936 	ierr = PetscOptionsView(PETSC_NULL);CHKERRQ(ierr);
937       }
938       if (!nopt) {
939 	ierr = PetscPrintf(PETSC_COMM_WORLD,"There are no unused options.\n");CHKERRQ(ierr);
940       } else if (nopt == 1) {
941 	ierr = PetscPrintf(PETSC_COMM_WORLD,"There is one unused database option. It is:\n");CHKERRQ(ierr);
942       } else {
943 	ierr = PetscPrintf(PETSC_COMM_WORLD,"There are %d unused database options. They are:\n",nopt);CHKERRQ(ierr);
944       }
945     }
946 #if defined(PETSC_USE_DEBUG)
947     if (nopt && !flg3 && !flg1) {
948       ierr = PetscPrintf(PETSC_COMM_WORLD,"WARNING! There are options you set that were not used!\n");CHKERRQ(ierr);
949       ierr = PetscPrintf(PETSC_COMM_WORLD,"WARNING! could be spelling mistake, etc!\n");CHKERRQ(ierr);
950       ierr = PetscOptionsLeft();CHKERRQ(ierr);
951     } else if (nopt && flg3) {
952 #else
953     if (nopt && flg3) {
954 #endif
955       ierr = PetscOptionsLeft();CHKERRQ(ierr);
956     }
957   }
958 
959   /*
960      Destroy all the function registration lists created
961   */
962   ierr = PetscFinalize_DynamicLibraries();CHKERRQ(ierr);
963 
964   if (petsc_history) {
965     ierr = PetscCloseHistoryFile(&petsc_history);CHKERRQ(ierr);
966     petsc_history = 0;
967   }
968 
969   ierr = PetscInfoAllow(PETSC_FALSE,PETSC_NULL);CHKERRQ(ierr);
970 
971   {
972     char fname[PETSC_MAX_PATH_LEN];
973     FILE *fd;
974     int  err;
975 
976     fname[0] = 0;
977     ierr = PetscOptionsGetString(PETSC_NULL,"-malloc_dump",fname,250,&flg1);CHKERRQ(ierr);
978     if (flg1 && fname[0]) {
979       char sname[PETSC_MAX_PATH_LEN];
980 
981       sprintf(sname,"%s_%d",fname,rank);
982       fd   = fopen(sname,"w"); if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open log file: %s",sname);
983       ierr = PetscMallocDump(fd);CHKERRQ(ierr);
984       err = fclose(fd);
985       if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
986     } else if (flg1) {
987       MPI_Comm local_comm;
988 
989       ierr = MPI_Comm_dup(MPI_COMM_WORLD,&local_comm);CHKERRQ(ierr);
990       ierr = PetscSequentialPhaseBegin_Private(local_comm,1);CHKERRQ(ierr);
991         ierr = PetscMallocDump(stdout);CHKERRQ(ierr);
992       ierr = PetscSequentialPhaseEnd_Private(local_comm,1);CHKERRQ(ierr);
993       ierr = MPI_Comm_free(&local_comm);CHKERRQ(ierr);
994     }
995   }
996   {
997     char fname[PETSC_MAX_PATH_LEN];
998     FILE *fd;
999 
1000     fname[0] = 0;
1001     ierr = PetscOptionsGetString(PETSC_NULL,"-malloc_log",fname,250,&flg1);CHKERRQ(ierr);
1002     if (flg1 && fname[0]) {
1003       char sname[PETSC_MAX_PATH_LEN];
1004       int  err;
1005 
1006       sprintf(sname,"%s_%d",fname,rank);
1007       fd   = fopen(sname,"w"); if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open log file: %s",sname);
1008       ierr = PetscMallocDumpLog(fd);CHKERRQ(ierr);
1009       err = fclose(fd);
1010       if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
1011     } else if (flg1) {
1012       ierr = PetscMallocDumpLog(stdout);CHKERRQ(ierr);
1013     }
1014   }
1015   /* Can be destroyed only after all the options are used */
1016   ierr = PetscOptionsDestroy();CHKERRQ(ierr);
1017 
1018   PetscGlobalArgc = 0;
1019   PetscGlobalArgs = 0;
1020 
1021 #if defined(PETSC_USE_COMPLEX)
1022 #if !defined(PETSC_HAVE_MPI_C_DOUBLE_COMPLEX)
1023   ierr = MPI_Op_free(&MPIU_SUM);CHKERRQ(ierr);
1024   ierr = MPI_Type_free(&MPI_C_DOUBLE_COMPLEX);CHKERRQ(ierr);
1025   ierr = MPI_Type_free(&MPI_C_COMPLEX);CHKERRQ(ierr);
1026 #endif
1027 #endif
1028   ierr = MPI_Type_free(&MPIU_2SCALAR);CHKERRQ(ierr);
1029   ierr = MPI_Type_free(&MPIU_2INT);CHKERRQ(ierr);
1030   ierr = MPI_Op_free(&PetscMaxSum_Op);CHKERRQ(ierr);
1031   ierr = MPI_Op_free(&PetscADMax_Op);CHKERRQ(ierr);
1032   ierr = MPI_Op_free(&PetscADMin_Op);CHKERRQ(ierr);
1033 
1034   ierr = MPI_Keyval_free(&Petsc_Counter_keyval);CHKERRQ(ierr);
1035   ierr = MPI_Keyval_free(&Petsc_InnerComm_keyval);CHKERRQ(ierr);
1036   ierr = MPI_Keyval_free(&Petsc_OuterComm_keyval);CHKERRQ(ierr);
1037 
1038   ierr = PetscInfo(0,"PETSc successfully ended!\n");CHKERRQ(ierr);
1039   if (PetscBeganMPI) {
1040 #if defined(PETSC_HAVE_MPI_FINALIZED)
1041     PetscMPIInt flag;
1042     ierr = MPI_Finalized(&flag);CHKERRQ(ierr);
1043     if (flag) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"MPI_Finalize() has already been called, even though MPI_Init() was called by PetscInitialize()");
1044 #endif
1045     ierr = MPI_Finalize();CHKERRQ(ierr);
1046   }
1047 
1048   if (PETSC_ZOPEFD){
1049     if (PETSC_ZOPEFD != PETSC_STDOUT) fprintf(PETSC_ZOPEFD, "<<<end>>>");
1050     else fprintf(PETSC_STDOUT, "<<<end>>>");
1051   }
1052 
1053 #if defined(PETSC_HAVE_CUDA)
1054   cublasShutdown();
1055 #endif
1056 /*
1057 
1058      Note: In certain cases PETSC_COMM_WORLD is never MPI_Comm_free()ed because
1059    the communicator has some outstanding requests on it. Specifically if the
1060    flag PETSC_HAVE_BROKEN_REQUEST_FREE is set (for IBM MPI implementation). See
1061    src/vec/utils/vpscat.c. Due to this the memory allocated in PetscCommDuplicate()
1062    is never freed as it should be. Thus one may obtain messages of the form
1063    [ 1] 8 bytes PetscCommDuplicate() line 645 in src/sys/mpiu.c indicating the
1064    memory was not freed.
1065 
1066 */
1067   ierr = PetscMallocClear();CHKERRQ(ierr);
1068   PetscInitializeCalled = PETSC_FALSE;
1069   PetscFinalizeCalled   = PETSC_TRUE;
1070   PetscFunctionReturn(ierr);
1071 }
1072 
1073