subroutine ESMF_Finalize(keywordEnforcer, endflag, rc)
!
! !ARGUMENTS:
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
type(ESMF_End_Flag), intent(in), optional :: endflag
integer, intent(out), optional :: rc
!
! !STATUS:
! \begin{itemize}
! \item\apiStatusCompatibleVersion{5.2.0r}
! \end{itemize}
!
! !DESCRIPTION:
! This must be called once on each PET before the application exits
! to allow ESMF to flush buffers, close open connections, and
! release internal resources cleanly. The optional argument
! {\tt endflag} may be used to indicate the mode of termination.
! Note that this call must be issued only once per PET with
! {\tt endflag=ESMF\_END\_NORMAL}, and that this call may not be followed
! by {\tt ESMF\_Initialize()}. This last restriction means that it is not
! possible to restart ESMF within the same execution.
!
! The arguments are:
! \begin{description}
! \item [{[endflag]}]
! Specify mode of termination. The default is {\tt ESMF\_END\_NORMAL}
! which waits for all PETs of the global VM to reach
! {\tt ESMF\_Finalize()} before termination. See section
! \ref{const:endflag} for a complete list and description of
! valid flags.
! \item [{[rc]}]
! Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!
!EOP
logical :: rcpresent ! Return code present
logical :: abortFlag
type(ESMF_Logical) :: keepMpiFlag
integer :: localrc
character(ESMF_MAXSTR) :: errmsg, msgStr
integer :: errmsg_l
logical, save :: already_final = .false. ! Static, maintains state.
integer :: traceIsOn, profileIsOn
! Initialize return code
rcpresent = .FALSE.
if(present(rc)) then
rcpresent = .TRUE.
rc = ESMF_RC_NOT_IMPL
endif
abortFlag = .false.
keepMpiFlag = ESMF_FALSE
if (present(endflag)) then
if (endflag==ESMF_END_ABORT) abortFlag = .true.
if (endflag==ESMF_END_KEEPMPI) keepMpiFlag = ESMF_TRUE
endif
if (already_final) then
if (rcpresent) rc = ESMF_SUCCESS
return
endif
! Write final message to the log
write(msgStr,*) "Finalizing ESMF"
if (abortFlag) &
write(msgStr,*) "Finalizing ESMF with endflag==ESMF_END_ABORT"
if (keepMpiFlag==ESMF_TRUE) &
write(msgStr,*) "Finalizing ESMF with endflag==ESMF_END_KEEPMPI"
call ESMF_LogWrite(trim(msgStr), ESMF_LOGMSG_INFO, rc=localrc)
if (localrc /= ESMF_SUCCESS) then
write (ESMF_UtilIOStderr,*) ESMF_METHOD, ": Error writing into the default log"
endif
call c_esmc_getComplianceCheckTrace(traceIsOn, profileIsOn, localrc)
if (localrc /= ESMF_SUCCESS) then
write (ESMF_UtilIOStderr,*) ESMF_METHOD, ": Error checking ESMF_RUNTIME_* env variables"
endif
if (traceIsOn == 1 .or. profileIsOn == 1) then
call ESMF_TraceClose(rc=localrc)
if (localrc /= ESMF_SUCCESS) then
write (ESMF_UtilIOStderr,*) ESMF_METHOD, ": Error closing trace stream"
endif
endif
#ifdef LOG_FINALIZE
call ESMF_LogWrite("Done closing ESMF_Trace", &
ESMF_LOGMSG_INFO, rc=localrc)
if (localrc /= ESMF_SUCCESS) then
write (ESMF_UtilIOStderr,*) ESMF_METHOD, ": Error writing into the default log"
endif
#endif
! Close the Config file
! TODO: write this routine and remove the status= line
! call ESMF_ConfigFinalize(localrc)
localrc = ESMF_SUCCESS
if (localrc /= ESMF_SUCCESS) then
call ESMF_LogRc2Msg (localrc, errmsg, errmsg_l)
write (ESMF_UtilIOStderr,*) ESMF_METHOD, &
": Error finalizing config file: ", errmsg(:errmsg_l)
endif
! Delete any internal built-in time manager calendars
call ESMF_CalendarFinalize(rc=localrc)
if (localrc /= ESMF_SUCCESS) then
call ESMF_LogRc2Msg (localrc, errmsg, errmsg_l)
write (ESMF_UtilIOStderr,*) ESMF_METHOD, &
": Error finalizing the time manager calendars"
endif
#ifdef LOG_FINALIZE
call ESMF_LogWrite("Done finalizing ESMF_Calendar", &
ESMF_LOGMSG_INFO, rc=localrc)
if (localrc /= ESMF_SUCCESS) then
write (ESMF_UtilIOStderr,*) ESMF_METHOD, ": Error writing into the default log"
endif
#endif
! Flush log to avoid lost messages
call ESMF_LogFlush (rc=localrc)
if (localrc /= ESMF_SUCCESS) then
call ESMF_LogRc2Msg (localrc, errmsg, errmsg_l)
write (ESMF_UtilIOStderr,*) ESMF_METHOD, &
": Error flushing log file: ", errmsg(:errmsg_l)
end if
#ifdef LOG_FINALIZE
call ESMF_LogWrite("Done flushing ESMF_Log", &
ESMF_LOGMSG_INFO, rc=localrc)
if (localrc /= ESMF_SUCCESS) then
write (ESMF_UtilIOStderr,*) ESMF_METHOD, ": Error writing into the default log"
endif
#endif
if (abortFlag) then
! Abort the VM
call ESMF_VMAbort(rc=localrc)
if (localrc /= ESMF_SUCCESS) then
call ESMF_LogRc2Msg (localrc, errmsg, errmsg_l)
write (ESMF_UtilIOStderr,*) ESMF_METHOD, &
": Error aborting VM: ", errmsg(:errmsg_l)
return
endif
else
! Finalize the VM
call ESMF_VMFinalize(keepMpiFlag=keepMpiFlag, rc=localrc)
if (localrc /= ESMF_SUCCESS) then
call ESMF_LogRc2Msg (localrc, errmsg, errmsg_l)
write (ESMF_UtilIOStderr,*) ESMF_METHOD, &
": Error finalizing VM: ", errmsg(:errmsg_l)
return
endif
endif
#ifdef LOG_FINALIZE
call ESMF_LogWrite("Done finalizing ESMF_VM", &
ESMF_LOGMSG_INFO, rc=localrc)
if (localrc /= ESMF_SUCCESS) then
write (ESMF_UtilIOStderr,*) ESMF_METHOD, ": Error writing into the default log"
endif
#endif
! Shut down the log file
call ESMF_LogFinalize(localrc)
if (localrc /= ESMF_SUCCESS) then
call ESMF_LogRc2Msg (localrc, errmsg, errmsg_l)
write (ESMF_UtilIOStderr,*) ESMF_METHOD, &
": Error finalizing log file: ", errmsg(:errmsg_l)
return
endif
already_final = .true.
if (rcpresent) rc = ESMF_SUCCESS
end subroutine ESMF_Finalize