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