xref: /petsc/src/sys/objects/init.c (revision 967582eba84cc53dc1fbf6b54d6aa49b7d83bae6)
1 /*
2 
3    This file defines part of the initialization of PETSc
4 
5   This file uses regular malloc and free because it cannot known
6   what malloc is being used until it has already processed the input.
7 */
8 
9 #include <petscsys.h>        /*I  "petscsys.h"   I*/
10 #include <petsc/private/petscimpl.h>
11 #include <petscvalgrind.h>
12 #include <petscviewer.h>
13 #if defined(PETSC_USE_LOG)
14 PETSC_INTERN PetscErrorCode PetscLogInitialize(void);
15 #endif
16 
17 #if defined(PETSC_HAVE_SYS_SYSINFO_H)
18 #include <sys/sysinfo.h>
19 #endif
20 #if defined(PETSC_HAVE_UNISTD_H)
21 #include <unistd.h>
22 #endif
23 #if defined(PETSC_HAVE_CUDA)
24 #include <cuda_runtime.h>
25 #include <petsccublas.h>
26 #if defined(PETSC_HAVE_OMPI_MAJOR_VERSION)
27 #include "mpi-ext.h" /* Needed for OpenMPI CUDA-aware check */
28 #endif
29 #endif
30 
31 #if defined(PETSC_HAVE_VIENNACL)
32 PETSC_EXTERN PetscErrorCode PetscViennaCLInit();
33 #endif
34 
35 /* ------------------------Nasty global variables -------------------------------*/
36 /*
37      Indicates if PETSc started up MPI, or it was
38    already started before PETSc was initialized.
39 */
40 PetscBool   PetscBeganMPI         = PETSC_FALSE;
41 PetscBool   PetscInitializeCalled = PETSC_FALSE;
42 PetscBool   PetscFinalizeCalled   = PETSC_FALSE;
43 PetscBool   PetscCUDAInitialized  = PETSC_FALSE;
44 
45 PetscMPIInt PetscGlobalRank       = -1;
46 PetscMPIInt PetscGlobalSize       = -1;
47 
48 PetscBool   use_gpu_aware_mpi     = PETSC_TRUE;
49 
50 #if defined(PETSC_HAVE_COMPLEX)
51 #if defined(PETSC_COMPLEX_INSTANTIATE)
52 template <> class std::complex<double>; /* instantiate complex template class */
53 #endif
54 #if !defined(PETSC_HAVE_MPI_C_DOUBLE_COMPLEX)
55 MPI_Datatype MPIU_C_DOUBLE_COMPLEX;
56 MPI_Datatype MPIU_C_COMPLEX;
57 #endif
58 
59 /*MC
60    PETSC_i - the imaginary number i
61 
62    Synopsis:
63    #include <petscsys.h>
64    PetscComplex PETSC_i;
65 
66    Level: beginner
67 
68    Note:
69    Complex numbers are automatically available if PETSc located a working complex implementation
70 
71 .seealso: PetscRealPart(), PetscImaginaryPart(), PetscRealPartComplex(), PetscImaginaryPartComplex()
72 M*/
73 PetscComplex PETSC_i;
74 #endif
75 #if defined(PETSC_USE_REAL___FLOAT128)
76 MPI_Datatype MPIU___FLOAT128 = 0;
77 #if defined(PETSC_HAVE_COMPLEX)
78 MPI_Datatype MPIU___COMPLEX128 = 0;
79 #endif
80 #elif defined(PETSC_USE_REAL___FP16)
81 MPI_Datatype MPIU___FP16 = 0;
82 #endif
83 MPI_Datatype MPIU_2SCALAR = 0;
84 #if defined(PETSC_USE_64BIT_INDICES)
85 MPI_Datatype MPIU_2INT = 0;
86 #endif
87 MPI_Datatype MPIU_BOOL;
88 MPI_Datatype MPIU_ENUM;
89 MPI_Datatype MPIU_FORTRANADDR;
90 MPI_Datatype MPIU_SIZE_T;
91 
92 /*
93        Function that is called to display all error messages
94 */
95 PetscErrorCode (*PetscErrorPrintf)(const char [],...)          = PetscErrorPrintfDefault;
96 PetscErrorCode (*PetscHelpPrintf)(MPI_Comm,const char [],...)  = PetscHelpPrintfDefault;
97 PetscErrorCode (*PetscVFPrintf)(FILE*,const char[],va_list)    = PetscVFPrintfDefault;
98 /*
99   This is needed to turn on/off GPU synchronization
100 */
101 PetscBool PetscViennaCLSynchronize = PETSC_FALSE;
102 PetscBool PetscCUDASynchronize = PETSC_FALSE;
103 
104 /* ------------------------------------------------------------------------------*/
105 /*
106    Optional file where all PETSc output from various prints is saved
107 */
108 PETSC_INTERN FILE *petsc_history;
109 FILE *petsc_history = NULL;
110 
111 PetscErrorCode  PetscOpenHistoryFile(const char filename[],FILE **fd)
112 {
113   PetscErrorCode ierr;
114   PetscMPIInt    rank,size;
115   char           pfile[PETSC_MAX_PATH_LEN],pname[PETSC_MAX_PATH_LEN],fname[PETSC_MAX_PATH_LEN],date[64];
116   char           version[256];
117 
118   PetscFunctionBegin;
119   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
120   if (!rank) {
121     char        arch[10];
122     int         err;
123 
124     ierr = PetscGetArchType(arch,10);CHKERRQ(ierr);
125     ierr = PetscGetDate(date,64);CHKERRQ(ierr);
126     ierr = PetscGetVersion(version,256);CHKERRQ(ierr);
127     ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr);
128     if (filename) {
129       ierr = PetscFixFilename(filename,fname);CHKERRQ(ierr);
130     } else {
131       ierr = PetscGetHomeDirectory(pfile,240);CHKERRQ(ierr);
132       ierr = PetscStrcat(pfile,"/.petschistory");CHKERRQ(ierr);
133       ierr = PetscFixFilename(pfile,fname);CHKERRQ(ierr);
134     }
135 
136     *fd = fopen(fname,"a");
137     if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file: %s",fname);
138 
139     ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"----------------------------------------\n");CHKERRQ(ierr);
140     ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"%s %s\n",version,date);CHKERRQ(ierr);
141     ierr = PetscGetProgramName(pname,PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
142     ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"%s on a %s, %d proc. with options:\n",pname,arch,size);CHKERRQ(ierr);
143     ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"----------------------------------------\n");CHKERRQ(ierr);
144 
145     err = fflush(*fd);
146     if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
147   }
148   PetscFunctionReturn(0);
149 }
150 
151 PETSC_INTERN PetscErrorCode PetscCloseHistoryFile(FILE **fd)
152 {
153   PetscErrorCode ierr;
154   PetscMPIInt    rank;
155   char           date[64];
156   int            err;
157 
158   PetscFunctionBegin;
159   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
160   if (!rank) {
161     ierr = PetscGetDate(date,64);CHKERRQ(ierr);
162     ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"----------------------------------------\n");CHKERRQ(ierr);
163     ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"Finished at %s\n",date);CHKERRQ(ierr);
164     ierr = PetscFPrintf(PETSC_COMM_SELF,*fd,"----------------------------------------\n");CHKERRQ(ierr);
165     err  = fflush(*fd);
166     if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
167     err = fclose(*fd);
168     if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
169   }
170   PetscFunctionReturn(0);
171 }
172 
173 /* ------------------------------------------------------------------------------*/
174 
175 /*
176    This is ugly and probably belongs somewhere else, but I want to
177   be able to put a true MPI abort error handler with command line args.
178 
179     This is so MPI errors in the debugger will leave all the stack
180   frames. The default MP_Abort() cleans up and exits thus providing no useful information
181   in the debugger hence we call abort() instead of MPI_Abort().
182 */
183 
184 void Petsc_MPI_AbortOnError(MPI_Comm *comm,PetscMPIInt *flag,...)
185 {
186   PetscFunctionBegin;
187   (*PetscErrorPrintf)("MPI error %d\n",*flag);
188   abort();
189 }
190 
191 void Petsc_MPI_DebuggerOnError(MPI_Comm *comm,PetscMPIInt *flag,...)
192 {
193   PetscErrorCode ierr;
194 
195   PetscFunctionBegin;
196   (*PetscErrorPrintf)("MPI error %d\n",*flag);
197   ierr = PetscAttachDebugger();
198   if (ierr) PETSCABORT(*comm,*flag); /* hopeless so get out */
199 }
200 
201 #if defined(PETSC_HAVE_CUDA)
202 /*@C
203      PetscCUDAInitialize - Initializes the CUDA device and cuBLAS on the device
204 
205      Logically collective
206 
207   Input Parameter:
208   comm - the MPI communicator that will utilize the CUDA devices
209 
210   Options Database:
211 +  -cuda_initialize <default yes,no> - do the initialization in PetscInitialize(). If -cuda_initialize no is used then the default initialization is done automatically
212                                when the first CUDA call is made unless you call PetscCUDAInitialize() before any CUDA operations are performed
213 .  -cuda_view - view information about the CUDA devices
214 .  -cuda_synchronize - wait at the end of asynchronize CUDA calls so that their time gets credited to the current event; default with -log_view
215 .  -cuda_set_device <gpu> - integer number of the device
216 -  -use_gpu_aware_mpi     - Assume the MPI is GPU-aware when communicating data on GPU
217 
218   Level: beginner
219 
220   Notes:
221    Initializing cuBLAS takes about 1/2 second there it is done by default in PetscInitialize() before logging begins
222 
223 @*/
224 PetscErrorCode PetscCUDAInitialize(MPI_Comm comm)
225 {
226   PetscErrorCode        ierr;
227   PetscInt              deviceOpt = 0;
228   PetscBool             cuda_view_flag = PETSC_FALSE,flg;
229   struct cudaDeviceProp prop;
230   int                   devCount,device,devicecnt;
231   cudaError_t           err = cudaSuccess;
232   PetscMPIInt           rank,size;
233 
234   PetscFunctionBegin;
235   /*
236      If collecting logging information, by default, wait for GPU to complete its operations
237      before returning to the CPU in order to get accurate timings of each event
238   */
239   ierr = PetscOptionsHasName(NULL,NULL,"-log_summary",&PetscCUDASynchronize);CHKERRQ(ierr);
240   if (!PetscCUDASynchronize) {
241     ierr = PetscOptionsHasName(NULL,NULL,"-log_view",&PetscCUDASynchronize);CHKERRQ(ierr);
242   }
243 
244   ierr = PetscOptionsBegin(comm,NULL,"CUDA options","Sys");CHKERRQ(ierr);
245   ierr = PetscOptionsInt("-cuda_set_device","Set all MPI ranks to use the specified CUDA device",NULL,deviceOpt,&deviceOpt,&flg);CHKERRQ(ierr);
246   device = (int)deviceOpt;
247   ierr = PetscOptionsBool("-cuda_synchronize","Wait for the GPU to complete operations before returning to the CPU",NULL,PetscCUDASynchronize,&PetscCUDASynchronize,NULL);CHKERRQ(ierr);
248   ierr = PetscOptionsDeprecated("-cuda_show_devices","-cuda_view","3.12",NULL);CHKERRQ(ierr);
249   ierr = PetscOptionsName("-cuda_view","Display CUDA device information and assignments",NULL,&cuda_view_flag);CHKERRQ(ierr);
250   ierr = PetscOptionsEnd();CHKERRQ(ierr);
251   if (!PetscCUDAInitialized) {
252     ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
253 
254     if (size>1 && !flg) {
255       /* check to see if we force multiple ranks to hit the same GPU */
256       /* we're not using the same GPU on multiple MPI threads. So try to allocated different   GPUs to different processes */
257 
258       /* First get the device count */
259       err   = cudaGetDeviceCount(&devCount);
260       if (err != cudaSuccess) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SYS,"error in cudaGetDeviceCount %s",cudaGetErrorString(err));
261 
262       /* next determine the rank and then set the device via a mod */
263       ierr   = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
264       device = rank % devCount;
265     }
266     err = cudaSetDevice(device);
267     if (err != cudaSuccess) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SYS,"error in cudaSetDevice %s",cudaGetErrorString(err));
268 
269     /* set the device flags so that it can map host memory */
270     err = cudaSetDeviceFlags(cudaDeviceMapHost);
271     if (err != cudaSuccess) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SYS,"error in cudaSetDeviceFlags %s",cudaGetErrorString(err));
272 
273     ierr = PetscCUBLASInitializeHandle();CHKERRQ(ierr);
274     ierr = PetscCUSOLVERDnInitializeHandle();CHKERRQ(ierr);
275     PetscCUDAInitialized = PETSC_TRUE;
276   }
277   if (cuda_view_flag) {
278     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
279     err  = cudaGetDeviceCount(&devCount);
280     if (err != cudaSuccess) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SYS,"error in cudaGetDeviceCount %s",cudaGetErrorString(err));
281     for (devicecnt = 0; devicecnt < devCount; ++devicecnt) {
282       err = cudaGetDeviceProperties(&prop,devicecnt);
283       if (err != cudaSuccess) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SYS,"error in cudaGetDeviceProperties %s",cudaGetErrorString(err));
284       ierr = PetscPrintf(comm, "CUDA device %d: %s\n", devicecnt, prop.name);CHKERRQ(ierr);
285     }
286     ierr = PetscSynchronizedPrintf(comm,"[%d] Using CUDA device %d.\n",rank,device);CHKERRQ(ierr);
287     ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr);
288   }
289   PetscFunctionReturn(0);
290 }
291 #endif
292 
293 /*@C
294    PetscEnd - Calls PetscFinalize() and then ends the program. This is useful if one
295      wishes a clean exit somewhere deep in the program.
296 
297    Collective on PETSC_COMM_WORLD
298 
299    Options Database Keys are the same as for PetscFinalize()
300 
301    Level: advanced
302 
303    Note:
304    See PetscInitialize() for more general runtime options.
305 
306 .seealso: PetscInitialize(), PetscOptionsView(), PetscMallocDump(), PetscMPIDump(), PetscFinalize()
307 @*/
308 PetscErrorCode  PetscEnd(void)
309 {
310   PetscFunctionBegin;
311   PetscFinalize();
312   exit(0);
313   return 0;
314 }
315 
316 PetscBool PetscOptionsPublish = PETSC_FALSE;
317 PETSC_INTERN PetscErrorCode PetscSetUseHBWMalloc_Private(void);
318 PETSC_INTERN PetscBool      petscsetmallocvisited;
319 static       char           emacsmachinename[256];
320 
321 PetscErrorCode (*PetscExternalVersionFunction)(MPI_Comm) = NULL;
322 PetscErrorCode (*PetscExternalHelpFunction)(MPI_Comm)    = NULL;
323 
324 /*@C
325    PetscSetHelpVersionFunctions - Sets functions that print help and version information
326    before the PETSc help and version information is printed. Must call BEFORE PetscInitialize().
327    This routine enables a "higher-level" package that uses PETSc to print its messages first.
328 
329    Input Parameter:
330 +  help - the help function (may be NULL)
331 -  version - the version function (may be NULL)
332 
333    Level: developer
334 
335 @*/
336 PetscErrorCode  PetscSetHelpVersionFunctions(PetscErrorCode (*help)(MPI_Comm),PetscErrorCode (*version)(MPI_Comm))
337 {
338   PetscFunctionBegin;
339   PetscExternalHelpFunction    = help;
340   PetscExternalVersionFunction = version;
341   PetscFunctionReturn(0);
342 }
343 
344 #if defined(PETSC_USE_LOG)
345 PETSC_INTERN PetscBool   PetscObjectsLog;
346 #endif
347 
348 void PetscMPI_Comm_eh(MPI_Comm *comm, PetscMPIInt *err, ...)
349 {
350   if (PetscUnlikely(*err)) {
351     PetscMPIInt len;
352     char        errstring[MPI_MAX_ERROR_STRING];
353 
354     MPI_Error_string(*err,errstring,&len);
355     PetscError(MPI_COMM_SELF,__LINE__,PETSC_FUNCTION_NAME,__FILE__,PETSC_MPI_ERROR_CODE,PETSC_ERROR_INITIAL,"Internal error in MPI: %s",errstring);
356   }
357   return;
358 }
359 
360 PETSC_INTERN PetscErrorCode  PetscOptionsCheckInitial_Private(void)
361 {
362   char              string[64];
363   MPI_Comm          comm = PETSC_COMM_WORLD;
364   PetscBool         flg1 = PETSC_FALSE,flg2 = PETSC_FALSE,flg3 = PETSC_FALSE,flag;
365   PetscErrorCode    ierr;
366   PetscReal         si;
367   PetscInt          intensity;
368   int               i;
369   PetscMPIInt       rank;
370   char              version[256],helpoptions[256];
371 #if defined(PETSC_USE_LOG)
372   char              mname[PETSC_MAX_PATH_LEN];
373   PetscViewerFormat format;
374   PetscBool         flg4 = PETSC_FALSE;
375 #endif
376 #if defined(PETSC_HAVE_CUDA)
377   PetscBool         initCUDA = PETSC_TRUE,mpi_gpu_awareness;
378 #endif
379 
380   PetscFunctionBegin;
381   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
382 
383 #if !defined(PETSC_HAVE_THREADSAFETY)
384   if (!(PETSC_RUNNING_ON_VALGRIND)) {
385     /*
386       Setup the memory management; support for tracing malloc() usage
387     */
388     PetscBool         mdebug = PETSC_FALSE, eachcall = PETSC_FALSE, initializenan = PETSC_FALSE, mlog = PETSC_FALSE;
389 
390 #if defined(PETSC_USE_DEBUG)
391     mdebug        = PETSC_TRUE;
392     initializenan = PETSC_TRUE;
393     ierr   = PetscOptionsHasName(NULL,NULL,"-malloc_test",&flg1);CHKERRQ(ierr);
394 #else
395     /* don't warn about unused option */
396     ierr = PetscOptionsHasName(NULL,NULL,"-malloc_test",&flg1);CHKERRQ(ierr);
397     flg1 = PETSC_FALSE;
398 #endif
399     ierr = PetscOptionsGetBool(NULL,NULL,"-malloc_debug",&flg2,&flg3);CHKERRQ(ierr);
400     if (flg1 || flg2) {
401       mdebug        = PETSC_TRUE;
402       eachcall      = PETSC_TRUE;
403       initializenan = PETSC_TRUE;
404     } else if (flg3 && !flg2) {
405       mdebug        = PETSC_FALSE;
406       eachcall      = PETSC_FALSE;
407       initializenan = PETSC_FALSE;
408     }
409 
410     ierr = PetscOptionsHasName(NULL,NULL,"-malloc_view",&mlog);CHKERRQ(ierr);
411     if (mlog) {
412       mdebug = PETSC_TRUE;
413     }
414     /* the next line is deprecated */
415     ierr = PetscOptionsGetBool(NULL,NULL,"-malloc",&mdebug,NULL);CHKERRQ(ierr);
416     ierr = PetscOptionsGetBool(NULL,NULL,"-malloc_dump",&mdebug,NULL);CHKERRQ(ierr);
417     ierr = PetscOptionsGetBool(NULL,NULL,"-log_view_memory",&mdebug,NULL);CHKERRQ(ierr);
418     if (mdebug) {
419       ierr = PetscMallocSetDebug(eachcall,initializenan);CHKERRQ(ierr);
420     }
421     if (mlog) {
422       PetscReal logthreshold = 0;
423       ierr = PetscOptionsGetReal(NULL,NULL,"-malloc_view_threshold",&logthreshold,NULL);CHKERRQ(ierr);
424       ierr = PetscMallocViewSet(logthreshold);CHKERRQ(ierr);
425     }
426 #if defined(PETSC_USE_LOG)
427     ierr = PetscOptionsGetBool(NULL,NULL,"-log_view_memory",&PetscLogMemory,NULL);CHKERRQ(ierr);
428 #endif
429   }
430 
431   ierr = PetscOptionsGetBool(NULL,NULL,"-malloc_coalesce",&flg1,&flg2);CHKERRQ(ierr);
432   if (flg2) {ierr = PetscMallocSetCoalesce(flg1);CHKERRQ(ierr);}
433   flg1 = PETSC_FALSE;
434   ierr = PetscOptionsGetBool(NULL,NULL,"-malloc_hbw",&flg1,NULL);CHKERRQ(ierr);
435   /* ignore this option if malloc is already set */
436   if (flg1 && !petscsetmallocvisited) {ierr = PetscSetUseHBWMalloc_Private();CHKERRQ(ierr);}
437 
438   flg1 = PETSC_FALSE;
439   ierr = PetscOptionsGetBool(NULL,NULL,"-malloc_info",&flg1,NULL);CHKERRQ(ierr);
440   if (!flg1) {
441     flg1 = PETSC_FALSE;
442     ierr = PetscOptionsGetBool(NULL,NULL,"-memory_view",&flg1,NULL);CHKERRQ(ierr);
443   }
444   if (flg1) {
445     ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr);
446   }
447 #endif
448 
449 #if defined(PETSC_USE_LOG)
450   ierr = PetscOptionsHasName(NULL,NULL,"-objects_dump",&PetscObjectsLog);CHKERRQ(ierr);
451 #endif
452 
453   /*
454       Set the display variable for graphics
455   */
456   ierr = PetscSetDisplay();CHKERRQ(ierr);
457 
458   /*
459       Print the PETSc version information
460   */
461   ierr = PetscOptionsHasName(NULL,NULL,"-v",&flg1);CHKERRQ(ierr);
462   ierr = PetscOptionsHasName(NULL,NULL,"-version",&flg2);CHKERRQ(ierr);
463   ierr = PetscOptionsHasHelp(NULL,&flg3);CHKERRQ(ierr);
464   if (flg1 || flg2 || flg3) {
465 
466     /*
467        Print "higher-level" package version message
468     */
469     if (PetscExternalVersionFunction) {
470       ierr = (*PetscExternalVersionFunction)(comm);CHKERRQ(ierr);
471     }
472 
473     ierr = PetscGetVersion(version,256);CHKERRQ(ierr);
474     ierr = (*PetscHelpPrintf)(comm,"%s\n",version);CHKERRQ(ierr);
475     ierr = (*PetscHelpPrintf)(comm,"%s",PETSC_AUTHOR_INFO);CHKERRQ(ierr);
476     ierr = (*PetscHelpPrintf)(comm,"See docs/changes/index.html for recent updates.\n");CHKERRQ(ierr);
477     ierr = (*PetscHelpPrintf)(comm,"See docs/faq.html for problems.\n");CHKERRQ(ierr);
478     ierr = (*PetscHelpPrintf)(comm,"See docs/manualpages/index.html for help. \n");CHKERRQ(ierr);
479     ierr = (*PetscHelpPrintf)(comm,"Libraries linked from %s\n",PETSC_LIB_DIR);CHKERRQ(ierr);
480     ierr = (*PetscHelpPrintf)(comm,"----------------------------------------\n");CHKERRQ(ierr);
481   }
482 
483   /*
484        Print "higher-level" package help message
485   */
486   if (flg3) {
487     if (PetscExternalHelpFunction) {
488       ierr = (*PetscExternalHelpFunction)(comm);CHKERRQ(ierr);
489     }
490   }
491 
492   ierr = PetscOptionsGetString(NULL,NULL,"-help",helpoptions,sizeof(helpoptions),&flg1);CHKERRQ(ierr);
493   if (flg1) {
494     ierr = PetscStrcmp(helpoptions,"intro",&flg2);CHKERRQ(ierr);
495     if (flg2) {
496       ierr = PetscOptionsDestroyDefault();CHKERRQ(ierr);
497       ierr = PetscFreeMPIResources();CHKERRQ(ierr);
498       ierr = MPI_Finalize();CHKERRQ(ierr);
499       exit(0);
500     }
501   }
502 
503   /*
504       Setup the error handling
505   */
506   flg1 = PETSC_FALSE;
507   ierr = PetscOptionsGetBool(NULL,NULL,"-on_error_abort",&flg1,NULL);CHKERRQ(ierr);
508   if (flg1) {
509     ierr = MPI_Comm_set_errhandler(comm,MPI_ERRORS_ARE_FATAL);CHKERRQ(ierr);
510     ierr = PetscPushErrorHandler(PetscAbortErrorHandler,NULL);CHKERRQ(ierr);
511   }
512   flg1 = PETSC_FALSE;
513   ierr = PetscOptionsGetBool(NULL,NULL,"-on_error_mpiabort",&flg1,NULL);CHKERRQ(ierr);
514   if (flg1) { ierr = PetscPushErrorHandler(PetscMPIAbortErrorHandler,NULL);CHKERRQ(ierr);}
515   flg1 = PETSC_FALSE;
516   ierr = PetscOptionsGetBool(NULL,NULL,"-mpi_return_on_error",&flg1,NULL);CHKERRQ(ierr);
517   if (flg1) {
518     ierr = MPI_Comm_set_errhandler(comm,MPI_ERRORS_RETURN);CHKERRQ(ierr);
519   }
520   /* experimental */
521   flg1 = PETSC_FALSE;
522   ierr = PetscOptionsGetBool(NULL,NULL,"-mpi_return_error_string",&flg1,NULL);CHKERRQ(ierr);
523   if (flg1) {
524     MPI_Errhandler eh;
525 
526     ierr = MPI_Comm_create_errhandler(PetscMPI_Comm_eh,&eh);CHKERRQ(ierr);
527     ierr = MPI_Comm_set_errhandler(comm,eh);CHKERRQ(ierr);
528     ierr = MPI_Errhandler_free(&eh);CHKERRQ(ierr);
529   }
530   flg1 = PETSC_FALSE;
531   ierr = PetscOptionsGetBool(NULL,NULL,"-no_signal_handler",&flg1,NULL);CHKERRQ(ierr);
532   if (!flg1) {ierr = PetscPushSignalHandler(PetscSignalHandlerDefault,(void*)0);CHKERRQ(ierr);}
533   flg1 = PETSC_FALSE;
534   ierr = PetscOptionsGetBool(NULL,NULL,"-fp_trap",&flg1,&flag);CHKERRQ(ierr);
535   if (flag) {ierr = PetscSetFPTrap((PetscFPTrap)flg1);CHKERRQ(ierr);}
536   ierr = PetscOptionsGetInt(NULL,NULL,"-check_pointer_intensity",&intensity,&flag);CHKERRQ(ierr);
537   if (flag) {ierr = PetscCheckPointerSetIntensity(intensity);CHKERRQ(ierr);}
538 
539   /*
540       Setup debugger information
541   */
542   ierr = PetscSetDefaultDebugger();CHKERRQ(ierr);
543   ierr = PetscOptionsGetString(NULL,NULL,"-on_error_attach_debugger",string,64,&flg1);CHKERRQ(ierr);
544   if (flg1) {
545     MPI_Errhandler err_handler;
546 
547     ierr = PetscSetDebuggerFromString(string);CHKERRQ(ierr);
548     ierr = MPI_Comm_create_errhandler(Petsc_MPI_DebuggerOnError,&err_handler);CHKERRQ(ierr);
549     ierr = MPI_Comm_set_errhandler(comm,err_handler);CHKERRQ(ierr);
550     ierr = PetscPushErrorHandler(PetscAttachDebuggerErrorHandler,NULL);CHKERRQ(ierr);
551   }
552   ierr = PetscOptionsGetString(NULL,NULL,"-debug_terminal",string,64,&flg1);CHKERRQ(ierr);
553   if (flg1) { ierr = PetscSetDebugTerminal(string);CHKERRQ(ierr); }
554   ierr = PetscOptionsGetString(NULL,NULL,"-start_in_debugger",string,64,&flg1);CHKERRQ(ierr);
555   ierr = PetscOptionsGetString(NULL,NULL,"-stop_for_debugger",string,64,&flg2);CHKERRQ(ierr);
556   if (flg1 || flg2) {
557     PetscMPIInt    size;
558     PetscInt       lsize,*nodes;
559     MPI_Errhandler err_handler;
560     /*
561        we have to make sure that all processors have opened
562        connections to all other processors, otherwise once the
563        debugger has stated it is likely to receive a SIGUSR1
564        and kill the program.
565     */
566     ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
567     if (size > 2) {
568       PetscMPIInt dummy = 0;
569       MPI_Status  status;
570       for (i=0; i<size; i++) {
571         if (rank != i) {
572           ierr = MPI_Send(&dummy,1,MPI_INT,i,109,comm);CHKERRQ(ierr);
573         }
574       }
575       for (i=0; i<size; i++) {
576         if (rank != i) {
577           ierr = MPI_Recv(&dummy,1,MPI_INT,i,109,comm,&status);CHKERRQ(ierr);
578         }
579       }
580     }
581     /* check if this processor node should be in debugger */
582     ierr  = PetscMalloc1(size,&nodes);CHKERRQ(ierr);
583     lsize = size;
584     ierr  = PetscOptionsGetIntArray(NULL,NULL,"-debugger_nodes",nodes,&lsize,&flag);CHKERRQ(ierr);
585     if (flag) {
586       for (i=0; i<lsize; i++) {
587         if (nodes[i] == rank) { flag = PETSC_FALSE; break; }
588       }
589     }
590     if (!flag) {
591       ierr = PetscSetDebuggerFromString(string);CHKERRQ(ierr);
592       ierr = PetscPushErrorHandler(PetscAbortErrorHandler,NULL);CHKERRQ(ierr);
593       if (flg1) {
594         ierr = PetscAttachDebugger();CHKERRQ(ierr);
595       } else {
596         ierr = PetscStopForDebugger();CHKERRQ(ierr);
597       }
598       ierr = MPI_Comm_create_errhandler(Petsc_MPI_AbortOnError,&err_handler);CHKERRQ(ierr);
599       ierr = MPI_Comm_set_errhandler(comm,err_handler);CHKERRQ(ierr);
600     }
601     ierr = PetscFree(nodes);CHKERRQ(ierr);
602   }
603 
604   ierr = PetscOptionsGetString(NULL,NULL,"-on_error_emacs",emacsmachinename,128,&flg1);CHKERRQ(ierr);
605   if (flg1 && !rank) {ierr = PetscPushErrorHandler(PetscEmacsClientErrorHandler,emacsmachinename);CHKERRQ(ierr);}
606 
607   /*
608         Setup profiling and logging
609   */
610 #if defined(PETSC_USE_INFO)
611   {
612     ierr = PetscInfoSetFromOptions(NULL);CHKERRQ(ierr);
613   }
614 #endif
615 #if defined(PETSC_USE_LOG)
616   mname[0] = 0;
617   ierr = PetscOptionsGetString(NULL,NULL,"-history",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr);
618   if (flg1) {
619     if (mname[0]) {
620       ierr = PetscOpenHistoryFile(mname,&petsc_history);CHKERRQ(ierr);
621     } else {
622       ierr = PetscOpenHistoryFile(NULL,&petsc_history);CHKERRQ(ierr);
623     }
624   }
625 
626   ierr = PetscOptionsGetBool(NULL,NULL,"-log_sync",&PetscLogSyncOn,NULL);CHKERRQ(ierr);
627 
628 #if defined(PETSC_HAVE_MPE)
629   flg1 = PETSC_FALSE;
630   ierr = PetscOptionsHasName(NULL,NULL,"-log_mpe",&flg1);CHKERRQ(ierr);
631   if (flg1) {ierr = PetscLogMPEBegin();CHKERRQ(ierr);}
632 #endif
633   flg1 = PETSC_FALSE;
634   flg3 = PETSC_FALSE;
635   ierr = PetscOptionsGetBool(NULL,NULL,"-log_all",&flg1,NULL);CHKERRQ(ierr);
636   ierr = PetscOptionsHasName(NULL,NULL,"-log_summary",&flg3);CHKERRQ(ierr);
637   if (flg1)                      { ierr = PetscLogAllBegin();CHKERRQ(ierr); }
638   else if (flg3)                 { ierr = PetscLogDefaultBegin();CHKERRQ(ierr);}
639 
640   ierr = PetscOptionsGetString(NULL,NULL,"-log_trace",mname,250,&flg1);CHKERRQ(ierr);
641   if (flg1) {
642     char name[PETSC_MAX_PATH_LEN],fname[PETSC_MAX_PATH_LEN];
643     FILE *file;
644     if (mname[0]) {
645       PetscSNPrintf(name,PETSC_MAX_PATH_LEN,"%s.%d",mname,rank);
646       ierr = PetscFixFilename(name,fname);CHKERRQ(ierr);
647       file = fopen(fname,"w");
648       if (!file) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open trace file: %s",fname);
649     } else file = PETSC_STDOUT;
650     ierr = PetscLogTraceBegin(file);CHKERRQ(ierr);
651   }
652 
653   ierr = PetscOptionsGetViewer(comm,NULL,NULL,"-log_view",NULL,&format,&flg4);CHKERRQ(ierr);
654   if (flg4) {
655     if (format == PETSC_VIEWER_ASCII_XML) {
656       ierr = PetscLogNestedBegin();CHKERRQ(ierr);
657     } else {
658       ierr = PetscLogDefaultBegin();CHKERRQ(ierr);
659     }
660   }
661   if (flg4 && format == PETSC_VIEWER_ASCII_XML) {
662     PetscReal threshold = PetscRealConstant(0.01);
663     ierr = PetscOptionsGetReal(NULL,NULL,"-log_threshold",&threshold,&flg1);CHKERRQ(ierr);
664     if (flg1) {ierr = PetscLogSetThreshold((PetscLogDouble)threshold,NULL);CHKERRQ(ierr);}
665   }
666 #endif
667 
668   ierr = PetscOptionsGetBool(NULL,NULL,"-saws_options",&PetscOptionsPublish,NULL);CHKERRQ(ierr);
669 
670 #if defined(PETSC_HAVE_CUDA)
671   ierr = PetscOptionsBegin(comm,NULL,"CUDA initialize","Sys");CHKERRQ(ierr);
672   ierr = PetscOptionsBool("-cuda_initialize","Initialize the CUDA devices and cuBLAS during PetscInitialize()",NULL,initCUDA,&initCUDA,NULL);CHKERRQ(ierr);
673   ierr = PetscOptionsBool("-use_gpu_aware_mpi","Use GPU-aware MPI",NULL,use_gpu_aware_mpi,&use_gpu_aware_mpi,NULL);CHKERRQ(ierr);
674   ierr = PetscOptionsEnd();CHKERRQ(ierr);
675   if (initCUDA) {ierr = PetscCUDAInitialize(PETSC_COMM_WORLD);CHKERRQ(ierr);}
676   if (use_gpu_aware_mpi) {
677 #if defined(PETSC_HAVE_OMPI_MAJOR_VERSION) && defined(MPIX_CUDA_AWARE_SUPPORT) && MPIX_CUDA_AWARE_SUPPORT
678     /* Trust OpenMPI's compile time cuda query interface */
679     mpi_gpu_awareness = PETSC_TRUE;
680 #else
681     /* For other MPI implementations without cuda query API, we do a GPU MPI call to see if it segfaults.
682        Note that Spectrum MPI sets OMPI_MAJOR_VERSION and is CUDA-aware, but does not have MPIX_CUDA_AWARE_SUPPORT.
683     */
684     mpi_gpu_awareness = PetscCheckMpiGpuAwareness();
685 #endif
686     if (!mpi_gpu_awareness) {
687       (*PetscErrorPrintf)("PETSc is configured with GPU support, but your MPI is not GPU-aware. For better performance, please use a GPU-aware MPI.\n");
688       (*PetscErrorPrintf)("For IBM Spectrum MPI on OLCF Summit, you may need jsrun --smpiargs=-gpu.\n");
689       (*PetscErrorPrintf)("For OpenMPI, you need to configure it --with-cuda (https://www.open-mpi.org/faq/?category=buildcuda)\n");
690       (*PetscErrorPrintf)("For MVAPICH2-GDR, you need to set MV2_USE_CUDA=1 (http://mvapich.cse.ohio-state.edu/userguide/gdr/)\n");
691       (*PetscErrorPrintf)("For Cray-MPICH, you need to set MPICH_RDMA_ENABLED_CUDA=1 (https://www.olcf.ornl.gov/tutorials/gpudirect-mpich-enabled-cuda/)\n");
692       (*PetscErrorPrintf)("If you do not care, use option -use_gpu_aware_mpi 0, then PETSc will copy data from GPU to CPU for communication.\n");
693       PETSCABORT(PETSC_COMM_WORLD,PETSC_ERR_LIB);
694     }
695   }
696 #endif
697 
698   /*
699        Print basic help message
700   */
701   ierr = PetscOptionsHasHelp(NULL,&flg1);CHKERRQ(ierr);
702   if (flg1) {
703     ierr = (*PetscHelpPrintf)(comm,"Options for all PETSc programs:\n");CHKERRQ(ierr);
704     ierr = (*PetscHelpPrintf)(comm," -help: prints help method for each option\n");CHKERRQ(ierr);
705     ierr = (*PetscHelpPrintf)(comm," -on_error_abort: cause an abort when an error is detected. Useful \n ");CHKERRQ(ierr);
706     ierr = (*PetscHelpPrintf)(comm,"       only when run in the debugger\n");CHKERRQ(ierr);
707     ierr = (*PetscHelpPrintf)(comm," -on_error_attach_debugger [gdb,dbx,xxgdb,ups,noxterm]\n");CHKERRQ(ierr);
708     ierr = (*PetscHelpPrintf)(comm,"       start the debugger in new xterm\n");CHKERRQ(ierr);
709     ierr = (*PetscHelpPrintf)(comm,"       unless noxterm is given\n");CHKERRQ(ierr);
710     ierr = (*PetscHelpPrintf)(comm," -start_in_debugger [gdb,dbx,xxgdb,ups,noxterm]\n");CHKERRQ(ierr);
711     ierr = (*PetscHelpPrintf)(comm,"       start all processes in the debugger\n");CHKERRQ(ierr);
712     ierr = (*PetscHelpPrintf)(comm," -on_error_emacs <machinename>\n");CHKERRQ(ierr);
713     ierr = (*PetscHelpPrintf)(comm,"    emacs jumps to error file\n");CHKERRQ(ierr);
714     ierr = (*PetscHelpPrintf)(comm," -debugger_nodes [n1,n2,..] Nodes to start in debugger\n");CHKERRQ(ierr);
715     ierr = (*PetscHelpPrintf)(comm," -debugger_pause [m] : delay (in seconds) to attach debugger\n");CHKERRQ(ierr);
716     ierr = (*PetscHelpPrintf)(comm," -stop_for_debugger : prints message on how to attach debugger manually\n");CHKERRQ(ierr);
717     ierr = (*PetscHelpPrintf)(comm,"                      waits the delay for you to attach\n");CHKERRQ(ierr);
718     ierr = (*PetscHelpPrintf)(comm," -display display: Location where X window graphics and debuggers are displayed\n");CHKERRQ(ierr);
719     ierr = (*PetscHelpPrintf)(comm," -no_signal_handler: do not trap error signals\n");CHKERRQ(ierr);
720     ierr = (*PetscHelpPrintf)(comm," -mpi_return_on_error: MPI returns error code, rather than abort on internal error\n");CHKERRQ(ierr);
721     ierr = (*PetscHelpPrintf)(comm," -fp_trap: stop on floating point exceptions\n");CHKERRQ(ierr);
722     ierr = (*PetscHelpPrintf)(comm,"           note on IBM RS6000 this slows run greatly\n");CHKERRQ(ierr);
723     ierr = (*PetscHelpPrintf)(comm," -malloc_dump <optional filename>: dump list of unfreed memory at conclusion\n");CHKERRQ(ierr);
724     ierr = (*PetscHelpPrintf)(comm," -malloc: use PETSc error checking malloc (deprecated, use -malloc_debug)\n");CHKERRQ(ierr);
725     ierr = (*PetscHelpPrintf)(comm," -malloc no: don't use PETSc error checking malloc (deprecated, use -malloc_debug no)\n");CHKERRQ(ierr);
726     ierr = (*PetscHelpPrintf)(comm," -malloc_info: prints total memory usage\n");CHKERRQ(ierr);
727     ierr = (*PetscHelpPrintf)(comm," -malloc_view <optional filename>: keeps log of all memory allocations, displays in PetscFinalize()\n");CHKERRQ(ierr);
728     ierr = (*PetscHelpPrintf)(comm," -malloc_debug <true or false>: enables or disables extended checking for memory corruption\n");CHKERRQ(ierr);
729     ierr = (*PetscHelpPrintf)(comm," -options_view: dump list of options inputted\n");CHKERRQ(ierr);
730     ierr = (*PetscHelpPrintf)(comm," -options_left: dump list of unused options\n");CHKERRQ(ierr);
731     ierr = (*PetscHelpPrintf)(comm," -options_left no: don't dump list of unused options\n");CHKERRQ(ierr);
732     ierr = (*PetscHelpPrintf)(comm," -tmp tmpdir: alternative /tmp directory\n");CHKERRQ(ierr);
733     ierr = (*PetscHelpPrintf)(comm," -shared_tmp: tmp directory is shared by all processors\n");CHKERRQ(ierr);
734     ierr = (*PetscHelpPrintf)(comm," -not_shared_tmp: each processor has separate tmp directory\n");CHKERRQ(ierr);
735     ierr = (*PetscHelpPrintf)(comm," -memory_view: print memory usage at end of run\n");CHKERRQ(ierr);
736 #if defined(PETSC_USE_LOG)
737     ierr = (*PetscHelpPrintf)(comm," -get_total_flops: total flops over all processors\n");CHKERRQ(ierr);
738     ierr = (*PetscHelpPrintf)(comm," -log_view [:filename:[format]]: logging objects and events\n");CHKERRQ(ierr);
739     ierr = (*PetscHelpPrintf)(comm," -log_trace [filename]: prints trace of all PETSc calls\n");CHKERRQ(ierr);
740     ierr = (*PetscHelpPrintf)(comm," -log_exclude <list,of,classnames>: exclude given classes from logging\n");CHKERRQ(ierr);
741 #if defined(PETSC_HAVE_MPE)
742     ierr = (*PetscHelpPrintf)(comm," -log_mpe: Also create logfile viewable through Jumpshot\n");CHKERRQ(ierr);
743 #endif
744 #endif
745 #if defined(PETSC_USE_INFO)
746     ierr = (*PetscHelpPrintf)(comm," -info [filename][:[~]<list,of,classnames>[:[~]self]]: print verbose information\n");CHKERRQ(ierr);
747 #endif
748     ierr = (*PetscHelpPrintf)(comm," -v: prints PETSc version number and release date\n");CHKERRQ(ierr);
749     ierr = (*PetscHelpPrintf)(comm," -options_file <file>: reads options from file\n");CHKERRQ(ierr);
750     ierr = (*PetscHelpPrintf)(comm," -petsc_sleep n: sleeps n seconds before running program\n");CHKERRQ(ierr);
751   }
752 
753 #if defined(PETSC_HAVE_POPEN)
754   {
755   char machine[128];
756   ierr = PetscOptionsGetString(NULL,NULL,"-popen_machine",machine,128,&flg1);CHKERRQ(ierr);
757   if (flg1) {
758     ierr = PetscPOpenSetMachine(machine);CHKERRQ(ierr);
759   }
760   }
761 #endif
762 
763   ierr = PetscOptionsGetReal(NULL,NULL,"-petsc_sleep",&si,&flg1);CHKERRQ(ierr);
764   if (flg1) {
765     ierr = PetscSleep(si);CHKERRQ(ierr);
766   }
767 
768 #if defined(PETSC_HAVE_VIENNACL)
769   ierr = PetscOptionsHasName(NULL,NULL,"-log_summary",&flg3);CHKERRQ(ierr);
770   if (!flg3) {
771     ierr = PetscOptionsHasName(NULL,NULL,"-log_view",&flg3);CHKERRQ(ierr);
772   }
773   ierr = PetscOptionsGetBool(NULL,NULL,"-viennacl_synchronize",&flg3,NULL);CHKERRQ(ierr);
774   PetscViennaCLSynchronize = flg3;
775   ierr = PetscViennaCLInit();CHKERRQ(ierr);
776 #endif
777 
778   /*
779      Creates the logging data structures; this is enabled even if logging is not turned on
780      This is the last thing we do before returning to the user code to prevent having the
781      logging numbers contaminated by any startup time associated with MPI and the GPUs
782   */
783 #if defined(PETSC_USE_LOG)
784   ierr = PetscLogInitialize();CHKERRQ(ierr);
785 #endif
786 
787   PetscFunctionReturn(0);
788 }
789