! ! SpcCoeff_Define ! ! Module defining the SpcCoeff data structure and routines ! to manipulate them. ! ! ! CREATION HISTORY: ! Written by: Paul van Delst, CIMSS/SSEC 18-Mar-2002 ! paul.vandelst@ssec.wisc.edu ! MODULE SpcCoeff_Define ! ----------------- ! Environment setup ! ----------------- ! Module use USE Type_Kinds , ONLY: Long, Double USE Message_Handler , ONLY: SUCCESS, FAILURE, WARNING, & Display_Message USE Compare_Float_Numbers, ONLY: Compare_Float USE SensorInfo_Parameters, ONLY: INVALID_WMO_SATELLITE_ID, & INVALID_WMO_SENSOR_ID , & N_SENSOR_TYPES , & INVALID_SENSOR , & MICROWAVE_SENSOR , & INFRARED_SENSOR , & VISIBLE_SENSOR , & ULTRAVIOLET_SENSOR , & SENSOR_TYPE_NAME , & N_POLARIZATION_TYPES , & INVALID_POLARIZATION , & UNPOLARIZED , & INTENSITY , & FIRST_STOKES_COMPONENT , & SECOND_STOKES_COMPONENT , & THIRD_STOKES_COMPONENT , & FOURTH_STOKES_COMPONENT , & VL_POLARIZATION , & HL_POLARIZATION , & plus45L_POLARIZATION , & minus45L_POLARIZATION , & VL_MIXED_POLARIZATION , & HL_MIXED_POLARIZATION , & RC_POLARIZATION , & LC_POLARIZATION , & POLARIZATION_TYPE_NAME USE AntCorr_Define , ONLY: AntCorr_type , & Associated_AntCorr , & Destroy_AntCorr , & Allocate_AntCorr , & Assign_AntCorr , & Equal_AntCorr , & Info_AntCorr , & CheckRelease_AntCorr ! Disable implicit typing IMPLICIT NONE ! ------------ ! Visibilities ! ------------ ! Everything private by default PRIVATE ! Public types ! ------------ PUBLIC :: SpcCoeff_type ! Public procedures ! ----------------- PUBLIC :: Associated_SpcCoeff PUBLIC :: Destroy_SpcCoeff PUBLIC :: Allocate_SpcCoeff PUBLIC :: Assign_SpcCoeff PUBLIC :: Equal_SpcCoeff PUBLIC :: CheckRelease_SpcCoeff PUBLIC :: Info_SpcCoeff PUBLIC :: IsFlagSet_SpcCoeff, SetFlag_SpcCoeff, ClearFlag_SpcCoeff ! Use associated procedures PUBLIC :: Associated_AntCorr PUBLIC :: Destroy_AntCorr PUBLIC :: Allocate_AntCorr PUBLIC :: Assign_AntCorr PUBLIC :: Equal_AntCorr PUBLIC :: Info_AntCorr PUBLIC :: CheckRelease_AntCorr ! Public parameters ! ----------------- ! Sensor Id defaults PUBLIC :: INVALID_WMO_SATELLITE_ID PUBLIC :: INVALID_WMO_SENSOR_ID ! Allowable sensor type values and names PUBLIC :: N_SENSOR_TYPES PUBLIC :: INVALID_SENSOR PUBLIC :: MICROWAVE_SENSOR PUBLIC :: INFRARED_SENSOR PUBLIC :: VISIBLE_SENSOR PUBLIC :: ULTRAVIOLET_SENSOR PUBLIC :: SENSOR_TYPE_NAME ! Allowable polarisation type values and names PUBLIC :: N_POLARIZATION_TYPES PUBLIC :: INVALID_POLARIZATION PUBLIC :: UNPOLARIZED PUBLIC :: INTENSITY PUBLIC :: FIRST_STOKES_COMPONENT PUBLIC :: SECOND_STOKES_COMPONENT PUBLIC :: THIRD_STOKES_COMPONENT PUBLIC :: FOURTH_STOKES_COMPONENT PUBLIC :: VL_POLARIZATION PUBLIC :: HL_POLARIZATION PUBLIC :: plus45L_POLARIZATION PUBLIC :: minus45L_POLARIZATION PUBLIC :: VL_MIXED_POLARIZATION PUBLIC :: HL_MIXED_POLARIZATION PUBLIC :: RC_POLARIZATION PUBLIC :: LC_POLARIZATION PUBLIC :: POLARIZATION_TYPE_NAME ! Current set of channel flags PUBLIC :: SOLAR_FLAG PUBLIC :: ZEEMAN_FLAG ! ----------------- ! Module parameters ! ----------------- ! RCS Id for the module CHARACTER(*), PARAMETER :: MODULE_RCS_ID = & '$Id: SpcCoeff_Define.f90 22707 2012-11-21 21:09:10Z paul.vandelst@noaa.gov $' ! Literal constants REAL(Double), PARAMETER :: ZERO = 0.0_Double ! SpcCoeff invalid value INTEGER, PARAMETER :: IP_INVALID = -1 REAL(Double), PARAMETER :: FP_INVALID = -1.0_Double ! Keyword set value INTEGER, PARAMETER :: SET = 1 ! Sensor Id component string length INTEGER, PARAMETER :: SL = 20 ! Current valid release and version numbers INTEGER, PARAMETER :: SPCCOEFF_RELEASE = 7 ! This determines structure and file formats. INTEGER, PARAMETER :: SPCCOEFF_VERSION = 1 ! This is just the data version. ! ASCII codes for Version routine INTEGER, PARAMETER :: CARRIAGE_RETURN = 13 INTEGER, PARAMETER :: LINEFEED = 10 ! The bit positions for the various channel flags INTEGER, PARAMETER :: SOLAR_FLAG = 0 INTEGER, PARAMETER :: ZEEMAN_FLAG = 1 ! ----------------------------- ! SpcCoeff data type definition ! ----------------------------- TYPE :: SpcCoeff_type INTEGER :: n_Allocates = 0 ! Release and version information INTEGER(Long) :: Release = SPCCOEFF_RELEASE INTEGER(Long) :: Version = SPCCOEFF_VERSION ! Dimensions INTEGER(Long) :: n_Channels = 0 ! L dimension ! Data prescence indicator(s) LOGICAL :: AC_Present = .FALSE. ! Scalar components CHARACTER(SL) :: Sensor_Id = ' ' INTEGER(Long) :: WMO_Satellite_ID = INVALID_WMO_SATELLITE_ID INTEGER(Long) :: WMO_Sensor_ID = INVALID_WMO_SENSOR_ID INTEGER(Long) :: Sensor_Type = INVALID_SENSOR ! Channel data arrays INTEGER(Long), POINTER :: Sensor_Channel(:) => NULL() ! L INTEGER(Long), POINTER :: Polarization(:) => NULL() ! L INTEGER(Long), POINTER :: Channel_Flag(:) => NULL() ! L REAL(Double) , POINTER :: Frequency(:) => NULL() ! L REAL(Double) , POINTER :: Wavenumber(:) => NULL() ! L REAL(Double) , POINTER :: Planck_C1(:) => NULL() ! L REAL(Double) , POINTER :: Planck_C2(:) => NULL() ! L REAL(Double) , POINTER :: Band_C1(:) => NULL() ! L REAL(Double) , POINTER :: Band_C2(:) => NULL() ! L REAL(Double) , POINTER :: Cosmic_Background_Radiance(:) => NULL() ! L REAL(Double) , POINTER :: Solar_Irradiance(:) => NULL() ! L ! Antenna correction structure TYPE(AntCorr_type) :: AC END TYPE SpcCoeff_type ! ------------------- ! Procedure overloads ! ------------------- INTERFACE SetFlag_SpcCoeff MODULE PROCEDURE SetFlag_Scalar MODULE PROCEDURE SetFlag_Rank1 END INTERFACE SetFlag_SpcCoeff INTERFACE ClearFlag_SpcCoeff MODULE PROCEDURE ClearFlag_Scalar MODULE PROCEDURE ClearFlag_Rank1 END INTERFACE ClearFlag_SpcCoeff CONTAINS !################################################################################ !################################################################################ !## ## !## ## PUBLIC MODULE ROUTINES ## ## !## ## !################################################################################ !################################################################################ FUNCTION IsFlagSet_SpcCoeff(Flags, Flag_Type) RESULT(Is_Set) INTEGER, INTENT(IN) :: Flags INTEGER, INTENT(IN) :: Flag_Type LOGICAL :: Is_Set Is_Set = BTEST(Flags,Flag_Type) END FUNCTION IsFlagSet_SpcCoeff SUBROUTINE SetFlag_Scalar(Flags, Flag_Type) INTEGER, INTENT(IN OUT) :: Flags INTEGER, INTENT(IN) :: Flag_Type Flags = IBSET(Flags,Flag_Type) END SUBROUTINE SetFlag_Scalar SUBROUTINE SetFlag_Rank1(Flags, Flag_Type) INTEGER, INTENT(IN OUT) :: Flags(:) INTEGER, INTENT(IN) :: Flag_Type INTEGER :: l DO l = 1, SIZE(Flags) CALL SetFlag_Scalar(Flags(l),Flag_Type) END DO END SUBROUTINE SetFlag_Rank1 SUBROUTINE ClearFlag_Scalar(Flags, Flag_Type) INTEGER, INTENT(IN OUT) :: Flags INTEGER, INTENT(IN) :: Flag_Type Flags = IBCLR(Flags,Flag_Type) END SUBROUTINE ClearFlag_Scalar SUBROUTINE ClearFlag_Rank1(Flags, Flag_Type) INTEGER, INTENT(IN OUT) :: Flags(:) INTEGER, INTENT(IN) :: Flag_Type INTEGER :: l DO l = 1, SIZE(Flags) CALL ClearFlag_Scalar(Flags(l),Flag_Type) END DO END SUBROUTINE ClearFlag_Rank1 !-------------------------------------------------------------------------------- ! ! NAME: ! Associated_SpcCoeff ! ! PURPOSE: ! Function to test the association status of the pointer members of a ! SpcCoeff structure. ! ! CALLING SEQUENCE: ! Association_Status = Associated_SpcCoeff( SpcCoeff , & ! Input ! ANY_Test=Any_Test ) ! Optional input ! ! INPUT ARGUMENTS: ! SpcCoeff: SpcCoeff structure which is to have its pointer ! member's association status tested. ! UNITS: N/A ! TYPE: SpcCoeff_type ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN) ! ! OPTIONAL INPUT ARGUMENTS: ! ANY_Test: Set this argument to test if ANY of the ! SpcCoeff structure pointer members are associated. ! The default is to test if ALL the pointer members ! are associated. ! If ANY_Test = 0, test if ALL the pointer members ! are associated. (DEFAULT) ! ANY_Test = 1, test if ANY of the pointer members ! are associated. ! UNITS: N/A ! TYPE: INTEGER ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN), OPTIONAL ! ! FUNCTION RESULT: ! Association_Status: The return value is a logical value indicating the ! association status of the SpcCoeff pointer members. ! .TRUE. - if ALL the SpcCoeff pointer members are ! associated, or if the ANY_Test argument ! is set and ANY of the SpcCoeff pointer ! members are associated. ! .FALSE. - some or all of the SpcCoeff pointer ! members are NOT associated. ! UNITS: N/A ! TYPE: LOGICAL ! DIMENSION: Scalar ! !-------------------------------------------------------------------------------- FUNCTION Associated_SpcCoeff( SpcCoeff, & ! Input ANY_Test) & ! Optional input RESULT( Association_Status ) ! Arguments TYPE(SpcCoeff_type), INTENT(IN) :: SpcCoeff INTEGER, OPTIONAL, INTENT(IN) :: ANY_Test ! Function result LOGICAL :: Association_Status ! Local variables LOGICAL :: ALL_Test ! Set up ! ------ ! Default is to test ALL the pointer members ! for a true association status.... ALL_Test = .TRUE. ! ...unless the ANY_Test argument is set. IF ( PRESENT( ANY_Test ) ) THEN IF ( ANY_Test == SET ) ALL_Test = .FALSE. END IF ! Test the members that MUST be associated ! ---------------------------------------- Association_Status = .FALSE. IF ( ALL_Test ) THEN IF ( ASSOCIATED( SpcCoeff%Sensor_Channel ) .AND. & ASSOCIATED( SpcCoeff%Polarization ) .AND. & ASSOCIATED( SpcCoeff%Channel_Flag ) .AND. & ASSOCIATED( SpcCoeff%Frequency ) .AND. & ASSOCIATED( SpcCoeff%Wavenumber ) .AND. & ASSOCIATED( SpcCoeff%Planck_C1 ) .AND. & ASSOCIATED( SpcCoeff%Planck_C2 ) .AND. & ASSOCIATED( SpcCoeff%Band_C1 ) .AND. & ASSOCIATED( SpcCoeff%Band_C2 ) .AND. & ASSOCIATED( SpcCoeff%Cosmic_Background_Radiance ) .AND. & ASSOCIATED( SpcCoeff%Solar_Irradiance ) ) THEN Association_Status = .TRUE. END IF ELSE IF ( ASSOCIATED( SpcCoeff%Sensor_Channel ) .OR. & ASSOCIATED( SpcCoeff%Polarization ) .OR. & ASSOCIATED( SpcCoeff%Channel_Flag ) .OR. & ASSOCIATED( SpcCoeff%Frequency ) .OR. & ASSOCIATED( SpcCoeff%Wavenumber ) .OR. & ASSOCIATED( SpcCoeff%Planck_C1 ) .OR. & ASSOCIATED( SpcCoeff%Planck_C2 ) .OR. & ASSOCIATED( SpcCoeff%Band_C1 ) .OR. & ASSOCIATED( SpcCoeff%Band_C2 ) .OR. & ASSOCIATED( SpcCoeff%Cosmic_Background_Radiance ) .OR. & ASSOCIATED( SpcCoeff%Solar_Irradiance ) ) THEN Association_Status = .TRUE. END IF END IF ! Test the members that MAY be associated ! --------------------------------------- ! Antenna correction IF ( SpcCoeff%AC_Present ) THEN IF ( ALL_Test ) THEN IF ( Association_Status .AND. & Associated_AntCorr(SpcCoeff%AC) ) THEN Association_Status = .TRUE. END IF ELSE IF ( Association_Status .OR. & Associated_AntCorr(SpcCoeff%AC) ) THEN Association_Status = .TRUE. END IF END IF END IF END FUNCTION Associated_SpcCoeff !-------------------------------------------------------------------------------- ! ! NAME: ! Destroy_SpcCoeff ! ! PURPOSE: ! Function to re-initialize the scalar and pointer members of SpcCoeff ! data structures. ! ! CALLING SEQUENCE: ! Error_Status = Destroy_SpcCoeff( SpcCoeff , & ! Output ! RCS_Id =RCS_Id , & ! Revision control ! Message_Log=Message_Log ) ! Error messaging ! ! OUTPUT ARGUMENTS: ! SpcCoeff: Re-initialized SpcCoeff structure. ! UNITS: N/A ! TYPE: SpcCoeff_type ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN OUT) ! ! OPTIONAL INPUT ARGUMENTS: ! Message_Log: Character string specifying a filename in which any ! messages will be logged. If not specified, or if an ! error occurs opening the log file, the default action ! is to output messages to standard output. ! UNITS: N/A ! TYPE: CHARACTER(*) ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN), OPTIONAL ! ! OPTIONAL OUTPUT ARGUMENTS: ! RCS_Id: Character string containing the Revision Control ! System Id field for the module. ! UNITS: N/A ! TYPE: CHARACTER(*) ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(OUT), OPTIONAL ! ! FUNCTION RESULT: ! Error_Status: The return value is an integer defining the error status. ! The error codes are defined in the Message_Handler module. ! If == SUCCESS the structure re-initialisation was successful ! == FAILURE - an error occurred, or ! - the structure internal allocation counter ! is not equal to zero (0) upon exiting this ! function. This value is incremented and ! decremented for every structure allocation ! and deallocation respectively. ! UNITS: N/A ! TYPE: INTEGER ! DIMENSION: Scalar ! ! COMMENTS: ! Note the INTENT on the output SpcCoeff argument is IN OUT rather than ! just OUT. This is necessary because the argument may be defined upon ! input. To prevent memory leaks, the IN OUT INTENT is a must. ! !-------------------------------------------------------------------------------- FUNCTION Destroy_SpcCoeff( SpcCoeff , & ! Output No_Clear , & ! Optional input RCS_Id , & ! Revision control Message_Log) & ! Error messaging RESULT( Error_Status ) ! Arguments TYPE(SpcCoeff_type) , INTENT(IN OUT) :: SpcCoeff INTEGER, OPTIONAL, INTENT(IN) :: No_Clear CHARACTER(*), OPTIONAL, INTENT(OUT) :: RCS_Id CHARACTER(*), OPTIONAL, INTENT(IN) :: Message_Log ! Function result INTEGER :: Error_Status ! Local parameters CHARACTER(*), PARAMETER :: ROUTINE_NAME = 'Destroy_SpcCoeff' ! Local variables CHARACTER(256) :: Message LOGICAL :: Clear INTEGER :: Destroy_Status ! Set up ! ------ Error_Status = SUCCESS IF ( PRESENT( RCS_Id ) ) RCS_Id = MODULE_RCS_ID ! Reinitialise the dimensions SpcCoeff%n_Channels = 0 ! Default is to clear scalar members... Clear = .TRUE. ! ....unless the No_Clear argument is set IF ( PRESENT( No_Clear ) ) THEN IF ( No_Clear == SET ) Clear = .FALSE. END IF IF ( Clear ) CALL Clear_SpcCoeff( SpcCoeff ) ! If ALL components are NOT associated, do nothing IF ( .NOT. Associated_SpcCoeff( SpcCoeff ) ) RETURN ! Deallocate the regular arrays components ! ---------------------------------------- DEALLOCATE( SpcCoeff%Sensor_Channel , & SpcCoeff%Polarization , & SpcCoeff%Channel_Flag , & SpcCoeff%Frequency , & SpcCoeff%Wavenumber , & SpcCoeff%Planck_C1 , & SpcCoeff%Planck_C2 , & SpcCoeff%Band_C1 , & SpcCoeff%Band_C2 , & SpcCoeff%Cosmic_Background_Radiance, & SpcCoeff%Solar_Irradiance , & STAT=Destroy_Status ) IF ( Destroy_Status /= 0 ) THEN Error_Status = FAILURE WRITE( Message,'("Error deallocating SpcCoeff components. STAT = ",i0)') & Destroy_Status CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) ! No return. Continue with deallocation END IF ! Destroy the Antenna Correction structure component ! -------------------------------------------------- Destroy_Status = Destroy_AntCorr( SpcCoeff%AC, & No_Clear =No_Clear, & Message_Log=Message_Log ) IF ( Destroy_Status /= SUCCESS ) THEN Error_Status = Destroy_Status CALL Display_Message( ROUTINE_NAME, & 'Error destroying SpcCoeff Antenaa Correction structure(s).', & Error_Status, & Message_Log=Message_Log ) ! No return. Continue with deallocation END IF ! Decrement and test allocation counter ! ------------------------------------- SpcCoeff%n_Allocates = SpcCoeff%n_Allocates - 1 IF ( SpcCoeff%n_Allocates /= 0 ) THEN Error_Status = FAILURE WRITE( Message, '( "Allocation counter /= 0, Value = ", i0 )' ) & SpcCoeff%n_Allocates CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) END IF END FUNCTION Destroy_SpcCoeff !-------------------------------------------------------------------------------- ! ! NAME: ! Allocate_SpcCoeff ! ! PURPOSE: ! Function to allocate the pointer members of a SpcCoeff ! data structure. ! ! CALLING SEQUENCE: ! Error_Status = Allocate_SpcCoeff( n_Channels , & ! Input ! SpcCoeff , & ! Output ! n_FOVs =n_FOVs , & ! Optional Input ! RCS_Id =RCS_Id , & ! Revision control ! Message_Log=Message_Log ) ! Error messaging ! ! INPUT ARGUMENTS: ! n_Channels: Number of sensor channels. ! Must be > 0. ! UNITS: N/A ! TYPE: INTEGER ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN) ! ! OUTPUT ARGUMENTS: ! SpcCoeff: SpcCoeff structure with allocated pointer ! members ! UNITS: N/A ! TYPE: SpcCoeff_type ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN OUT) ! ! ! OPTIONAL INPUT ARGUMENTS: ! n_FOVs: Number of sensor fields-of-view (FOVs). Used ! for microwave instrument antennae correction. ! If not present, or if present but == 0, the ! antenna correction element of the SpcCoeff ! is not allocated. ! UNITS: N/A ! TYPE: INTEGER ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN) ! ! Message_Log: Character string specifying a filename in ! which any messages will be logged. If not ! specified, or if an error occurs opening the ! log file, the default action is to output ! messages to standard output. ! UNITS: N/A ! TYPE: CHARACTER(*) ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN), OPTIONAL ! ! OPTIONAL OUTPUT ARGUMENTS: ! RCS_Id: Character string containing the Revision ! Control System Id field for the module. ! UNITS: N/A ! TYPE: CHARACTER(*) ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(OUT), OPTIONAL ! ! FUNCTION RESULT: ! Error_Status: The return value is an integer defining the ! error status. The error codes are defined in ! the Message_Handler module. ! If == SUCCESS the structure pointer allocations ! were successful ! == FAILURE - an error occurred, or ! - the structure internal allocation ! counter is not equal to one (1) ! upon exiting this function. This ! value is incremented and decre- ! mented for every structure ! allocation and deallocation ! respectively. ! UNITS: N/A ! TYPE: INTEGER ! DIMENSION: Scalar ! ! COMMENTS: ! Note the INTENT on the output SpcCoeff argument is IN OUT rather than ! just OUT. This is necessary because the argument may be defined upon ! input. To prevent memory leaks, the IN OUT INTENT is a must. ! !-------------------------------------------------------------------------------- FUNCTION Allocate_SpcCoeff( n_Channels , & ! Input SpcCoeff , & ! Output n_FOVs , & ! Optional Input RCS_Id , & ! Revision control Message_Log) & ! Error messaging RESULT( Error_Status ) ! Arguments INTEGER , INTENT(IN) :: n_Channels TYPE(SpcCoeff_type) , INTENT(IN OUT) :: SpcCoeff INTEGER , OPTIONAL, INTENT(IN) :: n_FOVs CHARACTER(*), OPTIONAL, INTENT(OUT) :: RCS_Id CHARACTER(*), OPTIONAL, INTENT(IN) :: Message_Log ! Function result INTEGER :: Error_Status ! Local parameters CHARACTER(*), PARAMETER :: ROUTINE_NAME = 'Allocate_SpcCoeff' ! Local variables CHARACTER(256) :: Message INTEGER :: Allocate_Status LOGICAL :: Allocate_AC ! Set up ! ------ Error_Status = SUCCESS IF ( PRESENT( RCS_Id ) ) RCS_Id = MODULE_RCS_ID ! Check dimension input IF ( n_Channels < 1 ) THEN Error_Status = FAILURE CALL Display_Message( ROUTINE_NAME, & 'Input N_CHANNELS must be > 0.', & Error_Status, & Message_Log=Message_Log ) RETURN END IF ! Antenna correction component is NOT allocated... Allocate_AC = .FALSE. ! ...unless the n_FOVs dimension is present and non-zero IF ( PRESENT( n_FOVs ) ) THEN IF ( n_FOVs > 0 ) Allocate_AC = .TRUE. END IF ! Check if ANY pointers are already associated ! If they are, deallocate them but leave scalars. IF ( Associated_SpcCoeff( SpcCoeff, ANY_Test = SET ) ) THEN Error_Status = Destroy_SpcCoeff( SpcCoeff, & No_Clear = SET, & Message_Log=Message_Log ) IF ( Error_Status /= SUCCESS ) THEN CALL Display_Message( ROUTINE_NAME, & 'Error deallocating SpcCoeff pointer members.', & Error_Status, & Message_Log=Message_Log ) RETURN END IF END IF ! Allocate the intrinsic type arrays ! ---------------------------------- ALLOCATE( SpcCoeff%Sensor_Channel( n_Channels ), & SpcCoeff%Polarization( n_Channels ), & SpcCoeff%Channel_Flag( n_Channels ), & SpcCoeff%Frequency( n_Channels ), & SpcCoeff%Wavenumber( n_Channels ), & SpcCoeff%Planck_C1( n_Channels ), & SpcCoeff%Planck_C2( n_Channels ), & SpcCoeff%Band_C1( n_Channels ), & SpcCoeff%Band_C2( n_Channels ), & SpcCoeff%Cosmic_Background_Radiance( n_Channels ), & SpcCoeff%Solar_Irradiance( n_Channels ), & STAT = Allocate_Status ) IF ( Allocate_Status /= 0 ) THEN Error_Status = FAILURE WRITE( Message,'("Error allocating SpcCoeff data arrays. STAT = ",i0)') & Allocate_Status CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) RETURN END IF ! Assign the dimensions and initialise arrays SpcCoeff%n_Channels = n_Channels SpcCoeff%Sensor_Channel = 0 SpcCoeff%Polarization = INVALID_POLARIZATION SpcCoeff%Channel_Flag = 0 SpcCoeff%Frequency = FP_INVALID SpcCoeff%Wavenumber = FP_INVALID SpcCoeff%Planck_C1 = FP_INVALID SpcCoeff%Planck_C2 = FP_INVALID SpcCoeff%Band_C1 = FP_INVALID SpcCoeff%Band_C2 = FP_INVALID SpcCoeff%Cosmic_Background_Radiance = FP_INVALID SpcCoeff%Solar_Irradiance = FP_INVALID ! Allocate the antenna correction component ! ----------------------------------------- IF ( Allocate_AC ) THEN Error_Status = Allocate_AntCorr( n_FOVs, n_Channels, & SpcCoeff%AC, & Message_Log=Message_Log ) IF ( Error_Status /= SUCCESS ) THEN CALL Display_Message( ROUTINE_NAME, & 'Error allocating AC structure.', & Error_Status, & Message_Log=Message_Log ) RETURN END IF ! Set the data indicator in the main structure SpcCoeff%AC_Present = .TRUE. END IF ! Increment and test allocation counter ! ------------------------------------- SpcCoeff%n_Allocates = SpcCoeff%n_Allocates + 1 IF ( SpcCoeff%n_Allocates /= 1 ) THEN Error_Status = WARNING WRITE( Message, '( "Allocation counter /= 1, Value = ", i5 )' ) & SpcCoeff%n_Allocates CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) END IF END FUNCTION Allocate_SpcCoeff !-------------------------------------------------------------------------------- ! ! NAME: ! Assign_SpcCoeff ! ! PURPOSE: ! Function to copy valid SpcCoeff structures. ! ! CALLING SEQUENCE: ! Error_Status = Assign_SpcCoeff( SpcCoeff_in , & ! Input ! SpcCoeff_out , & ! Output ! RCS_Id =RCS_Id , & ! Revision control ! Message_Log=Message_Log ) ! Error messaging ! ! INPUT ARGUMENTS: ! SpcCoeff_in: SpcCoeff structure which is to be copied. ! UNITS: N/A ! TYPE: SpcCoeff_type ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN) ! ! OUTPUT ARGUMENTS: ! SpcCoeff_out: Copy of the input structure, SpcCoeff_in. ! UNITS: N/A ! TYPE: Same as SpcCoeff_in ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN OUT) ! ! OPTIONAL INPUT ARGUMENTS: ! Message_Log: Character string specifying a filename in which any ! messages will be logged. If not specified, or if an ! error occurs opening the log file, the default action ! is to output messages to standard output. ! UNITS: N/A ! TYPE: CHARACTER(*) ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN), OPTIONAL ! ! OPTIONAL OUTPUT ARGUMENTS: ! RCS_Id: Character string containing the Revision Control ! System Id field for the module. ! UNITS: N/A ! TYPE: CHARACTER(*) ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(OUT), OPTIONAL ! ! FUNCTION RESULT: ! Error_Status: The return value is an integer defining the error status. ! The error codes are defined in the Message_Handler module. ! If == SUCCESS the structure assignment was successful ! == FAILURE an error occurred ! UNITS: N/A ! TYPE: INTEGER ! DIMENSION: Scalar ! ! COMMENTS: ! Note the INTENT on the output SpcCoeff argument is IN OUT rather than ! just OUT. This is necessary because the argument may be defined upon ! input. To prevent memory leaks, the IN OUT INTENT is a must. ! !-------------------------------------------------------------------------------- FUNCTION Assign_SpcCoeff( SpcCoeff_in , & ! Input SpcCoeff_out, & ! Output RCS_Id , & ! Revision control Message_Log ) & ! Error messaging RESULT( Error_Status ) ! Arguments TYPE(SpcCoeff_type) , INTENT(IN) :: SpcCoeff_in TYPE(SpcCoeff_type) , INTENT(IN OUT) :: SpcCoeff_out CHARACTER(*), OPTIONAL, INTENT(OUT) :: RCS_Id CHARACTER(*), OPTIONAL, INTENT(IN) :: Message_Log ! Function result INTEGER :: Error_Status ! Local parameters CHARACTER(*), PARAMETER :: ROUTINE_NAME = 'Assign_SpcCoeff' ! Set up ! ------ Error_Status = SUCCESS IF ( PRESENT( RCS_Id ) ) RCS_Id = MODULE_RCS_ID ! ALL *input* pointers must be associated ! BUT the antenna correction AC component ! may not be. IF ( .NOT. Associated_SpcCoeff( SpcCoeff_In ) ) THEN Error_Status = Destroy_SpcCoeff( SpcCoeff_Out, & Message_Log=Message_Log ) IF ( Error_Status /= SUCCESS ) THEN CALL Display_Message( ROUTINE_NAME, & 'Error deallocating output SpcCoeff components.', & Error_Status, & Message_Log=Message_Log ) END IF RETURN END IF ! Allocate the structure ! ---------------------- Error_Status = Allocate_SpcCoeff( SpcCoeff_in%n_Channels, & SpcCoeff_out, & n_FOVs=SpcCoeff_in%AC%n_FOVs, & Message_Log=Message_Log ) IF ( Error_Status /= SUCCESS ) THEN CALL Display_Message( ROUTINE_NAME, & 'Error allocating output SpcCoeff arrays.', & Error_Status, & Message_Log=Message_Log ) RETURN END IF ! Assign intrinsic data types ! --------------------------- SpcCoeff_out%Release = SpcCoeff_in%Release SpcCoeff_out%Version = SpcCoeff_in%Version SpcCoeff_out%Sensor_Id = SpcCoeff_in%Sensor_Id SpcCoeff_out%Sensor_Type = SpcCoeff_in%Sensor_Type SpcCoeff_out%WMO_Satellite_ID = SpcCoeff_in%WMO_Satellite_ID SpcCoeff_out%WMO_Sensor_ID = SpcCoeff_in%WMO_Sensor_ID SpcCoeff_out%Sensor_Channel = SpcCoeff_in%Sensor_Channel SpcCoeff_out%Polarization = SpcCoeff_in%Polarization SpcCoeff_out%Channel_Flag = SpcCoeff_in%Channel_Flag SpcCoeff_out%Frequency = SpcCoeff_in%Frequency SpcCoeff_out%Wavenumber = SpcCoeff_in%Wavenumber SpcCoeff_out%Planck_C1 = SpcCoeff_in%Planck_C1 SpcCoeff_out%Planck_C2 = SpcCoeff_in%Planck_C2 SpcCoeff_out%Band_C1 = SpcCoeff_in%Band_C1 SpcCoeff_out%Band_C2 = SpcCoeff_in%Band_C2 SpcCoeff_out%Cosmic_Background_Radiance = SpcCoeff_in%Cosmic_Background_Radiance SpcCoeff_out%Solar_Irradiance = SpcCoeff_in%Solar_Irradiance ! Assign Antenna Correction structures ! ------------------------------------ IF ( SpcCoeff_in%AC_Present ) THEN Error_Status = Assign_AntCorr( SpcCoeff_in%AC, & SpcCoeff_out%AC, & Message_Log=Message_Log) IF ( Error_Status /= SUCCESS ) THEN CALL Display_Message( ROUTINE_NAME, & 'Error copying AC structure for '//& TRIM(SpcCoeff_in%Sensor_Id), & Error_Status, & Message_Log=Message_Log ) RETURN END IF END IF END FUNCTION Assign_SpcCoeff !-------------------------------------------------------------------------------- ! ! NAME: ! Equal_SpcCoeff ! ! PURPOSE: ! Function to test if two SpcCoeff structures are equal. ! ! CALLING SEQUENCE: ! Error_Status = Equal_SpcCoeff( SpcCoeff_LHS , & ! Input ! SpcCoeff_RHS , & ! Input ! ULP_Scale =ULP_Scale , & ! Optional input ! Check_All =Check_All , & ! Optional input ! RCS_Id =RCS_Id , & ! Revision control ! Message_Log=Message_Log ) ! Error messaging ! ! INPUT ARGUMENTS: ! SpcCoeff_LHS: SpcCoeff structure to be compared; equivalent to the ! left-hand side of a lexical comparison, e.g. ! IF ( SpcCoeff_LHS == SpcCoeff_RHS ). ! UNITS: N/A ! TYPE: SpcCoeff_type ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN) ! ! SpcCoeff_RHS: SpcCoeff structure to be compared to; equivalent to ! right-hand side of a lexical comparison, e.g. ! IF ( SpcCoeff_LHS == SpcCoeff_RHS ). ! UNITS: N/A ! TYPE: Same as SpcCoeff_LHS ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN) ! ! OPTIONAL INPUT ARGUMENTS: ! ULP_Scale: Unit of data precision used to scale the floating ! point comparison. ULP stands for "Unit in the Last Place," ! the smallest possible increment or decrement that can be ! made using a machine's floating point arithmetic. ! Value must be positive - if a negative value is supplied, ! the absolute value is used. If not specified, the default ! value is 1. ! UNITS: N/A ! TYPE: INTEGER ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN), OPTIONAL ! ! Check_All: Set this argument to check ALL the floating point ! channel data of the SpcCoeff structures. The default ! action is return with a FAILURE status as soon as ! any difference is found. This optional argument can ! be used to get a listing of ALL the differences ! between data in SpcCoeff structures. ! If == 0, Return with FAILURE status as soon as ! ANY difference is found *DEFAULT* ! == 1, Set FAILURE status if ANY difference is ! found, but continue to check ALL data. ! UNITS: N/A ! TYPE: INTEGER ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN), OPTIONAL ! ! Message_Log: Character string specifying a filename in which any ! messages will be logged. If not specified, or if an ! error occurs opening the log file, the default action ! is to output messages to standard output. ! UNITS: N/A ! TYPE: CHARACTER(*) ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN), OPTIONAL ! ! OPTIONAL OUTPUT ARGUMENTS: ! RCS_Id: Character string containing the Revision Control ! System Id field for the module. ! UNITS: N/A ! TYPE: CHARACTER(*) ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(OUT), OPTIONAL ! ! FUNCTION RESULT: ! Error_Status: The return value is an integer defining the error status. ! The error codes are defined in the Message_Handler module. ! If == SUCCESS the structures were equal ! == FAILURE - an error occurred, or ! - the structures were different. ! UNITS: N/A ! TYPE: INTEGER ! DIMENSION: Scalar ! !-------------------------------------------------------------------------------- FUNCTION Equal_SpcCoeff( SpcCoeff_LHS, & ! Input SpcCoeff_RHS, & ! Input ULP_Scale , & ! Optional input Check_All , & ! Optional input RCS_Id , & ! Revision control Message_Log ) & ! Error messaging RESULT( Error_Status ) ! Arguments TYPE(SpcCoeff_type) , INTENT(IN) :: SpcCoeff_LHS TYPE(SpcCoeff_type) , INTENT(IN) :: SpcCoeff_RHS INTEGER , OPTIONAL, INTENT(IN) :: ULP_Scale INTEGER , OPTIONAL, INTENT(IN) :: Check_All CHARACTER(*), OPTIONAL, INTENT(OUT) :: RCS_Id CHARACTER(*), OPTIONAL, INTENT(IN) :: Message_Log ! Function result INTEGER :: Error_Status ! Local parameters CHARACTER(*), PARAMETER :: ROUTINE_NAME = 'Equal_SpcCoeff' ! Local variables CHARACTER(256) :: Message INTEGER :: ULP LOGICAL :: Check_Once INTEGER :: l ! Set up ! ------ Error_Status = SUCCESS IF ( PRESENT( RCS_Id ) ) RCS_Id = MODULE_RCS_ID ! Default precision is a single unit in last place ULP = 1 ! ... unless the ULP_Scale argument is set and positive IF ( PRESENT( ULP_Scale ) ) THEN IF ( ULP_Scale > 0 ) ULP = ULP_Scale END IF ! Default action is to return on ANY difference... Check_Once = .TRUE. ! ...unless the Check_All argument is set IF ( PRESENT( Check_All ) ) THEN IF ( Check_All == SET ) Check_Once = .FALSE. END IF ! Check the structure association status IF ( .NOT. Associated_SpcCoeff( SpcCoeff_LHS ) ) THEN Error_Status = FAILURE CALL Display_Message( ROUTINE_NAME, & 'Some or all INPUT SpcCoeff_LHS pointer '//& 'members are NOT associated.', & Error_Status, & Message_Log=Message_Log ) RETURN END IF IF ( .NOT. Associated_SpcCoeff( SpcCoeff_RHS ) ) THEN Error_Status = FAILURE CALL Display_Message( ROUTINE_NAME, & 'Some or all INPUT SpcCoeff_RHS pointer '//& 'members are NOT associated.', & Error_Status, & Message_Log=Message_Log ) RETURN END IF ! Check Release/Version info ! -------------------------- IF ( ( SpcCoeff_LHS%Release /= SpcCoeff_RHS%Release ) .OR. & ( SpcCoeff_LHS%Version /= SpcCoeff_RHS%Version ) ) THEN Error_Status = FAILURE WRITE( Message, '( "Release/Version numbers are different : ", & &i2, ".", i2.2, " vs. ", i2, ".", i2.2 )' ) & SpcCoeff_LHS%Release, SpcCoeff_LHS%Version, & SpcCoeff_RHS%Release, SpcCoeff_RHS%Version CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) IF ( Check_Once ) RETURN END IF ! Check dimensions ! ---------------- IF ( SpcCoeff_LHS%n_Channels /= SpcCoeff_RHS%n_Channels ) THEN Error_Status = FAILURE WRITE( Message, '( "n_Channels dimensions are different : ", & &i0, " vs. ", i0 )' ) & SpcCoeff_LHS%n_Channels, SpcCoeff_RHS%n_Channels CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) RETURN END IF ! Compare the values ! ------------------ ! The Sensor_ID IF ( SpcCoeff_LHS%Sensor_Id /= SpcCoeff_RHS%Sensor_Id ) THEN Error_Status = FAILURE WRITE( Message, '( "Sensor_ID values are different, ", & &a, " vs. ", a )' ) & TRIM( SpcCoeff_LHS%Sensor_Id), & TRIM( SpcCoeff_RHS%Sensor_Id) CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) IF ( Check_Once ) RETURN END IF ! The Sensor_Type IF ( SpcCoeff_LHS%Sensor_Type /= SpcCoeff_RHS%Sensor_Type ) THEN WRITE( Message,'("Sensor types are different, ", & &i0,"(",a,") vs. ", i0,"(",a,")")' ) & SpcCoeff_LHS%Sensor_Type, & TRIM(SENSOR_TYPE_NAME(SpcCoeff_LHS%Sensor_Type)), & SpcCoeff_RHS%Sensor_Type, & TRIM(SENSOR_TYPE_NAME(SpcCoeff_RHS%Sensor_Type)) CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) IF ( Check_Once ) RETURN END IF ! The WMO Satellite ID IF ( SpcCoeff_LHS%WMO_Satellite_ID /= SpcCoeff_RHS%WMO_Satellite_ID ) THEN Error_Status = FAILURE WRITE( Message,'("WMO_Satellite_ID values are different, ",i0,& &" vs. ",i0 )' ) & SpcCoeff_LHS%WMO_Satellite_ID, & SpcCoeff_RHS%WMO_Satellite_ID CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) IF ( Check_Once ) RETURN END IF ! The WMO Sensor ID IF ( SpcCoeff_LHS%WMO_Sensor_ID /= SpcCoeff_RHS%WMO_Sensor_ID ) THEN Error_Status = FAILURE WRITE( Message,'("WMO_Sensor_ID values are different, ",i0,& &" vs. ",i0)' ) & SpcCoeff_LHS%WMO_Sensor_ID, & SpcCoeff_RHS%WMO_Sensor_ID CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) IF ( Check_Once ) RETURN END IF ! The Sensor_Channel DO l = 1, SpcCoeff_RHS%n_Channels IF ( SpcCoeff_LHS%Sensor_Channel(l) /= SpcCoeff_RHS%Sensor_Channel(l) ) THEN Error_Status = FAILURE WRITE( Message,'("Sensor_Channel values are different, ",i0,& &" vs. ",i0,", for channel index # ",i0)' ) & SpcCoeff_LHS%Sensor_Channel(l), & SpcCoeff_RHS%Sensor_Channel(l), & l CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) IF ( Check_Once ) RETURN END IF END DO ! The Polarization indicator flag DO l = 1, SpcCoeff_RHS%n_Channels IF ( SpcCoeff_LHS%Polarization(l) /= SpcCoeff_RHS%Polarization(l) ) THEN Error_Status = FAILURE WRITE( Message,'("Polarization values are different, ",i0,& &" vs. ",i0,", for channel index # ", i0)' ) & SpcCoeff_LHS%Polarization(l), & SpcCoeff_RHS%Polarization(l), & l CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) IF ( Check_Once ) RETURN END IF END DO ! The Channel_Flag DO l = 1, SpcCoeff_RHS%n_Channels IF ( SpcCoeff_LHS%Channel_Flag(l) /= SpcCoeff_RHS%Channel_Flag(l) ) THEN Error_Status = FAILURE WRITE( Message,'("Channel_Flag values are different, ",b32.32,& &" vs. ",b32.32,", for channel index # ", i0)' ) & SpcCoeff_LHS%Channel_Flag(l), & SpcCoeff_RHS%Channel_Flag(l), & l CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) IF ( Check_Once ) RETURN END IF END DO ! The central Frequency DO l = 1, SpcCoeff_RHS%n_Channels IF ( .NOT. ( Compare_Float( SpcCoeff_LHS%Frequency(l), & SpcCoeff_RHS%Frequency(l), & ULP = ULP ) ) ) THEN Error_Status = FAILURE Message = Construct_Message( 'Frequency', l, & SpcCoeff_LHS%Frequency(l), & SpcCoeff_RHS%Frequency(l) ) CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) IF ( Check_Once ) RETURN END IF END DO ! The central Wavenumber DO l = 1, SpcCoeff_RHS%n_Channels IF ( .NOT. ( Compare_Float( SpcCoeff_LHS%Wavenumber(l), & SpcCoeff_RHS%Wavenumber(l), & ULP = ULP ) ) ) THEN Error_Status = FAILURE Message = Construct_Message( 'Wavenumber', l, & SpcCoeff_LHS%Wavenumber(l), & SpcCoeff_RHS%Wavenumber(l) ) CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) IF ( Check_Once ) RETURN END IF END DO ! The first Planck function constant, Planck_C1 DO l = 1, SpcCoeff_RHS%n_Channels IF ( .NOT. ( Compare_Float( SpcCoeff_LHS%Planck_C1(l), & SpcCoeff_RHS%Planck_C1(l), & ULP = ULP ) ) ) THEN Error_Status = FAILURE Message = Construct_Message( 'Planck_C1', l, & SpcCoeff_LHS%Planck_C1(l), & SpcCoeff_RHS%Planck_C1(l) ) CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) IF ( Check_Once ) RETURN END IF END DO ! The second Planck function constant, Planck_C2 DO l = 1, SpcCoeff_RHS%n_Channels IF ( .NOT. ( Compare_Float( SpcCoeff_LHS%Planck_C2(l), & SpcCoeff_RHS%Planck_C2(l), & ULP = ULP ) ) ) THEN Error_Status = FAILURE Message = Construct_Message( 'Planck_C2', l, & SpcCoeff_LHS%Planck_C2(l), & SpcCoeff_RHS%Planck_C2(l) ) CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) IF ( Check_Once ) RETURN END IF END DO ! The band correction offset, Band_C1 DO l = 1, SpcCoeff_RHS%n_Channels IF ( .NOT. ( Compare_Float( SpcCoeff_LHS%Band_C1(l), & SpcCoeff_RHS%Band_C1(l), & ULP = ULP ) ) ) THEN Error_Status = FAILURE Message = Construct_Message( 'Band_C1', l, & SpcCoeff_LHS%Band_C1(l), & SpcCoeff_RHS%Band_C1(l) ) CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) IF ( Check_Once ) RETURN END IF END DO ! The band correction slope, Band_C2 DO l = 1, SpcCoeff_RHS%n_Channels IF ( .NOT. ( Compare_Float( SpcCoeff_LHS%Band_C2(l), & SpcCoeff_RHS%Band_C2(l), & ULP = ULP ) ) ) THEN Error_Status = FAILURE Message = Construct_Message( 'Band_C2', l, & SpcCoeff_LHS%Band_C2(l), & SpcCoeff_RHS%Band_C2(l) ) CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) IF ( Check_Once ) RETURN END IF END DO ! The Cosmic_Background_Radiance DO l = 1, SpcCoeff_RHS%n_Channels IF ( .NOT. ( Compare_Float( SpcCoeff_LHS%Cosmic_Background_Radiance(l), & SpcCoeff_RHS%Cosmic_Background_Radiance(l), & ULP = ULP ) ) ) THEN Error_Status = FAILURE Message = Construct_Message( 'Cosmic_Background_Radiance', l, & SpcCoeff_LHS%Cosmic_Background_Radiance(l), & SpcCoeff_RHS%Cosmic_Background_Radiance(l) ) CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) IF ( Check_Once ) RETURN END IF END DO ! The Kurucz TOA Solar_Irradiance source function DO l = 1, SpcCoeff_RHS%n_Channels IF ( .NOT. ( Compare_Float( SpcCoeff_LHS%Solar_Irradiance(l), & SpcCoeff_RHS%Solar_Irradiance(l), & ULP = ULP ) ) ) THEN Error_Status = FAILURE Message = Construct_Message( 'Solar_Irradiance', l, & SpcCoeff_LHS%Solar_Irradiance(l), & SpcCoeff_RHS%Solar_Irradiance(l) ) CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) IF ( Check_Once ) RETURN END IF END DO ! Check the Antenna Correction structures ! --------------------------------------- IF ( SpcCoeff_LHS%AC_Present .NEQV. SpcCoeff_RHS%AC_Present ) THEN Error_Status = FAILURE WRITE( Message, '("AC_Present indicators different : ", 2(l1,1x))' ) & SpcCoeff_LHS%AC_Present, SpcCoeff_RHS%AC_Present CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) IF ( Check_Once ) RETURN END IF IF ( SpcCoeff_LHS%AC_Present ) THEN Error_Status = Equal_AntCorr( SpcCoeff_LHS%AC, & SpcCoeff_RHS%AC, & Message_Log=Message_Log) IF ( Error_Status /= SUCCESS ) THEN CALL Display_Message( ROUTINE_NAME, & 'Error comparing AC structure for '//& TRIM(SpcCoeff_LHS%Sensor_Id), & Error_Status, & Message_Log=Message_Log ) IF ( Check_Once ) RETURN END IF END IF END FUNCTION Equal_SpcCoeff !---------------------------------------------------------------------------------- ! ! NAME: ! CheckRelease_SpcCoeff ! ! PURPOSE: ! Function to check the SpcCoeff Release value. ! ! CALLING SEQUENCE: ! Error_Status = CheckRelease_SpcCoeff( SpcCoeff , & ! Input ! RCS_Id =RCS_Id , & ! Revision control ! Message_Log=Message_Log ) ! Error messaging ! ! INPUT ARGUMENTS: ! SpcCoeff: SpcCoeff structure for which the Release member ! is to be checked. ! UNITS: N/A ! TYPE: SpcCoeff_type ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(OUT) ! ! OPTIONAL INPUT ARGUMENTS: ! Message_Log: Character string specifying a filename in which any ! messages will be logged. If not specified, or if an ! error occurs opening the log file, the default action ! is to output messages to standard output. ! UNITS: N/A ! TYPE: CHARACTER(*) ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN), OPTIONAL ! ! OPTIONAL OUTPUT ARGUMENTS: ! RCS_Id: Character string containing the Revision Control ! System Id field for the module. ! UNITS: N/A ! TYPE: CHARACTER(*) ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(OUT), OPTIONAL ! ! FUNCTION RESULT: ! Error_Status: The return value is an integer defining the error status. ! The error codes are defined in the Message_Handler module. ! If == SUCCESS the structure Release value is valid. ! == FAILURE the structure Release value is NOT valid ! and either a data file file or software ! update is required. ! UNITS: N/A ! TYPE: INTEGER ! DIMENSION: Scalar ! !---------------------------------------------------------------------------------- FUNCTION CheckRelease_SpcCoeff( SpcCoeff , & ! Input RCS_Id , & ! Revision control Message_Log) & ! Error messaging RESULT( Error_Status ) ! Arguments TYPE(SpcCoeff_type) , INTENT(IN) :: SpcCoeff CHARACTER(*), OPTIONAL, INTENT(OUT) :: RCS_Id CHARACTER(*), OPTIONAL, INTENT(IN) :: Message_Log ! Function result INTEGER :: Error_Status ! Local parameters CHARACTER(*), PARAMETER :: ROUTINE_NAME = 'CheckRelease_SpcCoeff' ! Local variables CHARACTER(256) :: Message ! Set up ! ------ Error_Status = SUCCESS IF ( PRESENT( RCS_Id ) ) RCS_Id = MODULE_RCS_ID ! Check the release ! ----------------- ! Check that release is not too old IF ( SpcCoeff%Release < SPCCOEFF_RELEASE ) THEN Error_Status = FAILURE WRITE( Message, '( "An SpcCoeff data update is needed. ", & &"SpcCoeff release is ", i2, & &". Valid release is ",i2,"." )' ) & SpcCoeff%Release, SPCCOEFF_RELEASE CALL Display_Message( TRIM(Routine_Name), & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) RETURN END IF ! Check that release is not too new IF ( SpcCoeff%Release > SPCCOEFF_RELEASE ) THEN Error_Status = FAILURE WRITE( Message, '( "A SpcCoeff software update is needed. ", & &"SpcCoeff release is ", i2, & &". Valid release is ",i2,"." )' ) & SpcCoeff%Release, SPCCOEFF_RELEASE CALL Display_Message( TRIM(Routine_Name), & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) RETURN END IF END FUNCTION CheckRelease_SpcCoeff !-------------------------------------------------------------------------------- ! ! NAME: ! Info_SpcCoeff ! ! PURPOSE: ! Subroutine to return a string containing version and dimension ! information about the SpcCoeff data structure. ! ! CALLING SEQUENCE: ! CALL Info_SpcCoeff( SpcCoeff , & ! Input ! Info , & ! Output ! RCS_Id=RCS_Id ) ! Revision control ! ! INPUT ARGUMENTS: ! SpcCoeff: Filled SpcCoeff structure. ! UNITS: N/A ! TYPE: SpcCoeff_type ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN) ! ! OUTPUT ARGUMENTS: ! Info: String containing version and dimension information ! about the passed SpcCoeff data structure. ! UNITS: N/A ! TYPE: CHARACTER(*) ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(OUT) ! ! OPTIONAL OUTPUT ARGUMENTS: ! RCS_Id: Character string containing the Revision Control ! System Id field for the module. ! UNITS: N/A ! TYPE: CHARACTER(*) ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(OUT), OPTIONAL ! !-------------------------------------------------------------------------------- SUBROUTINE Info_SpcCoeff( SpcCoeff, & ! Input Info , & ! Output RCS_Id ) ! Revision control ! Arguments TYPE(SpcCoeff_type) , INTENT(IN) :: SpcCoeff CHARACTER(*) , INTENT(OUT) :: Info CHARACTER(*), OPTIONAL, INTENT(OUT) :: RCS_Id ! Local variables CHARACTER(2000) :: LongString CHARACTER(2000) :: ACString ! Set up ! ------ IF ( PRESENT( RCS_Id ) ) RCS_Id = MODULE_RCS_ID ! Write the required data to the local string ! ------------------------------------------- WRITE( LongString, '( a,1x,"SpcCoeff RELEASE.VERSION: ",i2,".",i2.2,2x,& &"N_CHANNELS=",i0)' ) & ACHAR(CARRIAGE_RETURN)//ACHAR(LINEFEED), & SpcCoeff%Release, SpcCoeff%Version, & SpcCoeff%n_Channels ! Add the antenna correction structure info if present ! ---------------------------------------------------- IF ( SpcCoeff%AC_Present ) THEN CALL Info_AntCorr( SpcCoeff%AC, ACString ) LongString = TRIM(LongString)//TRIM(ACString) END IF ! Trim the output based on the ! dummy argument string length ! ---------------------------- Info = LongString(1:MIN( LEN(Info), LEN_TRIM(LongString) )) END SUBROUTINE Info_SpcCoeff !################################################################################## !################################################################################## !## ## !## ## PRIVATE MODULE ROUTINES ## ## !## ## !################################################################################## !################################################################################## !---------------------------------------------------------------------------------- ! ! NAME: ! Clear_SpcCoeff ! ! PURPOSE: ! Subroutine to clear the scalar members of an SpcCoeff structure. ! ! CALLING SEQUENCE: ! CALL Clear_SpcCoeff( SpcCoeff ) ! Output ! ! OUTPUT ARGUMENTS: ! SpcCoeff: SpcCoeff structure for which the scalar members have ! been cleared. ! UNITS: N/A ! TYPE: SpcCoeff_type ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN OUT) ! ! COMMENTS: ! Note the INTENT on the output SpcCoeff argument is IN OUT rather than ! just OUT. This is necessary because the argument may be defined upon ! input. To prevent memory leaks, the IN OUT INTENT is a must. ! !---------------------------------------------------------------------------------- SUBROUTINE Clear_SpcCoeff( SpcCoeff ) TYPE(SpcCoeff_type), INTENT(IN OUT) :: SpcCoeff SpcCoeff%Release = SPCCOEFF_RELEASE SpcCoeff%Version = SPCCOEFF_VERSION SpcCoeff%AC_Present = .FALSE. SpcCoeff%Sensor_Id = ' ' SpcCoeff%Sensor_Type = INVALID_SENSOR SpcCoeff%WMO_Satellite_ID = INVALID_WMO_SATELLITE_ID SpcCoeff%WMO_Sensor_ID = INVALID_WMO_SENSOR_ID END SUBROUTINE Clear_SpcCoeff !---------------------------------------------------------------------------------- ! ! NAME: ! Construct_Message ! ! PURPOSE: ! Function to to construct a standard message when a floating point ! number comparison fails in the Equal_SpcCoeff() functions. ! ! CALLING SEQUENCE: ! Message = Construct_Message( Label, i, x1, x2, Node ) ! ! INPUT ARGUMENTS: ! Label: Character string containing the name of the data ! that was compared. ! UNITS: N/A ! TYPE: CHARACTER(*) ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN) ! ! i: The index (channel or node) in the SpcCoeff structure ! at which the floating point comparison failed. ! UNITS: N/A ! TYPE: INTEGER ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN) ! ! x1, x2: The numbers for which the floating point comparison ! failed. These are used to determine the best floating ! point format with which to output the numbers in the ! message. ! UNITS: N/A ! TYPE: REAL(Double) ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN) ! ! FUNCTION RESULT: ! Message: Character string containing the constructed error ! that is passed into the Display_Message subroutine. ! UNITS: N/A ! TYPE: CHARACTER(*) ! DIMENSION: Scalar ! !---------------------------------------------------------------------------------- FUNCTION Construct_Message( Label, i, x1, x2 ) RESULT( Message ) ! Arguments CHARACTER(*), INTENT(IN) :: Label INTEGER, INTENT(IN) :: i REAL(Double), INTENT(IN) :: x1, x2 ! Function result CHARACTER(256) :: Message ! Local parameters INTEGER, PARAMETER :: WIDTH = 20 REAL(Double), PARAMETER :: HUNDRED = 100.0_Double ! Local variables CHARACTER(6) :: Real_Format CHARACTER(256) :: Format_String INTEGER :: n REAL(Double) :: dx ! Determine the print format for the floating ! point numbers based on their magnitudes ! ------------------------------------------- n = WIDTH - INT( MAX( LOG10(x1), LOG10(x2), 0.0_Double ) ) - 2 WRITE( Real_Format, FMT='("f",i2.2,".",i2.2)' ) WIDTH, n ! Construct the format string used to create the message ! ------------------------------------------------------ Format_String = '( "'//TRIM(Label)//' difference, ", '//Real_Format//& ', " vs. ", '//Real_Format//', "(", es9.2, "% diff), '//& 'channel index # ", i4 )' ! Create the message ! ------------------ dx = HUNDRED * ( x1-x2 ) / x1 WRITE( Message, FMT=TRIM(Format_String) ) x1, x2, dx, i END FUNCTION Construct_Message END MODULE SpcCoeff_Define