xref: /petsc/src/sys/objects/init.c (revision 6a98f8dc3f2c9149905a87dc2e9d0fedaf64e09a)
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],mname[PETSC_MAX_PATH_LEN];
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   PetscViewerFormat format;
373   PetscBool         flg4 = PETSC_FALSE;
374 #endif
375 #if defined(PETSC_HAVE_CUDA)
376   PetscBool         initCUDA = PETSC_TRUE,mpi_gpu_awareness;
377 #endif
378 
379   PetscFunctionBegin;
380   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
381 
382 #if !defined(PETSC_HAVE_THREADSAFETY)
383   if (!(PETSC_RUNNING_ON_VALGRIND)) {
384     /*
385       Setup the memory management; support for tracing malloc() usage
386     */
387     PetscBool         mdebug = PETSC_FALSE, eachcall = PETSC_FALSE, initializenan = PETSC_FALSE, mlog = PETSC_FALSE;
388 
389 #if defined(PETSC_USE_DEBUG)
390     mdebug        = PETSC_TRUE;
391     initializenan = PETSC_TRUE;
392     ierr   = PetscOptionsHasName(NULL,NULL,"-malloc_test",&flg1);CHKERRQ(ierr);
393 #else
394     /* don't warn about unused option */
395     ierr = PetscOptionsHasName(NULL,NULL,"-malloc_test",&flg1);CHKERRQ(ierr);
396     flg1 = PETSC_FALSE;
397 #endif
398     ierr = PetscOptionsGetBool(NULL,NULL,"-malloc_debug",&flg2,&flg3);CHKERRQ(ierr);
399     if (flg1 || flg2) {
400       mdebug        = PETSC_TRUE;
401       eachcall      = PETSC_TRUE;
402       initializenan = PETSC_TRUE;
403     } else if (flg3 && !flg2) {
404       mdebug        = PETSC_FALSE;
405       eachcall      = PETSC_FALSE;
406       initializenan = PETSC_FALSE;
407     }
408 
409     ierr = PetscOptionsHasName(NULL,NULL,"-malloc_view",&mlog);CHKERRQ(ierr);
410     if (mlog) {
411       mdebug = PETSC_TRUE;
412     }
413     /* the next line is deprecated */
414     ierr = PetscOptionsGetBool(NULL,NULL,"-malloc",&mdebug,NULL);CHKERRQ(ierr);
415     ierr = PetscOptionsGetBool(NULL,NULL,"-malloc_dump",&mdebug,NULL);CHKERRQ(ierr);
416     ierr = PetscOptionsGetBool(NULL,NULL,"-log_view_memory",&mdebug,NULL);CHKERRQ(ierr);
417     if (mdebug) {
418       ierr = PetscMallocSetDebug(eachcall,initializenan);CHKERRQ(ierr);
419     }
420     if (mlog) {
421       PetscReal logthreshold = 0;
422       ierr = PetscOptionsGetReal(NULL,NULL,"-malloc_view_threshold",&logthreshold,NULL);CHKERRQ(ierr);
423       ierr = PetscMallocViewSet(logthreshold);CHKERRQ(ierr);
424     }
425 #if defined(PETSC_USE_LOG)
426     ierr = PetscOptionsGetBool(NULL,NULL,"-log_view_memory",&PetscLogMemory,NULL);CHKERRQ(ierr);
427 #endif
428   }
429 
430   ierr = PetscOptionsGetBool(NULL,NULL,"-malloc_coalesce",&flg1,&flg2);CHKERRQ(ierr);
431   if (flg2) {ierr = PetscMallocSetCoalesce(flg1);CHKERRQ(ierr);}
432   flg1 = PETSC_FALSE;
433   ierr = PetscOptionsGetBool(NULL,NULL,"-malloc_hbw",&flg1,NULL);CHKERRQ(ierr);
434   /* ignore this option if malloc is already set */
435   if (flg1 && !petscsetmallocvisited) {ierr = PetscSetUseHBWMalloc_Private();CHKERRQ(ierr);}
436 
437   flg1 = PETSC_FALSE;
438   ierr = PetscOptionsGetBool(NULL,NULL,"-malloc_info",&flg1,NULL);CHKERRQ(ierr);
439   if (!flg1) {
440     flg1 = PETSC_FALSE;
441     ierr = PetscOptionsGetBool(NULL,NULL,"-memory_view",&flg1,NULL);CHKERRQ(ierr);
442   }
443   if (flg1) {
444     ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr);
445   }
446 #endif
447 
448 #if defined(PETSC_USE_LOG)
449   ierr = PetscOptionsHasName(NULL,NULL,"-objects_dump",&PetscObjectsLog);CHKERRQ(ierr);
450 #endif
451 
452   /*
453       Set the display variable for graphics
454   */
455   ierr = PetscSetDisplay();CHKERRQ(ierr);
456 
457   /*
458       Print the PETSc version information
459   */
460   ierr = PetscOptionsHasName(NULL,NULL,"-v",&flg1);CHKERRQ(ierr);
461   ierr = PetscOptionsHasName(NULL,NULL,"-version",&flg2);CHKERRQ(ierr);
462   ierr = PetscOptionsHasHelp(NULL,&flg3);CHKERRQ(ierr);
463   if (flg1 || flg2 || flg3) {
464 
465     /*
466        Print "higher-level" package version message
467     */
468     if (PetscExternalVersionFunction) {
469       ierr = (*PetscExternalVersionFunction)(comm);CHKERRQ(ierr);
470     }
471 
472     ierr = PetscGetVersion(version,256);CHKERRQ(ierr);
473     ierr = (*PetscHelpPrintf)(comm,"--------------------------------------------------------------------------\n");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   }
481 
482   /*
483        Print "higher-level" package help message
484   */
485   if (flg3) {
486     if (PetscExternalHelpFunction) {
487       ierr = (*PetscExternalHelpFunction)(comm);CHKERRQ(ierr);
488     }
489   }
490 
491   ierr = PetscOptionsGetString(NULL,NULL,"-help",helpoptions,sizeof(helpoptions),&flg1);CHKERRQ(ierr);
492   if (flg1) {
493     ierr = PetscStrcmp(helpoptions,"intro",&flg2);CHKERRQ(ierr);
494     if (flg2) {
495       ierr = PetscOptionsDestroyDefault();CHKERRQ(ierr);
496       ierr = PetscFreeMPIResources();CHKERRQ(ierr);
497       ierr = MPI_Finalize();CHKERRQ(ierr);
498       exit(0);
499     }
500   }
501 
502   /*
503       Setup the error handling
504   */
505   flg1 = PETSC_FALSE;
506   ierr = PetscOptionsGetBool(NULL,NULL,"-on_error_abort",&flg1,NULL);CHKERRQ(ierr);
507   if (flg1) {
508     ierr = MPI_Comm_set_errhandler(comm,MPI_ERRORS_ARE_FATAL);CHKERRQ(ierr);
509     ierr = PetscPushErrorHandler(PetscAbortErrorHandler,NULL);CHKERRQ(ierr);
510   }
511   flg1 = PETSC_FALSE;
512   ierr = PetscOptionsGetBool(NULL,NULL,"-on_error_mpiabort",&flg1,NULL);CHKERRQ(ierr);
513   if (flg1) { ierr = PetscPushErrorHandler(PetscMPIAbortErrorHandler,NULL);CHKERRQ(ierr);}
514   flg1 = PETSC_FALSE;
515   ierr = PetscOptionsGetBool(NULL,NULL,"-mpi_return_on_error",&flg1,NULL);CHKERRQ(ierr);
516   if (flg1) {
517     ierr = MPI_Comm_set_errhandler(comm,MPI_ERRORS_RETURN);CHKERRQ(ierr);
518   }
519   /* experimental */
520   flg1 = PETSC_FALSE;
521   ierr = PetscOptionsGetBool(NULL,NULL,"-mpi_return_error_string",&flg1,NULL);CHKERRQ(ierr);
522   if (flg1) {
523     MPI_Errhandler eh;
524 
525     ierr = MPI_Comm_create_errhandler(PetscMPI_Comm_eh,&eh);CHKERRQ(ierr);
526     ierr = MPI_Comm_set_errhandler(comm,eh);CHKERRQ(ierr);
527     ierr = MPI_Errhandler_free(&eh);CHKERRQ(ierr);
528   }
529   flg1 = PETSC_FALSE;
530   ierr = PetscOptionsGetBool(NULL,NULL,"-no_signal_handler",&flg1,NULL);CHKERRQ(ierr);
531   if (!flg1) {ierr = PetscPushSignalHandler(PetscSignalHandlerDefault,(void*)0);CHKERRQ(ierr);}
532   flg1 = PETSC_FALSE;
533   ierr = PetscOptionsGetBool(NULL,NULL,"-fp_trap",&flg1,&flag);CHKERRQ(ierr);
534   if (flag) {ierr = PetscSetFPTrap((PetscFPTrap)flg1);CHKERRQ(ierr);}
535   ierr = PetscOptionsGetInt(NULL,NULL,"-check_pointer_intensity",&intensity,&flag);CHKERRQ(ierr);
536   if (flag) {ierr = PetscCheckPointerSetIntensity(intensity);CHKERRQ(ierr);}
537 
538   /*
539       Setup debugger information
540   */
541   ierr = PetscSetDefaultDebugger();CHKERRQ(ierr);
542   ierr = PetscOptionsGetString(NULL,NULL,"-on_error_attach_debugger",string,64,&flg1);CHKERRQ(ierr);
543   if (flg1) {
544     MPI_Errhandler err_handler;
545 
546     ierr = PetscSetDebuggerFromString(string);CHKERRQ(ierr);
547     ierr = MPI_Comm_create_errhandler(Petsc_MPI_DebuggerOnError,&err_handler);CHKERRQ(ierr);
548     ierr = MPI_Comm_set_errhandler(comm,err_handler);CHKERRQ(ierr);
549     ierr = PetscPushErrorHandler(PetscAttachDebuggerErrorHandler,NULL);CHKERRQ(ierr);
550   }
551   ierr = PetscOptionsGetString(NULL,NULL,"-debug_terminal",string,64,&flg1);CHKERRQ(ierr);
552   if (flg1) { ierr = PetscSetDebugTerminal(string);CHKERRQ(ierr); }
553   ierr = PetscOptionsGetString(NULL,NULL,"-start_in_debugger",string,64,&flg1);CHKERRQ(ierr);
554   ierr = PetscOptionsGetString(NULL,NULL,"-stop_for_debugger",string,64,&flg2);CHKERRQ(ierr);
555   if (flg1 || flg2) {
556     PetscMPIInt    size;
557     PetscInt       lsize,*nodes;
558     MPI_Errhandler err_handler;
559     /*
560        we have to make sure that all processors have opened
561        connections to all other processors, otherwise once the
562        debugger has stated it is likely to receive a SIGUSR1
563        and kill the program.
564     */
565     ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
566     if (size > 2) {
567       PetscMPIInt dummy = 0;
568       MPI_Status  status;
569       for (i=0; i<size; i++) {
570         if (rank != i) {
571           ierr = MPI_Send(&dummy,1,MPI_INT,i,109,comm);CHKERRQ(ierr);
572         }
573       }
574       for (i=0; i<size; i++) {
575         if (rank != i) {
576           ierr = MPI_Recv(&dummy,1,MPI_INT,i,109,comm,&status);CHKERRQ(ierr);
577         }
578       }
579     }
580     /* check if this processor node should be in debugger */
581     ierr  = PetscMalloc1(size,&nodes);CHKERRQ(ierr);
582     lsize = size;
583     ierr  = PetscOptionsGetIntArray(NULL,NULL,"-debugger_nodes",nodes,&lsize,&flag);CHKERRQ(ierr);
584     if (flag) {
585       for (i=0; i<lsize; i++) {
586         if (nodes[i] == rank) { flag = PETSC_FALSE; break; }
587       }
588     }
589     if (!flag) {
590       ierr = PetscSetDebuggerFromString(string);CHKERRQ(ierr);
591       ierr = PetscPushErrorHandler(PetscAbortErrorHandler,NULL);CHKERRQ(ierr);
592       if (flg1) {
593         ierr = PetscAttachDebugger();CHKERRQ(ierr);
594       } else {
595         ierr = PetscStopForDebugger();CHKERRQ(ierr);
596       }
597       ierr = MPI_Comm_create_errhandler(Petsc_MPI_AbortOnError,&err_handler);CHKERRQ(ierr);
598       ierr = MPI_Comm_set_errhandler(comm,err_handler);CHKERRQ(ierr);
599     }
600     ierr = PetscFree(nodes);CHKERRQ(ierr);
601   }
602 
603   ierr = PetscOptionsGetString(NULL,NULL,"-on_error_emacs",emacsmachinename,128,&flg1);CHKERRQ(ierr);
604   if (flg1 && !rank) {ierr = PetscPushErrorHandler(PetscEmacsClientErrorHandler,emacsmachinename);CHKERRQ(ierr);}
605 
606   /*
607         Setup profiling and logging
608   */
609 #if defined(PETSC_USE_INFO)
610   {
611     ierr = PetscInfoSetFromOptions(NULL);CHKERRQ(ierr);
612   }
613 #endif
614 #if defined(PETSC_USE_LOG)
615   mname[0] = 0;
616   ierr = PetscOptionsGetString(NULL,NULL,"-history",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr);
617   if (flg1) {
618     if (mname[0]) {
619       ierr = PetscOpenHistoryFile(mname,&petsc_history);CHKERRQ(ierr);
620     } else {
621       ierr = PetscOpenHistoryFile(NULL,&petsc_history);CHKERRQ(ierr);
622     }
623   }
624 
625   ierr = PetscOptionsGetBool(NULL,NULL,"-log_sync",&PetscLogSyncOn,NULL);CHKERRQ(ierr);
626 
627 #if defined(PETSC_HAVE_MPE)
628   flg1 = PETSC_FALSE;
629   ierr = PetscOptionsHasName(NULL,NULL,"-log_mpe",&flg1);CHKERRQ(ierr);
630   if (flg1) {ierr = PetscLogMPEBegin();CHKERRQ(ierr);}
631 #endif
632   flg1 = PETSC_FALSE;
633   flg3 = PETSC_FALSE;
634   ierr = PetscOptionsGetBool(NULL,NULL,"-log_all",&flg1,NULL);CHKERRQ(ierr);
635   ierr = PetscOptionsHasName(NULL,NULL,"-log_summary",&flg3);CHKERRQ(ierr);
636   if (flg1)                      { ierr = PetscLogAllBegin();CHKERRQ(ierr); }
637   else if (flg3)                 { ierr = PetscLogDefaultBegin();CHKERRQ(ierr);}
638 
639   ierr = PetscOptionsGetString(NULL,NULL,"-log_trace",mname,250,&flg1);CHKERRQ(ierr);
640   if (flg1) {
641     char name[PETSC_MAX_PATH_LEN],fname[PETSC_MAX_PATH_LEN];
642     FILE *file;
643     if (mname[0]) {
644       PetscSNPrintf(name,PETSC_MAX_PATH_LEN,"%s.%d",mname,rank);
645       ierr = PetscFixFilename(name,fname);CHKERRQ(ierr);
646       file = fopen(fname,"w");
647       if (!file) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open trace file: %s",fname);
648     } else file = PETSC_STDOUT;
649     ierr = PetscLogTraceBegin(file);CHKERRQ(ierr);
650   }
651 
652   ierr = PetscOptionsGetViewer(comm,NULL,NULL,"-log_view",NULL,&format,&flg4);CHKERRQ(ierr);
653   if (flg4) {
654     if (format == PETSC_VIEWER_ASCII_XML) {
655       ierr = PetscLogNestedBegin();CHKERRQ(ierr);
656     } else {
657       ierr = PetscLogDefaultBegin();CHKERRQ(ierr);
658     }
659   }
660   if (flg4 && format == PETSC_VIEWER_ASCII_XML) {
661     PetscReal threshold = PetscRealConstant(0.01);
662     ierr = PetscOptionsGetReal(NULL,NULL,"-log_threshold",&threshold,&flg1);CHKERRQ(ierr);
663     if (flg1) {ierr = PetscLogSetThreshold((PetscLogDouble)threshold,NULL);CHKERRQ(ierr);}
664   }
665 #endif
666 
667   ierr = PetscOptionsGetBool(NULL,NULL,"-saws_options",&PetscOptionsPublish,NULL);CHKERRQ(ierr);
668 
669 #if defined(PETSC_HAVE_CUDA)
670   ierr = PetscOptionsBegin(comm,NULL,"CUDA initialize","Sys");CHKERRQ(ierr);
671   ierr = PetscOptionsBool("-cuda_initialize","Initialize the CUDA devices and cuBLAS during PetscInitialize()",NULL,initCUDA,&initCUDA,NULL);CHKERRQ(ierr);
672   ierr = PetscOptionsBool("-use_gpu_aware_mpi","Use GPU-aware MPI",NULL,use_gpu_aware_mpi,&use_gpu_aware_mpi,NULL);CHKERRQ(ierr);
673   ierr = PetscOptionsEnd();CHKERRQ(ierr);
674   if (initCUDA) {ierr = PetscCUDAInitialize(PETSC_COMM_WORLD);CHKERRQ(ierr);}
675   if (use_gpu_aware_mpi) {
676 #if defined(PETSC_HAVE_OMPI_MAJOR_VERSION) && defined(MPIX_CUDA_AWARE_SUPPORT) && MPIX_CUDA_AWARE_SUPPORT
677     /* Trust OpenMPI's compile time cuda query interface */
678     mpi_gpu_awareness = PETSC_TRUE;
679 #else
680     /* For other MPI implementations without cuda query API, we do a GPU MPI call to see if it segfaults.
681        Note that Spectrum MPI sets OMPI_MAJOR_VERSION and is CUDA-aware, but does not have MPIX_CUDA_AWARE_SUPPORT.
682     */
683     mpi_gpu_awareness = PetscCheckMpiGpuAwareness();
684 #endif
685     if (!mpi_gpu_awareness) {
686       (*PetscErrorPrintf)("PETSc is configured with GPU support, but your MPI is not GPU-aware. For better performance, please use a GPU-aware MPI.\n");
687       (*PetscErrorPrintf)("For IBM Spectrum MPI on OLCF Summit, you may need jsrun --smpiargs=-gpu.\n");
688       (*PetscErrorPrintf)("For OpenMPI, you need to configure it --with-cuda (https://www.open-mpi.org/faq/?category=buildcuda)\n");
689       (*PetscErrorPrintf)("For MVAPICH2-GDR, you need to set MV2_USE_CUDA=1 (http://mvapich.cse.ohio-state.edu/userguide/gdr/)\n");
690       (*PetscErrorPrintf)("For Cray-MPICH, you need to set MPICH_RDMA_ENABLED_CUDA=1 (https://www.olcf.ornl.gov/tutorials/gpudirect-mpich-enabled-cuda/)\n");
691       (*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");
692       PETSCABORT(PETSC_COMM_WORLD,PETSC_ERR_LIB);
693     }
694   }
695 #endif
696 
697   /*
698        Print basic help message
699   */
700   ierr = PetscOptionsHasHelp(NULL,&flg1);CHKERRQ(ierr);
701   if (flg1) {
702     ierr = (*PetscHelpPrintf)(comm,"-------------------------------------------------\n");CHKERRQ(ierr);
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