/*@C PetscTraceBackErrorHandler - Default error handler routine that generates a traceback on error detection. Not Collective Input Parameters: + comm - communicator over which error occurred . line - the line number of the error (indicated by __LINE__) . func - the function where error is detected (indicated by __FUNCT__) . file - the file in which the error was detected (indicated by __FILE__) . mess - an error text string, usually just printed to the screen . n - the generic error number . p - PETSC_ERROR_INITIAL if this is the first call the error handler, otherwise PETSC_ERROR_REPEAT - ctx - error handler context Level: developer Notes: Most users need not directly employ this routine and the other error handlers, but can instead use the simplified interface SETERRQ, which has the calling sequence $ SETERRQ(comm,number,n,mess) Notes for experienced users: Use PetscPushErrorHandler() to set the desired error handler. The currently available PETSc error handlers include PetscTraceBackErrorHandler(), PetscAttachDebuggerErrorHandler(), PetscAbortErrorHandler(), and PetscMPIAbortErrorHandler() Concepts: error handler^traceback Concepts: traceback^generating .seealso: PetscPushErrorHandler(), PetscAttachDebuggerErrorHandler(), PetscAbortErrorHandler() @*/ PetscErrorCode PetscTraceBackErrorHandler(MPI_Comm comm,int line,const char *fun,const char *file,PetscErrorCode n,PetscErrorType p,const char *mess,void *ctx) { PetscLogDouble mem,rss; PetscBool flg1 = PETSC_FALSE,flg2 = PETSC_FALSE,flg3 = PETSC_FALSE; PetscMPIInt rank = 0; PetscFunctionBegin; if (comm != PETSC_COMM_SELF) MPI_Comm_rank(comm,&rank); if (!rank) { PetscBool ismain,isunknown; static int cnt = 1; if (p == PETSC_ERROR_INITIAL) { PetscErrorPrintfHilight(); (*PetscErrorPrintf)("--------------------- Error Message --------------------------------------------------------------\n"); PetscErrorPrintfNormal(); if (n == PETSC_ERR_MEM) { (*PetscErrorPrintf)("Out of memory. This could be due to allocating\n"); (*PetscErrorPrintf)("too large an object or bleeding by not properly\n"); (*PetscErrorPrintf)("destroying unneeded objects.\n"); PetscMallocGetCurrentUsage(&mem); PetscMemoryGetCurrentUsage(&rss); PetscOptionsGetBool(NULL,"-malloc_dump",&flg1,NULL); PetscOptionsGetBool(NULL,"-malloc_log",&flg2,NULL); PetscOptionsHasName(NULL,"-malloc_log_threshold",&flg3); if (flg2 || flg3) PetscMallocDumpLog(stdout); else { (*PetscErrorPrintf)("Memory allocated %.0f Memory used by process %.0f\n",mem,rss); if (flg1) PetscMallocDump(stdout); else (*PetscErrorPrintf)("Try running with -malloc_dump or -malloc_log for info.\n"); } } else { const char *text; PetscErrorMessage(n,&text,NULL); if (text) (*PetscErrorPrintf)("%s\n",text); } if (mess) (*PetscErrorPrintf)("%s\n",mess); (*PetscErrorPrintf)("See http://www.mcs.anl.gov/petsc/documentation/faq.html for trouble shooting.\n"); (*PetscErrorPrintf)("%s\n",version); if (PetscErrorPrintfInitializeCalled) (*PetscErrorPrintf)("%s on a %s named %s by %s %s\n",pname,arch,hostname,username,date); (*PetscErrorPrintf)("Configure options %s\n",petscconfigureoptions); } /* print line of stack trace */ (*PetscErrorPrintf)("#%d %s() line %d in %s\n",cnt++,fun,line,file); PetscStrncmp(fun,"main",4,&ismain); PetscStrncmp(fun,"unknown",7,&isunknown); if (ismain || isunknown) { PetscOptionsViewError(); PetscErrorPrintfHilight(); (*PetscErrorPrintf)("----------------End of Error Message -------send entire error message to [email protected]\n"); PetscErrorPrintfNormal(); } } else { /* do not print error messages since process 0 will print them, sleep before aborting so will not accidently kill process 0*/ PetscSleep(10.0); abort(); } PetscFunctionReturn(n); }
/*@C PetscTraceBackErrorHandler - Default error handler routine that generates a traceback on error detection. Not Collective Input Parameters: + comm - communicator over which error occurred . line - the line number of the error (indicated by __LINE__) . func - the function where error is detected (indicated by __FUNCT__) . file - the file in which the error was detected (indicated by __FILE__) . dir - the directory of the file (indicated by __SDIR__) . mess - an error text string, usually just printed to the screen . n - the generic error number . p - PETSC_ERROR_INITIAL if this is the first call the the error handler, otherwise PETSC_ERROR_REPEAT - ctx - error handler context Level: developer Notes: Most users need not directly employ this routine and the other error handlers, but can instead use the simplified interface SETERRQ, which has the calling sequence $ SETERRQ(comm,number,n,mess) Notes for experienced users: Use PetscPushErrorHandler() to set the desired error handler. The currently available PETSc error handlers include PetscTraceBackErrorHandler(), PetscAttachDebuggerErrorHandler(), PetscAbortErrorHandler(), and PetscMPIAbortErrorHandler() Concepts: error handler^traceback Concepts: traceback^generating .seealso: PetscPushErrorHandler(), PetscAttachDebuggerErrorHandler(), PetscAbortErrorHandler() @*/ PetscErrorCode PetscTraceBackErrorHandler(MPI_Comm comm,int line,const char *fun,const char* file,const char *dir,PetscErrorCode n,PetscErrorType p,const char *mess,void *ctx) { PetscLogDouble mem,rss; PetscBool flg1 = PETSC_FALSE,flg2 = PETSC_FALSE,flg3 = PETSC_FALSE; PetscMPIInt rank = 0; PetscFunctionBegin; if (comm != PETSC_COMM_SELF) { MPI_Comm_rank(comm,&rank); } if (!rank) { if (p == PETSC_ERROR_INITIAL) { (*PetscErrorPrintf)("--------------------- Error Message ------------------------------------\n"); if (n == PETSC_ERR_MEM) { (*PetscErrorPrintf)("Out of memory. This could be due to allocating\n"); (*PetscErrorPrintf)("too large an object or bleeding by not properly\n"); (*PetscErrorPrintf)("destroying unneeded objects.\n"); PetscMallocGetCurrentUsage(&mem); PetscMemoryGetCurrentUsage(&rss); PetscOptionsGetBool(PETSC_NULL,"-malloc_dump",&flg1,PETSC_NULL); PetscOptionsGetBool(PETSC_NULL,"-malloc_log",&flg2,PETSC_NULL); PetscOptionsHasName(PETSC_NULL,"-malloc_log_threshold",&flg3); if (flg2 || flg3) { PetscMallocDumpLog(stdout); } else { (*PetscErrorPrintf)("Memory allocated %.0f Memory used by process %.0f\n",mem,rss); if (flg1) { PetscMallocDump(stdout); } else { (*PetscErrorPrintf)("Try running with -malloc_dump or -malloc_log for info.\n"); } } } else { const char *text; PetscErrorMessage(n,&text,PETSC_NULL); if (text) (*PetscErrorPrintf)("%s!\n",text); } if (mess) { (*PetscErrorPrintf)("%s!\n",mess); } (*PetscErrorPrintf)("------------------------------------------------------------------------\n"); (*PetscErrorPrintf)("%s\n",version); (*PetscErrorPrintf)("See docs/changes/index.html for recent updates.\n"); (*PetscErrorPrintf)("See docs/faq.html for hints about trouble shooting.\n"); (*PetscErrorPrintf)("See docs/index.html for manual pages.\n"); (*PetscErrorPrintf)("------------------------------------------------------------------------\n"); if (PetscErrorPrintfInitializeCalled) { (*PetscErrorPrintf)("%s on a %s named %s by %s %s\n",pname,arch,hostname,username,date); } (*PetscErrorPrintf)("Libraries linked from %s\n",PETSC_LIB_DIR); (*PetscErrorPrintf)("Configure run at %s\n",petscconfigureruntime); (*PetscErrorPrintf)("Configure options %s\n",petscconfigureoptions); (*PetscErrorPrintf)("------------------------------------------------------------------------\n"); } /* print line of stack trace */ (*PetscErrorPrintf)("%s() line %d in %s%s\n",fun,line,dir,file); } else { /* do not print error messages since process 0 will print them, sleep before aborting so will not accidently kill process 0*/ PetscSleep(10.0); abort(); } PetscFunctionReturn(n); }
/*@C PetscFinalize - Checks for options to be called at the conclusion of the program. MPI_Finalize() is called only if the user had not called MPI_Init() before calling PetscInitialize(). Collective on PETSC_COMM_WORLD Options Database Keys: + -options_table - Calls PetscOptionsView() . -options_left - Prints unused options that remain in the database . -objects_dump [all] - Prints list of objects allocated by the user that have not been freed, the option all cause all outstanding objects to be listed . -mpidump - Calls PetscMPIDump() . -malloc_dump - Calls PetscMallocDump() . -malloc_info - Prints total memory usage - -malloc_log - Prints summary of memory usage Level: beginner Note: See PetscInitialize() for more general runtime options. .seealso: PetscInitialize(), PetscOptionsView(), PetscMallocDump(), PetscMPIDump(), PetscEnd() @*/ PetscErrorCode PetscFinalize(void) { PetscErrorCode ierr; PetscMPIInt rank; PetscInt nopt; PetscBool flg1 = PETSC_FALSE,flg2 = PETSC_FALSE,flg3 = PETSC_FALSE; #if defined(PETSC_HAVE_AMS) PetscBool flg = PETSC_FALSE; #endif #if defined(PETSC_USE_LOG) char mname[PETSC_MAX_PATH_LEN]; #endif PetscFunctionBegin; if (!PetscInitializeCalled) { printf("PetscInitialize() must be called before PetscFinalize()\n"); PetscFunctionReturn(PETSC_ERR_ARG_WRONGSTATE); } ierr = PetscInfo(NULL,"PetscFinalize() called\n");CHKERRQ(ierr); #if defined(PETSC_SERIALIZE_FUNCTIONS) ierr = PetscFPTDestroy();CHKERRQ(ierr); #endif #if defined(PETSC_HAVE_AMS) ierr = PetscOptionsGetBool(NULL,"-options_gui",&flg,NULL);CHKERRQ(ierr); if (flg) { ierr = PetscOptionsAMSDestroy();CHKERRQ(ierr); } #endif #if defined(PETSC_HAVE_SERVER) flg1 = PETSC_FALSE; ierr = PetscOptionsGetBool(NULL,"-server",&flg1,NULL);CHKERRQ(ierr); if (flg1) { /* this is a crude hack, but better than nothing */ ierr = PetscPOpen(PETSC_COMM_WORLD,NULL,"pkill -9 petscwebserver","r",NULL);CHKERRQ(ierr); } #endif ierr = PetscHMPIFinalize();CHKERRQ(ierr); ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); ierr = PetscOptionsGetBool(NULL,"-malloc_info",&flg2,NULL);CHKERRQ(ierr); if (!flg2) { flg2 = PETSC_FALSE; ierr = PetscOptionsGetBool(NULL,"-memory_info",&flg2,NULL);CHKERRQ(ierr); } if (flg2) { ierr = PetscMemoryShowUsage(PETSC_VIEWER_STDOUT_WORLD,"Summary of Memory Usage in PETSc\n");CHKERRQ(ierr); } #if defined(PETSC_USE_LOG) flg1 = PETSC_FALSE; ierr = PetscOptionsGetBool(NULL,"-get_total_flops",&flg1,NULL);CHKERRQ(ierr); if (flg1) { PetscLogDouble flops = 0; ierr = MPI_Reduce(&petsc_TotalFlops,&flops,1,MPI_DOUBLE,MPI_SUM,0,PETSC_COMM_WORLD);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"Total flops over all processors %g\n",flops);CHKERRQ(ierr); } #endif #if defined(PETSC_USE_LOG) #if defined(PETSC_HAVE_MPE) mname[0] = 0; ierr = PetscOptionsGetString(NULL,"-log_mpe",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr); if (flg1) { if (mname[0]) {ierr = PetscLogMPEDump(mname);CHKERRQ(ierr);} else {ierr = PetscLogMPEDump(0);CHKERRQ(ierr);} } #endif mname[0] = 0; ierr = PetscOptionsGetString(NULL,"-log_summary",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr); if (flg1) { PetscViewer viewer; if (mname[0]) { ierr = PetscViewerASCIIOpen(PETSC_COMM_WORLD,mname,&viewer);CHKERRQ(ierr); ierr = PetscLogView(viewer);CHKERRQ(ierr); ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); } else { viewer = PETSC_VIEWER_STDOUT_WORLD; ierr = PetscLogView(viewer);CHKERRQ(ierr); } } mname[0] = 0; ierr = PetscOptionsGetString(NULL,"-log_summary_python",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr); if (flg1) { PetscViewer viewer; if (mname[0]) { ierr = PetscViewerASCIIOpen(PETSC_COMM_WORLD,mname,&viewer);CHKERRQ(ierr); ierr = PetscLogViewPython(viewer);CHKERRQ(ierr); ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); } else { viewer = PETSC_VIEWER_STDOUT_WORLD; ierr = PetscLogViewPython(viewer);CHKERRQ(ierr); } } ierr = PetscOptionsGetString(NULL,"-log_detailed",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr); if (flg1) { if (mname[0]) {ierr = PetscLogPrintDetailed(PETSC_COMM_WORLD,mname);CHKERRQ(ierr);} else {ierr = PetscLogPrintDetailed(PETSC_COMM_WORLD,0);CHKERRQ(ierr);} } mname[0] = 0; ierr = PetscOptionsGetString(NULL,"-log_all",mname,PETSC_MAX_PATH_LEN,&flg1);CHKERRQ(ierr); ierr = PetscOptionsGetString(NULL,"-log",mname,PETSC_MAX_PATH_LEN,&flg2);CHKERRQ(ierr); if (flg1 || flg2) { if (mname[0]) PetscLogDump(mname); else PetscLogDump(0); } #endif /* Free all objects registered with PetscObjectRegisterDestroy() such as PETSC_VIEWER_XXX_(). */ ierr = PetscObjectRegisterDestroyAll();CHKERRQ(ierr); ierr = PetscStackDestroy();CHKERRQ(ierr); flg1 = PETSC_FALSE; ierr = PetscOptionsGetBool(NULL,"-no_signal_handler",&flg1,NULL);CHKERRQ(ierr); if (!flg1) { ierr = PetscPopSignalHandler();CHKERRQ(ierr);} flg1 = PETSC_FALSE; ierr = PetscOptionsGetBool(NULL,"-mpidump",&flg1,NULL);CHKERRQ(ierr); if (flg1) { ierr = PetscMPIDump(stdout);CHKERRQ(ierr); } flg1 = PETSC_FALSE; flg2 = PETSC_FALSE; /* preemptive call to avoid listing this option in options table as unused */ ierr = PetscOptionsHasName(NULL,"-malloc_dump",&flg1);CHKERRQ(ierr); ierr = PetscOptionsHasName(NULL,"-objects_dump",&flg1);CHKERRQ(ierr); ierr = PetscOptionsGetBool(NULL,"-options_table",&flg2,NULL);CHKERRQ(ierr); if (flg2) { PetscViewer viewer; ierr = PetscViewerASCIIGetStdout(PETSC_COMM_WORLD,&viewer);CHKERRQ(ierr); ierr = PetscOptionsView(viewer);CHKERRQ(ierr); ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); } /* to prevent PETSc -options_left from warning */ ierr = PetscOptionsHasName(NULL,"-nox",&flg1);CHKERRQ(ierr); ierr = PetscOptionsHasName(NULL,"-nox_warning",&flg1);CHKERRQ(ierr); if (!PetscHMPIWorker) { /* worker processes skip this because they do not usually process options */ flg3 = PETSC_FALSE; /* default value is required */ ierr = PetscOptionsGetBool(NULL,"-options_left",&flg3,&flg1);CHKERRQ(ierr); ierr = PetscOptionsAllUsed(&nopt);CHKERRQ(ierr); if (flg3) { if (!flg2) { /* have not yet printed the options */ PetscViewer viewer; ierr = PetscViewerASCIIGetStdout(PETSC_COMM_WORLD,&viewer);CHKERRQ(ierr); ierr = PetscOptionsView(viewer);CHKERRQ(ierr); ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); } if (!nopt) { ierr = PetscPrintf(PETSC_COMM_WORLD,"There are no unused options.\n");CHKERRQ(ierr); } else if (nopt == 1) { ierr = PetscPrintf(PETSC_COMM_WORLD,"There is one unused database option. It is:\n");CHKERRQ(ierr); } else { ierr = PetscPrintf(PETSC_COMM_WORLD,"There are %D unused database options. They are:\n",nopt);CHKERRQ(ierr); } } #if defined(PETSC_USE_DEBUG) if (nopt && !flg3 && !flg1) { ierr = PetscPrintf(PETSC_COMM_WORLD,"WARNING! There are options you set that were not used!\n");CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"WARNING! could be spelling mistake, etc!\n");CHKERRQ(ierr); ierr = PetscOptionsLeft();CHKERRQ(ierr); } else if (nopt && flg3) { #else if (nopt && flg3) { #endif ierr = PetscOptionsLeft();CHKERRQ(ierr); } } { PetscThreadComm tcomm_world; ierr = PetscGetThreadCommWorld(&tcomm_world);CHKERRQ(ierr); /* Free global thread communicator */ ierr = PetscThreadCommDestroy(&tcomm_world);CHKERRQ(ierr); } /* List all objects the user may have forgot to free */ ierr = PetscOptionsHasName(NULL,"-objects_dump",&flg1);CHKERRQ(ierr); if (flg1) { MPI_Comm local_comm; char string[64]; ierr = PetscOptionsGetString(NULL,"-objects_dump",string,64,NULL);CHKERRQ(ierr); ierr = MPI_Comm_dup(MPI_COMM_WORLD,&local_comm);CHKERRQ(ierr); ierr = PetscSequentialPhaseBegin_Private(local_comm,1);CHKERRQ(ierr); ierr = PetscObjectsDump(stdout,(string[0] == 'a') ? PETSC_TRUE : PETSC_FALSE);CHKERRQ(ierr); ierr = PetscSequentialPhaseEnd_Private(local_comm,1);CHKERRQ(ierr); ierr = MPI_Comm_free(&local_comm);CHKERRQ(ierr); } PetscObjectsCounts = 0; PetscObjectsMaxCounts = 0; ierr = PetscFree(PetscObjects);CHKERRQ(ierr); #if defined(PETSC_USE_LOG) ierr = PetscLogDestroy();CHKERRQ(ierr); #endif /* Destroy any packages that registered a finalize */ ierr = PetscRegisterFinalizeAll();CHKERRQ(ierr); /* Destroy all the function registration lists created */ ierr = PetscFinalize_DynamicLibraries();CHKERRQ(ierr); /* Print PetscFunctionLists that have not been properly freed ierr = PetscFunctionListPrintAll();CHKERRQ(ierr); */ if (petsc_history) { ierr = PetscCloseHistoryFile(&petsc_history);CHKERRQ(ierr); petsc_history = 0; } ierr = PetscInfoAllow(PETSC_FALSE,NULL);CHKERRQ(ierr); { char fname[PETSC_MAX_PATH_LEN]; FILE *fd; int err; fname[0] = 0; ierr = PetscOptionsGetString(NULL,"-malloc_dump",fname,250,&flg1);CHKERRQ(ierr); flg2 = PETSC_FALSE; ierr = PetscOptionsGetBool(NULL,"-malloc_test",&flg2,NULL);CHKERRQ(ierr); #if defined(PETSC_USE_DEBUG) if (PETSC_RUNNING_ON_VALGRIND) flg2 = PETSC_FALSE; #else flg2 = PETSC_FALSE; /* Skip reporting for optimized builds regardless of -malloc_test */ #endif if (flg1 && fname[0]) { char sname[PETSC_MAX_PATH_LEN]; sprintf(sname,"%s_%d",fname,rank); fd = fopen(sname,"w"); if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open log file: %s",sname); ierr = PetscMallocDump(fd);CHKERRQ(ierr); err = fclose(fd); if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file"); } else if (flg1 || flg2) { MPI_Comm local_comm; ierr = MPI_Comm_dup(MPI_COMM_WORLD,&local_comm);CHKERRQ(ierr); ierr = PetscSequentialPhaseBegin_Private(local_comm,1);CHKERRQ(ierr); ierr = PetscMallocDump(stdout);CHKERRQ(ierr); ierr = PetscSequentialPhaseEnd_Private(local_comm,1);CHKERRQ(ierr); ierr = MPI_Comm_free(&local_comm);CHKERRQ(ierr); } } { char fname[PETSC_MAX_PATH_LEN]; FILE *fd = NULL; fname[0] = 0; ierr = PetscOptionsGetString(NULL,"-malloc_log",fname,250,&flg1);CHKERRQ(ierr); ierr = PetscOptionsHasName(NULL,"-malloc_log_threshold",&flg2);CHKERRQ(ierr); if (flg1 && fname[0]) { int err; if (!rank) { fd = fopen(fname,"w"); if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open log file: %s",fname); } ierr = PetscMallocDumpLog(fd);CHKERRQ(ierr); if (fd) { err = fclose(fd); if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file"); } } else if (flg1 || flg2) { ierr = PetscMallocDumpLog(stdout);CHKERRQ(ierr); } } /* Can be destroyed only after all the options are used */ ierr = PetscOptionsDestroy();CHKERRQ(ierr); PetscGlobalArgc = 0; PetscGlobalArgs = 0; #if defined(PETSC_USE_REAL___FLOAT128) ierr = MPI_Type_free(&MPIU___FLOAT128);CHKERRQ(ierr); #if defined(PETSC_HAVE_COMPLEX) ierr = MPI_Type_free(&MPIU___COMPLEX128);CHKERRQ(ierr); #endif ierr = MPI_Op_free(&MPIU_MAX);CHKERRQ(ierr); ierr = MPI_Op_free(&MPIU_MIN);CHKERRQ(ierr); #endif #if defined(PETSC_HAVE_COMPLEX) #if !defined(PETSC_HAVE_MPI_C_DOUBLE_COMPLEX) ierr = MPI_Type_free(&MPIU_C_DOUBLE_COMPLEX);CHKERRQ(ierr); ierr = MPI_Type_free(&MPIU_C_COMPLEX);CHKERRQ(ierr); #endif #endif #if (defined(PETSC_HAVE_COMPLEX) && !defined(PETSC_HAVE_MPI_C_DOUBLE_COMPLEX)) || defined(PETSC_USE_REAL___FLOAT128) ierr = MPI_Op_free(&MPIU_SUM);CHKERRQ(ierr); #endif ierr = MPI_Type_free(&MPIU_2SCALAR);CHKERRQ(ierr); #if defined(PETSC_USE_64BIT_INDICES) || !defined(MPI_2INT) ierr = MPI_Type_free(&MPIU_2INT);CHKERRQ(ierr); #endif ierr = MPI_Op_free(&PetscMaxSum_Op);CHKERRQ(ierr); ierr = MPI_Op_free(&PetscADMax_Op);CHKERRQ(ierr); ierr = MPI_Op_free(&PetscADMin_Op);CHKERRQ(ierr); /* Destroy any known inner MPI_Comm's and attributes pointing to them Note this will not destroy any new communicators the user has created. If all PETSc objects were not destroyed those left over objects will have hanging references to the MPI_Comms that were freed; but that is ok because those PETSc objects will never be used again */ { PetscCommCounter *counter; PetscMPIInt flg; MPI_Comm icomm; union {MPI_Comm comm; void *ptr;} ucomm; ierr = MPI_Attr_get(PETSC_COMM_SELF,Petsc_InnerComm_keyval,&ucomm,&flg);CHKERRQ(ierr); if (flg) { icomm = ucomm.comm; ierr = MPI_Attr_get(icomm,Petsc_Counter_keyval,&counter,&flg);CHKERRQ(ierr); if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Inner MPI_Comm does not have expected tag/name counter, problem with corrupted memory"); ierr = MPI_Attr_delete(PETSC_COMM_SELF,Petsc_InnerComm_keyval);CHKERRQ(ierr); ierr = MPI_Attr_delete(icomm,Petsc_Counter_keyval);CHKERRQ(ierr); ierr = MPI_Comm_free(&icomm);CHKERRQ(ierr); } ierr = MPI_Attr_get(PETSC_COMM_WORLD,Petsc_InnerComm_keyval,&ucomm,&flg);CHKERRQ(ierr); if (flg) { icomm = ucomm.comm; ierr = MPI_Attr_get(icomm,Petsc_Counter_keyval,&counter,&flg);CHKERRQ(ierr); if (!flg) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_ARG_CORRUPT,"Inner MPI_Comm does not have expected tag/name counter, problem with corrupted memory"); ierr = MPI_Attr_delete(PETSC_COMM_WORLD,Petsc_InnerComm_keyval);CHKERRQ(ierr); ierr = MPI_Attr_delete(icomm,Petsc_Counter_keyval);CHKERRQ(ierr); ierr = MPI_Comm_free(&icomm);CHKERRQ(ierr); } } ierr = MPI_Keyval_free(&Petsc_Counter_keyval);CHKERRQ(ierr); ierr = MPI_Keyval_free(&Petsc_InnerComm_keyval);CHKERRQ(ierr); ierr = MPI_Keyval_free(&Petsc_OuterComm_keyval);CHKERRQ(ierr); #if defined(PETSC_HAVE_CUDA) { PetscInt p; for (p = 0; p < PetscGlobalSize; ++p) { if (p == PetscGlobalRank) cublasShutdown(); ierr = MPI_Barrier(PETSC_COMM_WORLD);CHKERRQ(ierr); } } #endif if (PetscBeganMPI) { #if defined(PETSC_HAVE_MPI_FINALIZED) PetscMPIInt flag; ierr = MPI_Finalized(&flag);CHKERRQ(ierr); if (flag) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"MPI_Finalize() has already been called, even though MPI_Init() was called by PetscInitialize()"); #endif ierr = MPI_Finalize();CHKERRQ(ierr); } /* Note: In certain cases PETSC_COMM_WORLD is never MPI_Comm_free()ed because the communicator has some outstanding requests on it. Specifically if the flag PETSC_HAVE_BROKEN_REQUEST_FREE is set (for IBM MPI implementation). See src/vec/utils/vpscat.c. Due to this the memory allocated in PetscCommDuplicate() is never freed as it should be. Thus one may obtain messages of the form [ 1] 8 bytes PetscCommDuplicate() line 645 in src/sys/mpiu.c indicating the memory was not freed. */ ierr = PetscMallocClear();CHKERRQ(ierr); PetscInitializeCalled = PETSC_FALSE; PetscFinalizeCalled = PETSC_TRUE; PetscFunctionReturn(ierr); } #if defined(PETSC_MISSING_LAPACK_lsame_) PETSC_EXTERN int lsame_(char *a,char *b) { if (*a == *b) return 1; if (*a + 32 == *b) return 1; if (*a - 32 == *b) return 1; return 0; } #endif #if defined(PETSC_MISSING_LAPACK_lsame) PETSC_EXTERN int lsame(char *a,char *b) { if (*a == *b) return 1; if (*a + 32 == *b) return 1; if (*a - 32 == *b) return 1; return 0; }