Files
GEOS-Chem-adjoint-v35-note/code/error_mod.f
2018-08-28 00:43:47 -04:00

1144 lines
37 KiB
Fortran

! $Id: error_mod.f,v 1.2 2011/02/23 00:08:47 daven Exp $
!------------------------------------------------------------------------------
! Harvard University Atmospheric Chemistry Modeling Group !
!------------------------------------------------------------------------------
!BOP
!
! !MODULE: error_mod.f
!
! !DESCRIPTION: Module ERROR\_MOD contains error checking routines.
!\\
!\\
! !INTERFACE:
!
MODULE ERROR_MOD
!
! !USES:
!
IMPLICIT NONE
PRIVATE
!
! !PUBLIC MEMBER FUNCTIONS:
!
PUBLIC :: ALLOC_ERR
PUBLIC :: CHECK_VALUE
PUBLIC :: DEBUG_MSG
PUBLIC :: ERROR_STOP
PUBLIC :: GEOS_CHEM_STOP
PUBLIC :: IS_SAFE_DIV
PUBLIC :: IS_SAFE_EXP
PUBLIC :: IT_IS_NAN
PUBLIC :: IT_IS_FINITE
PUBLIC :: SAFE_DIV
PUBLIC :: SAFE_EXP
PUBLIC :: SAFE_LOG
PUBLIC :: SAFE_LOG10
! Interface for NaN-check routines
INTERFACE IT_IS_NAN
MODULE PROCEDURE NAN_FLOAT
MODULE PROCEDURE NAN_DBLE
END INTERFACE
! Interface for finite-check routines
INTERFACE IT_IS_FINITE
MODULE PROCEDURE FINITE_FLOAT
MODULE PROCEDURE FINITE_DBLE
END INTERFACE
! Interface for check-value routines
INTERFACE CHECK_VALUE
MODULE PROCEDURE CHECK_REAL_VALUE
MODULE PROCEDURE CHECK_DBLE_VALUE
END INTERFACE
!
! !PRIVATE MEMBER FUNCTIONS:
!
PRIVATE :: CHECK_DBLE_VALUE
PRIVATE :: CHECK_REAL_VALUE
PRIVATE :: FINITE_DBLE
PRIVATE :: FINITE_FLOAT
PRIVATE :: NAN_DBLE
PRIVATE :: NAN_FLOAT
!
! !REVISION HISTORY:
! 08 Mar 2001 - R. Yantosca - Initial version
! (1 ) Added subroutines CHECK_REAL_VALUE and CHECK_DBLE_VALUE, which are
! overloaded by interface CHECK_VALUE. This is a convenience
! so that you don't have to always call IT_IS_NAN directly.
! (bmy, 6/13/01)
! (2 ) Updated comments (bmy, 9/4/01)
! (3 ) Now use correct values for bit masking in FINITE_FLOAT for the
! ALPHA platform (bmy, 11/15/01)
! (4 ) Now divide module header into MODULE PRIVATE, MODULE VARIABLES, and
! MODULE ROUTINES sections. Also add MODULE INTERFACES section,
! since we have an interface here. (bmy, 5/28/02)
! (5 ) Add NaN and infinity error checking for Linux platform (bmy, 3/22/02)
! (6 ) Added routines ERROR_STOP, GEOS_CHEM_STOP, and ALLOC_ERR to this
! module. Also improved CHECK_STT. (bmy, 11/27/02)
! (7 ) Minor bug fixes in FORMAT statements. Renamed cpp switch from
! DEC_COMPAQ to COMPAQ. Also added code to trap errors on SUN
! platform. (bmy, 3/21/03)
! (8 ) Added patches for IBM/AIX platform (gcc, bmy, 6/27/03)
! (9 ) Bug fixes for LINUX platform (bmy, 9/29/03)
! (10) Now supports INTEL_FC compiler (bmy, 10/24/03)
! (11) Changed the name of some cpp switches in "define.h" (bmy, 12/2/03)
! (12) Minor fix for LINUX_IFC and LINUX_EFC (bmy, 1/24/04)
! (13) Do not flush buffer for LINUX_EFC in ERROR_STOP (bmy, 4/6/04)
! (14) Move CHECK_STT routine to "tracer_mod.f" (bmy, 7/20/04)
! (15) Added LINUX_IFORT switch for Intel v8 and v9 compilers (bmy, 10/18/05)
! (16) Now print IFORT error messages for Intel v8/v9 compiler (bmy, 11/30/05)
! (17) Cosmetic change in DEBUG_MSG (bmy, 4/10/06)
! (18) Remove support for LINUX_IFC and LINUX_EFC compilers (bmy, 8/4/06)
! (19) Now use intrinsic functions for IFORT, remove C routines (bmy, 8/14/07)
! (20) Added routine SAFE_DIV (phs, bmy, 2/26/08)
! (21) Added routine IS_SAFE_DIV (phs, bmy, 6/11/08)
! (22) Updated routine SAFE_DIV (phs, 4/14/09)
! (23) Remove support for SGI, COMPAQ compilers (bmy, 7/8/09)
! 20 Nov 2009 - R. Yantosca - Added ProTeX header
! 04 Jan 2010 - R. Yantosca - Added SAFE_EXP and IS_SAFE_EXP functions
! 04 Jan 2010 - R. Yantosca - Added SAVE_LOG and SAFE_LOG10 functions
!EOP
!------------------------------------------------------------------------------
!BOC
CONTAINS
!EOC
!------------------------------------------------------------------------------
! Harvard University Atmospheric Chemistry Modeling Group !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: nan_float
!
! !DESCRIPTION: Function NAN\_FLOAT returns TRUE if a REAL*4 number is equal
! to the IEEE NaN (Not-a-Number) flag. Returns FALSE otherwise.
!\\
!\\
! !INTERFACE:
!
FUNCTION NAN_FLOAT( VALUE ) RESULT( IT_IS_A_NAN )
!
! !USES:
!
# include "define.h"
#if defined( IBM_AIX ) || defined( IBM_XLF )
USE IEEE_ARITHMETIC
#endif
!
! !INPUT PARAMETERS:
!
REAL*4, INTENT(IN) :: VALUE ! Value to be tested for NaN
!
! !RETURN VALUE:
!
LOGICAL :: IT_IS_A_NAN ! =T if VALUE is NaN; =F otherwise
!
! !REVISION HISTORY:
! (1 ) Is overloaded by interface "IT_IS_NAN".
! (2 ) Now call C routine is_nan(x) for Linux platform (bmy, 6/13/02)
! (3 ) Eliminate IF statement in Linux section. Also now trap NaN on
! the Sun/Sparc platform. Rename cpp switch from DEC_COMPAQ to
! COMPAQ. (bmy, 3/23/03)
! (4 ) Added patches for IBM/AIX platform (gcc, bmy, 6/27/03)
! (5 ) Use LINUX error-trapping for INTEL_FC (bmy, 10/24/03)
! (6 ) Renamed SGI to SGI_MIPS, LINUX to LINUX_PGI, INTEL_FC to INTEL_IFC,
! and added LINUX_EFC. (bmy, 12/2/03)
! (7 ) Added LINUX_IFORT switch for Intel v8 and v9 compilers (bmy, 10/18/05)
! (8 ) Remove support for LINUX_IFC & LINUX_EFC compilers (bmy, 8/4/06)
! (9 ) Now use ISNAN for Linux/IFORT compiler (bmy, 8/14/07)
! (10) Remove support for SGI, COMPAQ compilers. Add IBM_XLF switch.
! (bmy, 7/8/09)
! 20 Nov 2009 - R. Yantosca - Added ProTeX header
!EOP
!------------------------------------------------------------------------------
!BOC
#if defined( LINUX_IFORT )
IT_IS_A_NAN = ISNAN( VALUE )
#elif defined( LINUX_PGI )
! Declare IS_NAN as an external function
INTEGER, EXTERNAL :: IS_NAN
! For LINUX or INTEL_FC compilers, use C routine "is_nan" to test if
! VALUE is NaN. VALUE must be cast to DBLE since "is_nan" only
! takes doubles.
IT_IS_A_NAN = ( IS_NAN( DBLE( VALUE ) ) /= 0 )
#elif defined( SPARC )
!-----------------------------------------------------------------------------
! NOTE: If you compile with SunStudio11/12 with the -fast optimization, this
! will turn on -ftrap=common, which checks for NaN, invalid, division, and
! inexact IEEE math errors. (bmy, 12/18/07)
!
! ! Declare IR_ISNAN as an external function
! INTEGER, EXTERNAL :: IR_ISNAN
!
! ! Test if VALUE is a NaN
! IT_IS_A_NAN = ( IR_ISNAN( VALUE ) /= 0 )
!-----------------------------------------------------------------------------
IT_IS_A_NAN = .FALSE.
#elif defined( IBM_AIX ) || defined( IBM_XLF )
! For IBM/AIX platform
IF ( IEEE_SUPPORT_DATATYPE( VALUE ) ) THEN
IT_IS_A_NAN = IEEE_IS_NAN( VALUE )
ENDIF
#endif
! Return to calling program
END FUNCTION NAN_FLOAT
!EOC
!------------------------------------------------------------------------------
! Harvard University Atmospheric Chemistry Modeling Group !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: nan_dble
!
! !DESCRIPTION: Function NAN\_DBLE returns TRUE if a REAL*8 number is equal
! to the IEEE NaN (Not-a-Number) flag. Returns FALSE otherwise.
!\\
!\\
! !INTERFACE:
!
FUNCTION NAN_DBLE( VALUE ) RESULT( IT_IS_A_NAN )
!
! !USES:
!
# include "define.h"
#if defined( IBM_AIX ) || defined( IBM_XLF )
USE IEEE_ARITHMETIC
#endif
!
! !INPUT PARAMETERS:
!
REAL*8, INTENT(IN) :: VALUE ! Value to be tested for NaN
!
! !RETURN VALUE:
!
LOGICAL :: IT_IS_A_NAN ! =T if VALUE is NaN; =F otherwise
!
! !REVISION HISTORY:
! (1 ) Is overloaded by interface "IT_IS_NAN".
! (2 ) Now call C routine is_nan(x) for Linux platform (bmy, 6/13/02)
! (3 ) Eliminate IF statement in Linux section. Also now trap NaN on
! the Sun/Sparc platform. Rename cpp switch from DEC_COMPAQ to
! COMPAQ. (bmy, 3/23/03)
! (4 ) Added patches for IBM/AIX platform (gcc, bmy, 6/27/03)
! (5 ) Use LINUX error-trapping for INTEL_FC (bmy, 10/24/03)
! (6 ) Renamed SGI to SGI_MIPS, LINUX to LINUX_PGI, INTEL_FC to INTEL_IFC,
! and added LINUX_EFC. (bmy, 12/2/03)
! (7 ) Added LINUX_IFORT switch for Intel v8 and v9 compilers (bmy, 10/18/05)
! (8 ) Remove support for LINUX_IFC & LINUX_EFC compilers (bmy, 8/4/06)
! (9 ) Now use ISNAN for Linux/IFORT compiler (bmy, 8/14/07)
! (10) Remove support for SGI, COMPAQ compilers. Add IBM_XLF switch.
! (bmy, 7/8/09)
! 20 Nov 2009 - R. Yantosca - Added ProTeX header
!EOP
!------------------------------------------------------------------------------
!BOC
!
#if defined( LINUX_IFORT )
IT_IS_A_NAN = ISNAN( VALUE )
#elif defined( LINUX_PGI )
! Declare IS_NAN as an external function
INTEGER, EXTERNAL :: IS_NAN
! For LINUX or INTEL_FC compilers, use C routine
! "is_nan" to test if VALUE is NaN.
IT_IS_A_NAN = ( IS_NAN( VALUE ) /= 0 )
#elif defined( SPARC )
!-----------------------------------------------------------------------------
! NOTE: If you compile with SunStudio11/12 with the -fast optimization, this
! will turn on -ftrap=common, which checks for NaN, invalid, division, and
! inexact IEEE math errors. (bmy, 12/18/07)
!
! ! Declare ID_ISNAN as an external function
! INTEGER, EXTERNAL :: ID_ISNAN
!
! ! Test if VALUE is NaN
! IT_IS_A_NAN = ( ID_ISNAN( VALUE ) /= 0 )
!-----------------------------------------------------------------------------
IT_IS_A_NAN = .FALSE.
#elif defined( IBM_AIX ) || defined( IBM_XLF )
! For IBM/AIX platform
IF ( IEEE_SUPPORT_DATATYPE( VALUE ) ) THEN
IT_IS_A_NAN = IEEE_IS_NAN( VALUE )
ENDIF
#endif
! Return to calling program
END FUNCTION NAN_DBLE
!EOC
!------------------------------------------------------------------------------
! Harvard University Atmospheric Chemistry Modeling Group !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: finite_float
!
! !DESCRIPTION: Function FINITE\_FLOAT returns FALSE if a REAL*4 number is
! equal to the IEEE Infinity flag. Returns TRUE otherwise.
!\\
!\\
! !INTERFACE:
!
FUNCTION FINITE_FLOAT( VALUE ) RESULT( IT_IS_A_FINITE )
!
! !USES:
!
# include "define.h"
#if defined( IBM_AIX ) || defined( IBM_XLF )
USE IEEE_ARITHMETIC
#endif
!
! !INPUT PARAMETERS:
!
REAL*4, INTENT(IN) :: VALUE ! Value to be tested for infinity
!
! !RETURN VALUE:
!
LOGICAL :: IT_IS_A_FINITE ! =T if VALUE is finite; =F else
!
! !REVISION HISTORY:
! (1 ) Is overloaded by interface "IT_IS_FINITE".
! (2 ) Now use correct values for bit masking (bmy, 11/15/01)
! (3 ) Eliminate IF statement in Linux section. Also now trap Infinity on
! the Sun/Sparc platform. Rename cpp switch from DEC_COMPAQ to
! COMPAQ. (bmy, 3/23/03)
! (4 ) Added patches for IBM/AIX platform (gcc, bmy, 6/27/03)
! (5 ) Bug fix: now use external C IS_FINITE for PGI/Linux (bmy, 9/29/03)
! (6 ) Use LINUX error-trapping for INTEL_FC (bmy, 10/24/03)
! (7 ) Renamed SGI to SGI_MIPS, LINUX to LINUX_PGI, INTEL_FC to INTEL_IFC,
! and added LINUX_EFC. (bmy, 12/2/03)
! (8 ) Added LINUX_IFORT switch for Intel v8 and v9 compilers (bmy, 10/18/05)
! (9 ) Remove support for LINUX_IFC & LINUX_EFC compilers (bmy, 8/4/06)
! (10) Now use FP_CLASS for IFORT compiler (bmy, 8/14/07)
! (11) Remove support for SGI, COMPAQ compilers. Add IBM_XLF switch.
! (bmy, 7/8/09)
! 20 Nov 2009 - R. Yantosca - Added ProTeX header
!EOP
!------------------------------------------------------------------------------
!BOC
#if defined( LINUX_IFORT )
! Local variables (parameters copied from "fordef.for")
INTEGER, PARAMETER :: SNAN=0, QNAN=1, POS_INF=2, NEG_INF=3
INTEGER :: FPC
! Get the floating point type class for VALUE
FPC = FP_CLASS( VALUE )
! VALUE is infinite if it is either +Inf or -Inf
! Also flag an error if VALUE is a signaling or quiet NaN
IT_IS_A_FINITE = ( FPC /= POS_INF .and. FPC /= NEG_INF .and.
& FPC /= SNAN .and. FPC /= QNAN )
#elif defined( LINUX_PGI )
! Declare IS_FINITE as an external function
INTEGER, EXTERNAL :: IS_FINITE
! For LINUX or INTEL_FC compilers use C routine "is_finite" to test
! if VALUE is finite. VALUE must be cast to DBLE since "is_inf"
! only takes doubles.
IT_IS_A_FINITE = ( IS_FINITE( DBLE( VALUE ) ) /= 0 )
#elif defined( SPARC )
!-----------------------------------------------------------------------------
! NOTE: If you compile with SunStudio11/12 with the -fast optimization, this
! will turn on -ftrap=common, which checks for NaN, invalid, division, and
! inexact IEEE math errors. (bmy, 12/18/07)
! ! Declare IR_FINITE as an external function
! INTEGER, EXTERNAL :: IR_FINITE
!
! ! Test if VALUE is a finite number
! IT_IS_A_FINITE = ( IR_FINITE( VALUE ) /= 0 )
!-----------------------------------------------------------------------------
IT_IS_A_FINITE = .TRUE.
#elif defined( IBM_AIX ) || defined( IBM_XLF )
! For IBM/AIX platform
IF ( IEEE_SUPPORT_DATATYPE( VALUE ) ) THEN
IT_IS_A_FINITE = IEEE_IS_FINITE( VALUE )
ENDIF
#endif
! Return to calling program
END FUNCTION FINITE_FLOAT
!EOC
!------------------------------------------------------------------------------
! Harvard University Atmospheric Chemistry Modeling Group !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: finite_dble
!
! !DESCRIPTION: Function FINITE\_FLOAT returns FALSE if a REAL*8 number is
! equal to the IEEE Infinity flag. Returns TRUE otherwise.
!\\
!\\
! !INTERFACE:
!
FUNCTION FINITE_DBLE( VALUE ) RESULT( IT_IS_A_FINITE )
!
! !USES:
!
# include "define.h"
#if defined( IBM_AIX ) || defined( IBM_XLF )
USE IEEE_ARITHMETIC
#endif
!
! !INPUT PARAMETERS:
!
REAL*8, INTENT(IN) :: VALUE ! Value to be tested for infinity
!
! !RETURN VALUE:
!
LOGICAL :: IT_IS_A_FINITE ! =T if VALUE is finite; =F else
!
! !REVISION HISTORY:
! (1 ) Is overloaded by interface "IT_IS_FINITE".
! (2 ) Now use correct values for bit masking (bmy, 11/15/01)
! (3 ) Eliminate IF statement in Linux section. Also now trap Infinity on
! the Sun/Sparc platform. Rename cpp switch from DEC_COMPAQ to
! COMPAQ. (bmy, 3/23/03)
! (4 ) Added patches for IBM/AIX platform (gcc, bmy, 6/27/03)
! (5 ) Bug fix: now use external C IS_FINITE for PGI/Linux (bmy, 9/29/03)
! (6 ) Use LINUX error-trapping for INTEL_FC (bmy, 10/24/03)
! (7 ) Renamed SGI to SGI_MIPS, LINUX to LINUX_PGI, INTEL_FC to INTEL_IFC,
! and added LINUX_EFC. (bmy, 12/2/03)
! (8 ) Added LINUX_IFORT switch for Intel v8 and v9 compilers (bmy, 10/18/05)
! (9 ) Remove support for LINUX_IFC & LINUX_EFC compilers (bmy, 8/4/06)
! (10) Now use FP_CLASS for IFORT compiler (bmy, 8/14/07)
! (11) Remove support for SGI, COMPAQ compilers. Add IBM_XLF switch.
! (bmy, 7/8/09)
! 20 Nov 2009 - R. Yantosca - Added ProTeX header
!EOP
!------------------------------------------------------------------------------
!BOC
#if defined( LINUX_IFORT )
! Local variables (parameters copied from "fordef.for")
INTEGER, PARAMETER :: SNAN=0, QNAN=1, POS_INF=2, NEG_INF=3
INTEGER :: FPC
! Get the floating point type class for VALUE
FPC = FP_CLASS( VALUE )
! VALUE is infinite if it is either +Inf or -Inf
! Also flag an error if VALUE is a signaling or quiet NaN
IT_IS_A_FINITE = ( FPC /= POS_INF .and. FPC /= NEG_INF .and.
& FPC /= SNAN .and. FPC /= QNAN )
#elif defined( LINUX_PGI )
! Declare IS_FINITE as an external function
INTEGER, EXTERNAL :: IS_FINITE
! For LINUX or INTEL_FC compilers, use C routine
! "is_finite" to test if VALUE is infinity
IT_IS_A_FINITE = ( IS_FINITE( VALUE ) /= 0 )
#elif defined( SPARC )
!-----------------------------------------------------------------------------
! NOTE: If you compile with SunStudio11/12 with the -fast optimization, this
! will turn on -ftrap=common, which checks for NaN, invalid, division, and
! inexact IEEE math errors. (bmy, 12/18/07)
!
! ! Declare ID_FINITE as an external function
! INTEGER, EXTERNAL :: ID_FINITE
!
! ! Test if VALUE is a finite number
! IT_IS_A_FINITE = ( ID_FINITE( VALUE ) /= 0 )
!-----------------------------------------------------------------------------
IT_IS_A_FINITE = .TRUE.
#elif defined( IBM_AIX ) || defined( IBM_XLF )
! For IBM/AIX platform
IF ( IEEE_SUPPORT_DATATYPE( VALUE ) ) THEN
IT_IS_A_FINITE = IEEE_IS_FINITE( VALUE )
ENDIF
#endif
! Return to calling program
END FUNCTION FINITE_DBLE
!EOC
!------------------------------------------------------------------------------
! Harvard University Atmospheric Chemistry Modeling Group !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: check_real_value
!
! !DESCRIPTION: Subroutine CHECK\_REAL\_VALUE checks to make sure a REAL*4
! value is not NaN or Infinity. This is a wrapper for the interfaces
! IT\_IS\_NAN and IT\_IS\_FINITE.
!\\
!\\
! !INTERFACE:
!
SUBROUTINE CHECK_REAL_VALUE( VALUE, LOCATION, VARNAME, MESSAGE )
!
! !INPUT PARAMETERS:
!
REAL*4, INTENT(IN) :: VALUE ! Value to be checked
CHARACTER(LEN=255), INTENT(IN) :: VARNAME ! Name of variable
CHARACTER(LEN=255), INTENT(IN) :: MESSAGE ! Short descriptive msg
INTEGER, INTENT(IN) :: LOCATION(4) ! (/ I, J, L, N /) indices
!
! !REVISION HISTORY:
! 13 Jun 2001 - R. Yantosca - Initial version
! 15 Oct 2002 - R. Yantosca - Now call GEOS_CHEM_STOP to shutdown safely
! 15 Oct 2002 - R. Yantosca - Updated comments, cosmetic changes
! 20 Nov 2009 - R. Yantosca - Added ProTeX header
!EOP
!------------------------------------------------------------------------------
!BOC
! First check for NaN -- print info & stop run if found
IF ( IT_IS_NAN( VALUE ) ) THEN
WRITE( 6, '(a)' ) REPEAT( '=', 79 )
WRITE( 6, 110 ) TRIM( VARNAME )
WRITE( 6, 115 ) LOCATION
WRITE( 6, '(a)' ) TRIM( MESSAGE )
WRITE( 6, '(a)' ) REPEAT( '=', 79 )
CALL GEOS_CHEM_STOP
ENDIF
! Next check for infinity -- print info & stop run if found
IF ( .not. IT_IS_FINITE( VALUE ) ) THEN
WRITE( 6, '(a)' ) REPEAT( '=', 79 )
WRITE( 6, 120 ) TRIM( VARNAME )
WRITE( 6, 115 ) LOCATION
WRITE( 6, '(f13.6)' ) VALUE
WRITE( 6, '(a)' ) TRIM ( MESSAGE )
WRITE( 6, '(a)' ) REPEAT( '=', 79 )
CALL GEOS_CHEM_STOP
ENDIF
! FORMAT statements
110 FORMAT( 'CHECK_VALUE: ', a, ' is NaN!' )
115 FORMAT( 'Grid box (I,J,L,N) : ', 4i4 )
120 FORMAT( 'CHECK_VALUE: ', a, ' is not finite!' )
! Return to calling program
END SUBROUTINE CHECK_REAL_VALUE
!EOC
!------------------------------------------------------------------------------
! Harvard University Atmospheric Chemistry Modeling Group !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: check_dble_value
!
! !DESCRIPTION: Subroutine CHECK\_DBLE\_VALUE checks to make sure a REAL*4
! value is not NaN or Infinity. This is a wrapper for the interfaces
! IT\_IS\_NAN and IT\_IS\_FINITE.
!\\
!\\
! !INTERFACE:
!
SUBROUTINE CHECK_DBLE_VALUE( VALUE, LOCATION, VARNAME, MESSAGE )
!
! !INPUT PARAMETERS:
!
REAL*8, INTENT(IN) :: VALUE ! Value to be checked
CHARACTER(LEN=255), INTENT(IN) :: VARNAME ! Name of variable
CHARACTER(LEN=255), INTENT(IN) :: MESSAGE ! Short descriptive msg
INTEGER, INTENT(IN) :: LOCATION(4) ! (/ I, J, L, N /) indices
!
! !REVISION HISTORY:
! 13 Jun 2001 - R. Yantosca - Initial version
! 15 Oct 2002 - R. Yantosca - Now call GEOS_CHEM_STOP to shutdown safely
! 15 Oct 2002 - R. Yantosca - Updated comments, cosmetic changes
! 20 Nov 2009 - R. Yantosca - Added ProTeX header
!EOP
!------------------------------------------------------------------------------
!BOC
! First check for NaN
IF ( IT_IS_NAN( VALUE ) )THEN
WRITE( 6, '(a)' ) REPEAT( '=', 79 )
WRITE( 6, 110 ) TRIM( VARNAME )
WRITE( 6, 115 ) LOCATION
WRITE( 6, '(a)' ) TRIM( MESSAGE )
WRITE( 6, '(a)' ) REPEAT( '=', 79 )
CALL GEOS_CHEM_STOP
ENDIF
! Next check for infinity
IF ( .not. IT_IS_FINITE( VALUE ) ) THEN
WRITE( 6, '(a)' ) REPEAT( '=', 79 )
WRITE( 6, 120 ) TRIM( VARNAME )
WRITE( 6, 115 ) LOCATION
WRITE( 6, '(f13.6)' ) VALUE
WRITE( 6, '(a)' ) TRIM ( MESSAGE )
WRITE( 6, '(a)' ) REPEAT( '=', 79 )
CALL GEOS_CHEM_STOP
ENDIF
! FORMAT statements
110 FORMAT( 'CHECK_VALUE: ', a, ' is NaN!' )
115 FORMAT( 'Grid box (I,J,L,N) : ', 4i4 )
120 FORMAT( 'CHECK_VALUE: ', a, ' is not finite!' )
! Return to calling program
END SUBROUTINE CHECK_DBLE_VALUE
!EOC
!------------------------------------------------------------------------------
! Harvard University Atmospheric Chemistry Modeling Group !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: error_stop
!
! !DESCRIPTION: Subroutine ERROR\_STOP is a wrapper for GEOS\_CHEM\_STOP. It
! prints an error message then calls GEOS\_CHEM\_STOP to free memory and quit.
!\\
!\\
! !INTERFACE:
!
SUBROUTINE ERROR_STOP( MESSAGE, LOCATION )
!
! !INPUT PARAMETERS:
!
CHARACTER(LEN=*), INTENT(IN) :: MESSAGE ! Error msg to print
CHARACTER(LEN=*), INTENT(IN) :: LOCATION ! Where ERROR_STOP is called
!
! !REVISION HISTORY:
! 15 Oct 2002 - R. Yantosca - Initial version
! 20 Nov 2009 - R. Yantosca - Added ProTeX header
!EOP
!------------------------------------------------------------------------------
!BOC
!$OMP CRITICAL
! Write msg
WRITE( 6, '(a)' ) REPEAT( '=', 79 )
WRITE( 6, '(a)' ) 'GEOS-CHEM ERROR: ' // TRIM( MESSAGE )
WRITE( 6, '(a)' ) 'STOP at ' // TRIM( LOCATION )
WRITE( 6, '(a)' ) REPEAT( '=', 79 )
!$OMP END CRITICAL
! Deallocate memory and stop the run
CALL GEOS_CHEM_STOP
! Return to calling program
END SUBROUTINE ERROR_STOP
!EOC
!------------------------------------------------------------------------------
! Harvard University Atmospheric Chemistry Modeling Group !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: geos_chem_stop
!
! !DESCRIPTION: Subroutine GEOS\_CHEM\_STOP calls CLEANUP to deallocate all
! module arrays and then stops the run.
!\\
!\\
! !INTERFACE:
!
SUBROUTINE GEOS_CHEM_STOP
!
! !USES:
!
# include "define.h"
! !REVISION HISTORY:
! 15 Oct 2002 - R. Yantosca - Initial version
! 20 Nov 2009 - R. Yantosca - Now EXIT works for LINUX_IFC, LINUX_EFC,
! so remove #if block.
! 20 Nov 2009 - R. Yantosca - Added ProTeX header
!EOP
!------------------------------------------------------------------------------
!BOC
!$OMP CRITICAL
! Deallocate all module arrays
CALL CLEANUP
! Flush all files and stop
CALL EXIT( 99999 )
!$OMP END CRITICAL
! End of program
END SUBROUTINE GEOS_CHEM_STOP
!EOC
!------------------------------------------------------------------------------
! Harvard University Atmospheric Chemistry Modeling Group !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: alloc_err
!
! !DESCRIPTION: Subroutine ALLOC\_ERR prints an error message if there is not
! enough memory to allocate a particular allocatable array.
!\\
!\\
! !INTERFACE:
!
SUBROUTINE ALLOC_ERR( ARRAYNAME, AS )
!
! !USES:
!
# include "define.h"
!
! !INPUT PARAMETERS:
!
CHARACTER(LEN=*), INTENT(IN) :: ARRAYNAME ! Name of array
INTEGER, OPTIONAL, INTENT(IN) :: AS ! Error output from "STAT"
!
! !REVISION HISTORY:
! 26 Jun 2000 - R. Yantosca - Initial version, split off from "ndxx_setup.f"
! 15 Oct 2002 - R. Yantosca - Added to "error_mod.f"
! 30 Nov 2005 - R. Yantosca - Call IFORT_ERRMSG for Intel Fortran compiler
! 20 Nov 2009 - R. Yantosca - Added ProTeX header
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
CHARACTER(LEN=255) :: ERRMSG
!=================================================================
! ALLOC_ERR begins here!
!=================================================================
#if defined( LINUX_IFORT )
!-----------------------
! Linux/IFORT compiler
!-----------------------
! More local variables
CHARACTER(LEN=255) :: IFORT_ERRMSG, MSG
! Define error message
ERRMSG = 'Allocation error in array: ' // TRIM( ARRAYNAME )
! If we have passed the allocation status argument ...
IF ( PRESENT( AS ) ) THEN
! Get IFORT error message
MSG = IFORT_ERRMSG( AS )
! Append IFORT error message
ERRMSG = TRIM( ERRMSG ) // ' :: ' // TRIM( MSG )
ENDIF
#else
!-----------------------
! All other compilers
!-----------------------
! Define error message
ERRMSG = 'Allocation error in array: ' // TRIM( ARRAYNAME )
#endif
! Print error message, deallocate memory, and stop the run
CALL ERROR_STOP( ERRMSG, 'alloc_err.f' )
! End of subroutine
END SUBROUTINE ALLOC_ERR
!EOC
!------------------------------------------------------------------------------
! Harvard University Atmospheric Chemistry Modeling Group !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: debug_msg
!
! !DESCRIPTION: Subroutine DEBUG\_MSG prints a message to the stdout buffer
! and flushes. This is useful for determining the exact location where
! errors occur.
!\\
!\\
! !INTERFACE:
!
SUBROUTINE DEBUG_MSG( MESSAGE )
!
! !USES:
!
# include "define.h"
!
! !INPUT PARAMETERS:
!
CHARACTER(LEN=*), INTENT(IN) :: MESSAGE ! Message to print
!
! !REVISION HISTORY:
! 07 Jan 2002 - R. Yantosca - Initial version
! (1 ) Now just write the message and flush the buffer (bmy, 7/5/01)
! (2 ) Renamed from "paftop.f" to "debug_msg.f" (bmy, 1/7/02)
! (3 ) Bundled into "error_mod.f" (bmy, 11/22/02)
! (4 ) Now do not FLUSH the buffer for EFC compiler (bmy, 4/6/04)
! (5 ) Now add a little space for debug output (bmy, 4/10/06)
! (6 ) Remove support for LINUX_IFC & LINUX_EFC compilers (bmy, 8/4/06)
! 20 Nov 2009 - R. Yantosca - Added ProTeX header
!EOP
!------------------------------------------------------------------------------
!BOC
! Print message
WRITE( 6, '(5x,a)' ) MESSAGE
! Call FLUSH routine to flush the output buffer
CALL FLUSH( 6 )
! Return to calling program
END SUBROUTINE DEBUG_MSG
!EOC
!------------------------------------------------------------------------------
! Harvard University Atmospheric Chemistry Modeling Group !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: safe_div
!
! !DESCRIPTION: Function SAFE\_DIV performs "safe division", that is to
! prevent overflow, underlow, NaN, or infinity errors. An alternate value
! is returned if the division cannot be performed.
!\\
!\\
! !INTERFACE:
!
FUNCTION SAFE_DIV( N, D,
& ALT_NAN, ALT_OVER,
& ALT_UNDER ) RESULT( Q )
!
! !INPUT PARAMETERS:
!
REAL*8, INTENT(IN) :: N ! Numerator
REAL*8, INTENT(IN) :: D ! Denominator
REAL*8, INTENT(IN) :: ALT_NAN ! Alternate value to be
! returned if the division
! is either NAN (0/0) or
! leads to overflow (i.e.,
! a too large number)
REAL*8, OPTIONAL, INTENT(IN) :: ALT_OVER ! Alternate value to be
! returned if the division
! leads to overflow (default
! is ALT_NAN)
REAL*8, OPTIONAL, INTENT(IN) :: ALT_UNDER ! Alternate value to be
! returned if the division
! leads to underflow
! (default is 0, but you
! could use TINY() if you
! want a non-zero result).
!
! !RETURN VALUE:
!
REAL*8 :: Q ! Output from the division
!
! !REMARKS:
! For more information, see the discussion on:
! http://groups.google.com/group/comp.lang.fortran/browse_thread/thread/8b367f44c419fa1d/
!
! !REVISION HISTORY:
! 26 Feb 2008 - P. Le Sager & R. Yantosca - Initial version
! (1) Now can return different alternate values if NAN (that is 0/0),
! overflow (that is a too large number), or too small (that is greater
! than 0 but less than smallest possible number). Default value is
! zero in case of underflow (phs, 4/14/09)
! (2) Some compiler options flush underflows to zero (-ftz for IFort).
! To think about it (phs, 4/14/09)
! 20 Nov 2009 - R. Yantosca - Added ProTeX header
!EOP
!------------------------------------------------------------------------------
!BOC
IF ( N==0 .and. D==0 ) THEN
! NAN
Q = ALT_NAN
ELSE IF ( EXPONENT(N) - EXPONENT(D) >= MAXEXPONENT(N) .OR.
& D==0 ) THEN
! OVERFLOW
Q = ALT_NAN
IF ( PRESENT(ALT_OVER) ) Q = ALT_OVER
ELSE IF ( EXPONENT(N) - EXPONENT(D) <= MINEXPONENT(N) ) THEN
! UNDERFLOW
Q = 0D0
IF ( PRESENT(ALT_UNDER) ) Q = ALT_UNDER
ELSE
! No problem
Q = N / D
ENDIF
! Return to calling program
END FUNCTION SAFE_DIV
!EOC
!------------------------------------------------------------------------------
! Harvard University Atmospheric Chemistry Modeling Group !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: is_safe_div
!
! !DESCRIPTION: Function IS\_SAFE\_DIV tests for "safe division", that is
! check if the division will overflow/underflow or hold NaN. .FALSE. is
! returned if the division cannot be performed. (phs, 6/11/08)
!\\
!\\
! !INTERFACE:
!
FUNCTION IS_SAFE_DIV( N, D, R4 ) RESULT( F )
!
! !INPUT PARAMETERS:
!
REAL*8, INTENT(IN) :: N ! Numerator
REAL*8, INTENT(IN) :: D ! Denominator
LOGICAL, INTENT(IN), OPTIONAL :: R4 ! Logical flag to use the limits
! of REAL*4 to define underflow
! or overflow. Extra defensive.
!
! !OUTPUT PARAMETERS:
!
LOGICAL :: F ! =F if division isn't allowed
! =T otherwise
!
! !REMARKS:
! UnderFlow, OverFlow and NaN are tested for. If you need to
! differentiate between the three, use the SAFE_DIV (phs, 4/14/09)
!
! !REVISION HISTORY:
! 11 Jun 2008 - P. Le Sager - Initial version
! 20 Nov 2009 - R. Yantosca - Added ProTeX header
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
INTEGER MaxExp, MinExp
REAL*4 RR
!==================================================================
! IS_SAFE_DIV begins here!
!==================================================================
MaxExp = MAXEXPONENT( N )
MinExp = MINEXPONENT( N )
IF ( PRESENT( R4 ) ) THEN
IF ( R4 ) THEN
MaxExp = MAXEXPONENT( RR )
MinExp = MINEXPONENT( RR )
ENDIF
ENDIF
IF ( EXPONENT(N) - EXPONENT(D) >= MaxExp .or. D==0 .or.
& EXPONENT(N) - EXPONENT(D) <= MinExp ) THEN
F = .FALSE.
ELSE
F = .TRUE.
ENDIF
! Return to calling program
END FUNCTION IS_SAFE_DIV
!EOC
!------------------------------------------------------------------------------
! Harvard University Atmospheric Chemistry Modeling Group !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: safe_exp
!
! !DESCRIPTION: Function SAFE\_EXP performs a "safe exponential", that is to
! prevent overflow, underlow, NaN, or infinity errors when taking the
! value EXP( x ). An alternate value is returned if the exponential
! cannot be performed.
!\\
!\\
! !INTERFACE:
!
FUNCTION SAFE_EXP( X, ALT ) RESULT( VALUE )
!
! !INPUT PARAMETERS:
!
REAL*8, INTENT(IN) :: X ! Argument of EXP
REAL*8, INTENT(IN) :: ALT ! Alternate value to be returned
!
! !RETURN VALUE:
!
REAL*8 :: VALUE ! Output from the exponential
!
! !REVISION HISTORY:
! 04 Jan 2010 - R. Yantosca - Initial version
!EOP
!------------------------------------------------------------------------------
!BOC
IF ( IS_SAFE_EXP( X ) ) THEN
VALUE = EXP( X )
ELSE
VALUE = ALT
ENDIF
END FUNCTION SAFE_EXP
!EOC
!------------------------------------------------------------------------------
! Harvard University Atmospheric Chemistry Modeling Group !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: is_safe_exp
!
! !DESCRIPTION: Function IS\_SAFE\_EXP returns TRUE if it is safe to take
! the value EXP( x ) without encountering a floating point exception. FALSE
! is returned if the exponential cannot be performed.
!\\
!\\
! !INTERFACE:
!
FUNCTION IS_SAFE_EXP( X ) RESULT( F )
!
! !INPUT PARAMETERS:
!
REAL*8, INTENT(IN) :: X ! Argument to the exponential function
!
! !OUTPUT PARAMETERS:
!
LOGICAL :: F ! =F if exponential isn't allowed
! =T otherwise
!
! !REMARKS:
! Empirical testing has revealed that -600 < X < 600 will not result in
! a floating-point exception on Sun and IFORT compilers. This is good
! enough for most purposes.
!
! !REVISION HISTORY:
! 04 Jan 2010 - R. Yantosca - Initial version
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !DEFINED PARAMETERS:
!
REAL*8, PARAMETER :: CUTOFF = 600d0
! If -CUTOFF < x < CUTOFF, then it is safe to take EXP( x )
F = ( ABS( X ) < CUTOFF )
END FUNCTION IS_SAFE_EXP
!EOC
!------------------------------------------------------------------------------
! Harvard University Atmospheric Chemistry Modeling Group !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: safe_log
!
! !DESCRIPTION: Function SAFE\_LOG performs a "safe natural logarithm", that
! is to prevent overflow, underlow, NaN, or infinity errors when taking the
! value LOG( x ). An alternate value is returned if the logarithm
! cannot be performed.
!\\
!\\
! !INTERFACE:
!
FUNCTION SAFE_LOG( X, ALT ) RESULT( VALUE )
!
! !INPUT PARAMETERS:
!
REAL*8, INTENT(IN) :: X ! Argument of LOG
REAL*8, INTENT(IN) :: ALT ! Alternate value to be returned
!
! !RETURN VALUE:
!
REAL*8 :: VALUE ! Output from the natural logarithm
!
! !REVISION HISTORY:
! 04 Jan 2010 - R. Yantosca - Initial version
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !DEFINED PARAMETERS:
!
IF ( X > 0d0 ) THEN
VALUE = LOG( X ) ! Take LOG(x) for positive-definite X
ELSE
VALUE = ALT ! Otherwise return alternate value
ENDIF
END FUNCTION SAFE_LOG
!EOC
!------------------------------------------------------------------------------
! Harvard University Atmospheric Chemistry Modeling Group !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: safe_log10
!
! !DESCRIPTION: Function SAFE\_LOG10 performs a "safe log10", that
! is to prevent overflow, underlow, NaN, or infinity errors when taking the
! value LOG10( x ). An alternate value is returned if the logarithm
! cannot be performed.
!\\
!\\
! !INTERFACE:
!
FUNCTION SAFE_LOG10( X, ALT ) RESULT( VALUE )
!
! !INPUT PARAMETERS:
!
REAL*8, INTENT(IN) :: X ! Argument of LOG10
REAL*8, INTENT(IN) :: ALT ! Alternate value to be returned
!
! !RETURN VALUE:
!
REAL*8 :: VALUE ! Output from the natural logarithm
!
! !REVISION HISTORY:
! 04 Jan 2010 - R. Yantosca - Initial version
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !DEFINED PARAMETERS:
!
IF ( X > 0d0 ) THEN
VALUE = LOG10( X ) ! Take LOG10(x) for positive-definite X
ELSE
VALUE = ALT ! Otherwise return alternate value
ENDIF
END FUNCTION SAFE_LOG10
!EOC
END MODULE ERROR_MOD