! ! ODAS_Define ! ! Module defining the ODAS (Optical Depth, Absorber Space) data structure and ! containing routines to manipulate it. ! ! ! CREATION HISTORY: ! Written by: Paul van Delst, CIMSS/SSEC 18-Mar-2002 ! paul.vandelst@ssec.wisc.edu ! MODULE ODAS_Define ! ------------------ ! Environment set up ! ------------------ ! 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 Sort_Utility, ONLY: InsertionSort USE CRTM_Parameters, ONLY: ODAS_ALGORITHM ! Disable implicit typing IMPLICIT NONE ! ------------ ! Visibilities ! ------------ ! Everything private by default PRIVATE ! Public types ! ------------ PUBLIC :: ODAS_type ! Public procedures ! ----------------- PUBLIC :: Associated_ODAS PUBLIC :: Destroy_ODAS PUBLIC :: Allocate_ODAS PUBLIC :: Assign_ODAS PUBLIC :: Equal_ODAS PUBLIC :: CheckRelease_ODAS PUBLIC :: CheckAlgorithm_ODAS PUBLIC :: Info_ODAS ! 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 :: SENSOR_TYPE_NAME PUBLIC :: ODAS_RELEASE ! The Global unique algorithm ID PUBLIC :: ODAS_ALGORITHM ! ----------------- ! Module parameters ! ----------------- ! RCS Id for the module CHARACTER(*), PARAMETER :: MODULE_RCS_ID = & '$Id: ODAS_Define.f90 22707 2012-11-21 21:09:10Z paul.vandelst@noaa.gov $' ! ODAS invalid values INTEGER, PARAMETER :: IP_INVALID = -1 REAL(Double), PARAMETER :: FP_INVALID = -1.0_Double ! Keyword set value INTEGER, PARAMETER :: SET = 1 ! String lengths INTEGER, PARAMETER :: SL = 20 ! Sensor Id INTEGER, PARAMETER :: ML = 256 ! Messages ! Current valid release and version numbers INTEGER, PARAMETER :: ODAS_RELEASE = 7 ! This determines structure and file formats. INTEGER, PARAMETER :: ODAS_VERSION = 1 ! This is just the data version. ! The optical depth algorithm name CHARACTER(*), PARAMETER :: ODAS_ALGORITHM_NAME = 'ODAS' ! ASCII codes for Version routine INTEGER, PARAMETER :: CARRIAGE_RETURN = 13 INTEGER, PARAMETER :: LINEFEED = 10 ! Invalid sensor ids INTEGER, PARAMETER :: INVALID_WMO_SATELLITE_ID = 1023 INTEGER, PARAMETER :: INVALID_WMO_SENSOR_ID = 2047 ! The instrument types INTEGER, PARAMETER :: N_SENSOR_TYPES = 4 INTEGER, PARAMETER :: INVALID_SENSOR = 0 INTEGER, PARAMETER :: MICROWAVE_SENSOR = 1 INTEGER, PARAMETER :: INFRARED_SENSOR = 2 INTEGER, PARAMETER :: VISIBLE_SENSOR = 3 INTEGER, PARAMETER :: ULTRAVIOLET_SENSOR = 4 CHARACTER(*), PARAMETER, DIMENSION( 0:N_SENSOR_TYPES ) :: & SENSOR_TYPE_NAME = (/ 'Invalid ', & 'Microwave ', & 'Infrared ', & 'Visible ', & 'Ultraviolet' /) ! ------------------------- ! ODAS data type definition ! ------------------------- TYPE :: ODAS_type INTEGER :: n_Allocates = 0 ! Release and version information INTEGER(Long) :: Release = ODAS_RELEASE INTEGER(Long) :: Version = ODAS_VERSION ! Algorithm identifer INTEGER(Long) :: Algorithm = ODAS_ALGORITHM ! Dimensions INTEGER(Long) :: n_Predictors = 0 ! Iuse INTEGER(Long) :: n_Absorbers = 0 ! J INTEGER(Long) :: n_Channels = 0 ! L INTEGER(Long) :: n_Alphas = 0 ! Ia INTEGER(Long) :: n_Coeffs = 0 ! Co dimension of the C array ! 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 ! The actual sensor channel numbers INTEGER(Long), POINTER :: Sensor_Channel(:) => NULL() ! L ! The absorber ID and absorber space values INTEGER(Long), POINTER :: Absorber_ID(:) => NULL() ! J ! maximum order of the polynomial function for each absorber, independent channel INTEGER(Long), POINTER :: Max_Order(:) => NULL() ! J ! Coefficients for computing absorber level ! Alpha(1, j) - the original alpha ! Alpha(2, j) - the original alpha_C1 ! Alpha(3, j) - the original alpha_C2 REAL(Double), POINTER :: Alpha(:,:) => NULL() ! Ia x J !----------------------------------------------------------------------------------- ! Order - used maximum order of the polynomial function, given absorber and channel ! Pre_Index - Predict index. Pre_Index(0, j, l) is the numberof used predictors ! for absorber j and channel l ! Pos_Index - starting position of a coefficient subset ! C - tau coefficient ! ! The C array is one-dimesional and its internal structure is given by the Order, ! Pre_index and the Pos_index arrays. Let j and l be the array indexes along ! the absorber and channel dimensions: ! ps = Pos_Index(j, l) and n = Pre_Index(0, j l)*Order(j,l) are the starting ! position and size of the coefficient sub-set in array C at absorber j and ! channel l. The coefficient sub-set is equally divided into np+1 segments, ! where np = Pre_Index(0, j, l) is the number of predictors. The np+1 segments ! are used to compute the set of np+1 B coefficiets. The B coefficents are then ! used to compute the absorption coefficients. !------------------------------------------------------------------------------------ INTEGER(LONG), POINTER :: Order(:,:) => NULL() ! J x L INTEGER(Long), POINTER :: Pre_Index(:,:,:) => NULL() ! 0:Iuse x J x L INTEGER(Long), POINTER :: Pos_Index(:,:) => NULL() ! J x L REAL(Double), POINTER :: C(:) => NULL() ! Co ! tau coefficient array END TYPE ODAS_type CONTAINS !################################################################################ !################################################################################ !## ## !## ## PUBLIC MODULE ROUTINES ## ## !## ## !################################################################################ !################################################################################ !-------------------------------------------------------------------------------- ! ! NAME: ! Associated_ODAS ! ! PURPOSE: ! Function to test the association status of the pointer members of a ! ODAS structure. ! ! CALLING SEQUENCE: ! Association_Status = Associated_ODAS( ODAS ,& ! Input ! ANY_Test=Any_Test ) ! Optional input ! ! INPUT ARGUMENTS: ! ODAS: ODAS structure which is to have its pointer ! member's association status tested. ! UNITS: N/A ! TYPE: ODAS_type ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN) ! ! OPTIONAL INPUT ARGUMENTS: ! ANY_Test: Set this argument to test if ANY of the ! ODAS 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. ! ! FUNCTION RESULT: ! Association_Status: The return value is a logical value indicating the ! association status of the ODAS pointer members. ! .TRUE. - if ALL the ODAS pointer members are ! associated, or if the ANY_Test argument ! is set and ANY of the ODAS pointer ! members are associated. ! .FALSE. - some or all of the ODAS pointer ! members are NOT associated. ! UNITS: N/A ! TYPE: LOGICAL ! DIMENSION: Scalar ! !-------------------------------------------------------------------------------- FUNCTION Associated_ODAS( ODAS , & ! Input ANY_Test) & ! Optional input RESULT( Association_Status ) ! Arguments TYPE(ODAS_type) , INTENT(IN) :: ODAS 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( ODAS%Sensor_Channel ) .AND. & ASSOCIATED( ODAS%Absorber_ID ) .AND. & ASSOCIATED( ODAS%Max_Order ) .AND. & ASSOCIATED( ODAS%Alpha ) .AND. & ASSOCIATED( ODAS%Order ) .AND. & ASSOCIATED( ODAS%Pre_Index ) .AND. & ASSOCIATED( ODAS%Pos_Index ) .AND. & ASSOCIATED( ODAS%C ) ) THEN Association_Status = .TRUE. END IF ELSE IF ( ASSOCIATED( ODAS%Sensor_Channel ) .OR. & ASSOCIATED( ODAS%Absorber_ID ) .OR. & ASSOCIATED( ODAS%Max_Order ) .OR. & ASSOCIATED( ODAS%Alpha ) .OR. & ASSOCIATED( ODAS%Order ) .OR. & ASSOCIATED( ODAS%Pre_Index ) .OR. & ASSOCIATED( ODAS%Pos_Index ) .OR. & ASSOCIATED( ODAS%C ) ) THEN Association_Status = .TRUE. END IF END IF END FUNCTION Associated_ODAS !------------------------------------------------------------------------------ ! ! NAME: ! Destroy_ODAS ! ! PURPOSE: ! Function to re-initialize the scalar and pointer members of ODAS ! data structures. ! ! CALLING SEQUENCE: ! Error_Status = Destroy_ODAS( ODAS , & ! Output ! RCS_Id =RCS_Id , & ! Revision control ! Message_Log=Message_Log ) ! Error messaging ! ! OUTPUT ARGUMENTS: ! ODAS: Re-initialized ODAS structure. ! UNITS: N/A ! TYPE: ODAS_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: OPTIONAL, INTENT(IN) ! ! 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: OPTIONAL, INTENT(OUT) ! ! 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 ODAS 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_ODAS( ODAS , & ! Output No_Clear , & ! Optional input RCS_Id , & ! Revision control Message_Log) & ! Error messaging RESULT( Error_Status ) ! Arguments TYPE(ODAS_type) , INTENT(IN OUT) :: ODAS 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_ODAS' ! Local variables CHARACTER(ML) :: Message LOGICAL :: Clear INTEGER :: Allocate_Status ! Set up ! ------ Error_Status = SUCCESS IF ( PRESENT( RCS_Id ) ) RCS_Id = MODULE_RCS_ID ! Reinitialise the dimensions ODAS%n_Predictors = 0 ODAS%n_Absorbers = 0 ODAS%n_Channels = 0 ODAS%n_Alphas = 0 ODAS%n_Coeffs = 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_ODAS( ODAS ) ! If ALL components are NOT associated, do nothing IF ( .NOT. Associated_ODAS( ODAS ) ) RETURN ! Deallocate the regular arrays components ! ---------------------------------------- DEALLOCATE( ODAS%Sensor_Channel , & ODAS%Absorber_ID , & ODAS%Max_Order , & ODAS%Alpha , & ODAS%Order , & ODAS%Pre_Index , & ODAS%Pos_Index , & ODAS%C , & STAT=Allocate_Status ) IF ( Allocate_Status /= 0 ) THEN Error_Status = FAILURE WRITE( Message,'("Error deallocating ODAS components. STAT = ",i0)' ) & Allocate_Status CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) END IF ! Decrement and test allocation counter ! ------------------------------------- ODAS%n_Allocates = ODAS%n_Allocates - 1 IF ( ODAS%n_Allocates /= 0 ) THEN Error_Status = FAILURE WRITE( Message,'("Allocation counter /= 0, Value = ",i0)' ) & ODAS%n_Allocates CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) END IF END FUNCTION Destroy_ODAS !------------------------------------------------------------------------------ ! ! NAME: ! Allocate_ODAS ! ! PURPOSE: ! Function to allocate the pointer members of the ODAS ! data structure. ! ! CALLING SEQUENCE: ! Error_Status = Allocate_ODAS( n_Predictors , & ! Input ! n_Absorbers , & ! Input ! n_Channels , & ! Input ! n_Alphas , & ! Input ! n_Coeffs , & ! Input ! ODAS , & ! Output ! RCS_Id =RCS_Id , & ! Revision control ! Message_Log=Message_Log ) ! Error messaging ! ! INPUT ARGUMENTS: ! ! n_Predictors: Maximum number of predictors dimension. ! Must be > 0. ! UNITS: N/A ! TYPE: INTEGER ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN) ! ! n_Absorbers: Number of absorbers dimension. ! Must be > 0. ! UNITS: N/A ! TYPE: INTEGER ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN) ! ! n_Channels: Number of channels dimension. ! Must be > 0. ! UNITS: N/A ! TYPE: INTEGER ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN) ! ! n_Alphas: Number of Alpha dimension. ! Must be > 0. ! UNITS: N/A ! TYPE: INTEGER ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN) ! ! n_Coeffs: Number of coefficient dimension. ! Must be > 0. ! UNITS: N/A ! TYPE: INTEGER ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN) ! ! OUTPUT ARGUMENTS: ! ODAS: ODAS structure with allocated ! pointer members ! UNITS: N/A ! TYPE: ODAS_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: OPTIONAL, INTENT(IN) ! ! 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: OPTIONAL, INTENT(OUT) ! ! 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 one (1) 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 ODAS 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_ODAS( n_Predictors, & ! Input n_Absorbers , & ! Input n_Channels , & ! Input n_Alphas , & ! Input n_Coeffs , & ! Input ODAS , & ! Output RCS_Id , & ! Revision control Message_Log ) & ! Error messaging RESULT( Error_Status ) ! Arguments INTEGER , INTENT(IN) :: n_Predictors INTEGER , INTENT(IN) :: n_Absorbers INTEGER , INTENT(IN) :: n_Channels INTEGER , INTENT(IN) :: n_Alphas INTEGER , INTENT(IN) :: n_Coeffs TYPE(ODAS_type) , INTENT(IN OUT) :: ODAS CHARACTER(*), OPTIONAL, INTENT(OUT) :: RCS_Id CHARACTER(*), OPTIONAL, INTENT(IN) :: Message_Log ! Function result INTEGER :: Error_Status ! Local parameters CHARACTER(*), PARAMETER :: ROUTINE_NAME = 'Allocate_ODAS' ! Local variables CHARACTER(ML) :: Message INTEGER :: Allocate_Status ! Set up ! ------ Error_Status = SUCCESS IF ( PRESENT( RCS_Id ) ) RCS_Id = MODULE_RCS_ID ! Check dimension input IF ( n_Predictors < 1 .OR. & n_Absorbers < 1 .OR. & n_Channels < 1 .OR. & n_Alphas < 1 .OR. & n_Coeffs < 1 ) THEN Error_Status = FAILURE CALL Display_Message( ROUTINE_NAME, & 'Input ODAS dimensions must all be > 0.', & Error_Status, & Message_Log=Message_Log ) RETURN END IF ! Check if ANY pointers are already associated. ! If they are, deallocate them but leave scalars. IF ( Associated_ODAS( ODAS, ANY_Test=SET ) ) THEN Error_Status = Destroy_ODAS( ODAS, & No_Clear=SET, & Message_Log=Message_Log ) IF ( Error_Status /= SUCCESS ) THEN CALL Display_Message( ROUTINE_NAME, & 'Error deallocating ODAS prior to reallocation.', & Error_Status, & Message_Log=Message_Log ) RETURN END IF END IF ! Allocate the data arrays ! ------------------------ ALLOCATE( ODAS%Sensor_Channel( n_Channels ), & ODAS%Absorber_ID( n_Absorbers ), & ODAS%Max_Order( n_Absorbers ), & ODAS%Alpha( n_Alphas, n_Absorbers ), & ODAS%Order( n_Absorbers, n_Channels ), & ODAS%Pre_Index( 0:n_Predictors, n_Absorbers, n_Channels ), & ODAS%Pos_Index( n_Absorbers, n_Channels ), & ODAS%C( n_Coeffs ), & STAT=Allocate_Status ) IF ( Allocate_Status /= 0 ) THEN Error_Status = FAILURE WRITE( Message,'("Error allocating ODAS 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 ODAS%n_Predictors = n_Predictors ODAS%n_Absorbers = n_Absorbers ODAS%n_Channels = n_Channels ODAS%n_Alphas = n_Alphas ODAS%n_Coeffs = n_Coeffs ODAS%Sensor_Channel = 0 ODAS%Absorber_ID = IP_INVALID ODAS%Max_Order = IP_INVALID ODAS%Alpha = FP_INVALID ODAS%Order = IP_INVALID ODAS%Pre_Index = IP_INVALID ODAS%Pos_Index = IP_INVALID ODAS%C = FP_INVALID ! Increment and test allocation counter ! ------------------------------------- ODAS%n_Allocates = ODAS%n_Allocates + 1 IF ( ODAS%n_Allocates /= 1 ) THEN Error_Status = FAILURE WRITE( Message,'("Allocation counter /= 1, Value = ",i0)' ) & ODAS%n_Allocates CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) RETURN END IF END FUNCTION Allocate_ODAS !------------------------------------------------------------------------------ ! ! NAME: ! Assign_ODAS ! ! PURPOSE: ! Function to copy valid ODAS structures. ! ! CALLING SEQUENCE: ! Error_Status = Assign_ODAS( ODAS_in , & ! Input ! ODAS_out , & ! Output ! RCS_Id =RCS_Id , & ! Revision control ! Message_Log=Message_Log ) ! Error messaging ! ! INPUT ARGUMENTS: ! ODAS_in: ODAS structure which is to be copied. ! UNITS: N/A ! TYPE: ODAS_type ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN) ! ! OUTPUT ARGUMENTS: ! ODAS_out: Copy of the input structure, ODAS_in. ! UNITS: N/A ! TYPE: ODAS_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: OPTIONAL, INTENT(IN) ! ! 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: OPTIONAL, INTENT(OUT) ! ! 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 ODAS 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_ODAS( ODAS_in , & ! Input ODAS_out , & ! Output RCS_Id , & ! Revision control Message_Log ) & ! Error messaging RESULT( Error_Status ) ! Arguments TYPE(ODAS_type) , INTENT(IN) :: ODAS_in TYPE(ODAS_type) , INTENT(IN OUT) :: ODAS_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_ODAS' ! Set up ! ------ IF ( PRESENT( RCS_Id ) ) RCS_Id = MODULE_RCS_ID ! ALL *input* pointers must be associated IF ( .NOT. Associated_ODAS( ODAS_In ) ) THEN Error_Status = FAILURE CALL Display_Message( ROUTINE_NAME, & 'Some or all INPUT ODAS pointer '//& 'members are NOT associated.', & Error_Status, & Message_Log=Message_Log ) RETURN END IF ! Allocate the structure ! ---------------------- Error_Status = Allocate_ODAS( ODAS_in%n_Predictors, & ODAS_in%n_Absorbers , & ODAS_in%n_Channels , & ODAS_in%n_Alphas , & ODAS_in%n_Coeffs , & ODAS_out, & Message_Log=Message_Log ) IF ( Error_Status /= SUCCESS ) THEN CALL Display_Message( ROUTINE_NAME, & 'Error allocating output ODAS arrays.', & Error_Status, & Message_Log=Message_Log ) RETURN END IF ! Assign intrinsic data types ! --------------------------- ODAS_out%Release = ODAS_in%Release ODAS_out%Version = ODAS_in%Version ODAS_out%Sensor_Id = ODAS_in%Sensor_Id ODAS_out%Sensor_Type = ODAS_in%Sensor_Type ODAS_out%WMO_Satellite_ID = ODAS_in%WMO_Satellite_ID ODAS_out%WMO_Sensor_ID = ODAS_in%WMO_Sensor_ID ODAS_out%Sensor_Channel = ODAS_in%Sensor_Channel ODAS_out%Absorber_ID = ODAS_in%Absorber_ID ODAS_out%Max_Order = ODAS_in%Max_Order ODAS_out%Alpha = ODAS_in%Alpha ODAS_out%Order = ODAS_in%Order ODAS_out%Pre_Index = ODAS_in%Pre_Index ODAS_out%Pos_Index = ODAS_in%Pos_Index ODAS_out%C = ODAS_in%C END FUNCTION Assign_ODAS !------------------------------------------------------------------------------ ! ! NAME: ! Equal_ODAS ! ! PURPOSE: ! Function to test if two ODAS structures are equal. ! ! CALLING SEQUENCE: ! Error_Status = Equal_ODAS( ODAS_LHS , & ! Input ! ODAS_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: ! ODAS_LHS: ODAS structure to be compared; equivalent to the ! left-hand side of a lexical comparison, e.g. ! IF ( ODAS_LHS == ODAS_RHS ). ! UNITS: N/A ! TYPE: ODAS_type ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN) ! ! ODAS_RHS: ODAS structure to be compared to; equivalent to ! right-hand side of a lexical comparison, e.g. ! IF ( ODAS_LHS == ODAS_RHS ). ! UNITS: N/A ! TYPE: ODAS_type ! 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: OPTIONAL, INTENT(IN) ! ! Check_All: Set this argument to check ALL the *floating point* ! channel data of the ODAS 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 ODAS 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. ! Note: Setting this argument has no effect if, for ! example, the structure dimensions are different, ! or the sensor ids/channels are different, or the ! absorber ids are different, etc. ! UNITS: N/A ! TYPE: INTEGER ! DIMENSION: Scalar ! ATTRIBUTES: OPTIONAL, 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: OPTIONAL, INTENT(IN) ! ! 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: OPTIONAL, INTENT(OUT) ! ! 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 ! ! COMMENTS: ! Congruency of the structure data is a prerequisite of equality. ! That is, the *order* of the data is important. For example, if ! two structures contain the same absorber information, but in a ! different order, the structures are not considered equal. ! !------------------------------------------------------------------------------ FUNCTION Equal_ODAS( ODAS_LHS , & ! Input ODAS_RHS , & ! Input ULP_Scale , & ! Optional input Check_All , & ! Optional input RCS_Id , & ! Revision control Message_Log) & ! Error messaging RESULT( Error_Status ) ! Arguments TYPE(ODAS_type) , INTENT(IN) :: ODAS_LHS TYPE(ODAS_type) , INTENT(IN) :: ODAS_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_ODAS' ! Local variables CHARACTER(ML) :: Message INTEGER :: ULP LOGICAL :: Check_Once INTEGER(LONG) :: i, j, l, ip ! 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 == 1 ) Check_Once = .FALSE. END IF ! Check the structure association status IF ( .NOT. Associated_ODAS( ODAS_LHS ) ) THEN Error_Status = FAILURE CALL Display_Message( ROUTINE_NAME, & 'Some or all INPUT ODAS_LHS pointer '//& 'members are NOT associated.', & Error_Status, & Message_Log=Message_Log ) RETURN END IF IF ( .NOT. Associated_ODAS( ODAS_RHS ) ) THEN Error_Status = FAILURE CALL Display_Message( ROUTINE_NAME, & 'Some or all INPUT ODAS_RHS pointer '//& 'members are NOT associated.', & Error_Status, & Message_Log=Message_Log ) RETURN END IF ! Check structure Release/Version ! ------------------------------- IF ( ( ODAS_LHS%Release /= ODAS_RHS%Release ) .OR. & ( ODAS_LHS%Version /= ODAS_RHS%Version ) ) THEN Error_Status = FAILURE WRITE( Message, '( "Release/Version numbers are different : ", & &i2, ".", i2.2, " vs. ", i2, ".", i2.2 )' ) & ODAS_LHS%Release, ODAS_LHS%Version, & ODAS_RHS%Release, ODAS_RHS%Version CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) IF ( Check_Once ) RETURN END IF ! Check dimensions ! ---------------- IF ( ODAS_LHS%n_Predictors /= ODAS_RHS%n_Predictors .OR. & ODAS_LHS%n_Absorbers /= ODAS_RHS%n_Absorbers .OR. & ODAS_LHS%n_Channels /= ODAS_RHS%n_Channels .OR. & ODAS_LHS%n_Alphas /= ODAS_RHS%n_Alphas .OR. & ODAS_LHS%n_Coeffs /= ODAS_RHS%n_Coeffs ) THEN Error_Status = FAILURE CALL Display_Message( ROUTINE_NAME, & 'Structure dimensions are different', & Error_Status, & Message_Log=Message_Log ) RETURN END IF ! Compare the values ! ------------------ ! The Sensor_ID IF ( ODAS_LHS%Sensor_Id /= ODAS_RHS%Sensor_Id ) THEN Error_Status = FAILURE WRITE( Message, '( "Sensor_ID values are different, ", & &a, " vs. ", a )' ) & TRIM( ODAS_LHS%Sensor_Id), & TRIM( ODAS_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 ( ODAS_LHS%Sensor_Type /= ODAS_RHS%Sensor_Type ) THEN WRITE( Message,'("Sensor types are different, ", & &i0,"(",a,") vs. ", i0,"(",a,")")' ) & ODAS_LHS%Sensor_Type, & TRIM(SENSOR_TYPE_NAME(ODAS_LHS%Sensor_Type)), & ODAS_RHS%Sensor_Type, & TRIM(SENSOR_TYPE_NAME(ODAS_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 ( ODAS_LHS%WMO_Satellite_ID /= ODAS_RHS%WMO_Satellite_ID ) THEN Error_Status = FAILURE WRITE( Message,'("WMO_Satellite_ID values are different, ",i0,& &" vs. ",i0 )' ) & ODAS_LHS%WMO_Satellite_ID, & ODAS_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 ( ODAS_LHS%WMO_Sensor_ID /= ODAS_RHS%WMO_Sensor_ID ) THEN Error_Status = FAILURE WRITE( Message,'("WMO_Sensor_ID values are different, ",i0,& &" vs. ",i0)' ) & ODAS_LHS%WMO_Sensor_ID, & ODAS_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, ODAS_RHS%n_Channels IF ( ODAS_LHS%Sensor_Channel(l) /= ODAS_RHS%Sensor_Channel(l) ) THEN Error_Status = FAILURE WRITE( Message,'("Sensor_Channel values are different, ",i0,& &" vs. ",i0,", for channel index # ",i0)' ) & ODAS_LHS%Sensor_Channel(l), & ODAS_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 Absorber_ID DO j = 1, ODAS_RHS%n_Absorbers IF ( ODAS_LHS%Absorber_ID(j) /= ODAS_RHS%Absorber_ID(j) ) THEN Error_Status = FAILURE WRITE( Message,'("Absorber_ID values are different, ",i0,& &" vs. ",i0,", for absorber index # ",i0)' ) & ODAS_LHS%Absorber_ID(j), & ODAS_RHS%Absorber_ID(j), & j CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) IF ( Check_Once ) RETURN END IF END DO ! The Max Order array DO j = 1, ODAS_RHS%n_Absorbers IF ( ODAS_LHS%Max_Order(j) /= ODAS_RHS%Max_Order(j) ) THEN Error_Status = FAILURE WRITE( Message,'("Order values are different, ",i0,& &" vs. ",i0,", for index (",i0,")")' ) & ODAS_LHS%Max_Order(j), & ODAS_RHS%Max_Order(j), & j CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) IF ( Check_Once ) RETURN END IF END DO ! The Alpha value DO j = 1, ODAS_RHS%n_Absorbers DO i = 1, ODAS_RHS%n_Alphas IF ( .NOT. ( Compare_Float( ODAS_LHS%Alpha(i,j), & ODAS_RHS%Alpha(i,j), & ULP = ULP ) ) ) THEN Error_Status = FAILURE WRITE( Message,'("Alpha values are different, ",es13.6,& &" vs. ",es13.6,", for alpha index # ",i0,& &" and absorber index #",i0 )' ) & ODAS_LHS%Alpha(i,j), & ODAS_RHS%Alpha(i,j), & i,j CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) IF ( Check_Once ) RETURN END IF END DO END DO ! The Order array DO l = 1, ODAS_RHS%n_Channels DO j = 1, ODAS_RHS%n_Absorbers IF ( ODAS_LHS%Order(j,l) /= ODAS_RHS%Order(j,l) ) THEN Error_Status = FAILURE WRITE( Message,'("Order values are different, ",i0,& &" vs. ",i0,", for index (",i0,1x,i0,")")' ) & ODAS_LHS%Order(j,l), & ODAS_RHS%Order(j,l), & j,l CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) IF ( Check_Once ) RETURN END IF END DO END DO ! The Pre_Index DO l = 1, ODAS_RHS%n_Channels DO j = 1, ODAS_RHS%n_Absorbers DO ip = 0, ODAS_RHS%n_Predictors IF ( ODAS_LHS%Pre_Index(ip,j,l) /= ODAS_RHS%Pre_Index(ip,j,l) ) THEN Error_Status = FAILURE WRITE( Message,'("Predictor_Index values are different, ",i0,& &" vs. ",i0,", for index (",i0,1x,i0,1x,i0,")")' ) & ODAS_LHS%Pre_Index(ip,j,l), & ODAS_RHS%Pre_Index(ip,j,l), & ip,j,l CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) IF ( Check_Once ) RETURN END IF END DO END DO END DO ! The Pos_Index DO l = 1, ODAS_RHS%n_Channels DO j = 1, ODAS_RHS%n_Absorbers IF ( ODAS_LHS%Pos_Index(j,l) /= ODAS_RHS%Pos_Index(j,l) ) THEN Error_Status = FAILURE WRITE( Message,'("Predictor_Index values are different, ",i0,& &" vs. ",i0,", for index (",i0,1x,i0,")")' ) & ODAS_LHS%Pos_Index(j,l), & ODAS_RHS%Pos_Index(j,l), & j,l CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) IF ( Check_Once ) RETURN END IF END DO END DO ! The Coefficients DO i = 1, ODAS_RHS%n_Coeffs IF ( ODAS_LHS%C(i) /= ODAS_RHS%C(i) ) THEN Error_Status = FAILURE WRITE( Message,'("C values are different, ",i0,& &" vs. ",i0,", for index (",i0,")")' ) & ODAS_LHS%C(i), & ODAS_RHS%C(i), & i CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) IF ( Check_Once ) RETURN END IF END DO END FUNCTION Equal_ODAS !---------------------------------------------------------------------------------- ! ! NAME: ! CheckRelease_ODAS ! ! PURPOSE: ! Function to check the ODAS Release value. ! ! CALLING SEQUENCE: ! Error_Status = CheckRelease_ODASe( ODAS , & ! Input ! RCS_Id = RCS_Id , & ! Revision control ! Message_Log=Message_Log ) ! Error messaging ! ! INPUT ARGUMENTS: ! ODAS: ODAS structure for which the Release member ! is to be checked. ! UNITS: N/A ! TYPE: ODAS_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: OPTIONAL, INTENT(IN) ! 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: OPTIONAL, INTENT(OUT) ! ! 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_ODAS( ODAS , & ! Input RCS_Id , & ! Revision control Message_Log) & ! Error messaging RESULT( Error_Status ) ! Arguments TYPE(ODAS_type) , INTENT(IN) :: ODAS CHARACTER(*), OPTIONAL, INTENT(OUT) :: RCS_Id CHARACTER(*), OPTIONAL, INTENT(IN) :: Message_Log ! Function result INTEGER :: Error_Status ! Local parameters CHARACTER(*), PARAMETER :: ROUTINE_NAME = 'CheckRelease_ODAS' ! Local variables CHARACTER(ML) :: 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 ( ODAS%Release < ODAS_RELEASE ) THEN Error_Status = FAILURE WRITE( Message, '( "An ODAS data update is needed. ", & &"ODAS release is ", i2, & &". Valid release is ",i2,"." )' ) & ODAS%Release, ODAS_RELEASE CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) RETURN END IF ! Check that release is not too new IF ( ODAS%Release > ODAS_RELEASE ) THEN Error_Status = FAILURE WRITE( Message, '( "An ODAS software update is needed. ", & &"ODAS release is ", i2, & &". Valid release is ",i2,"." )' ) & ODAS%Release, ODAS_RELEASE CALL Display_Message( ROUTINE_NAME, & TRIM(Message), & Error_Status, & Message_Log=Message_Log ) RETURN END IF END FUNCTION CheckRelease_ODAS !---------------------------------------------------------------------------------- ! ! NAME: ! CheckAlgorithm_ODAS ! ! PURPOSE: ! Function to check the ODAS Algorithm value. ! ! CALLING SEQUENCE: ! Error_Status = CheckAlgorithm_ODAS( ODAS , & ! Input ! RCS_Id = RCS_Id , & ! Revision control ! Message_Log=Message_Log ) ! Error messaging ! ! INPUT ARGUMENTS: ! ODAS: ODAS structure for which the Algorithm member ! is to be checked. ! UNITS: N/A ! TYPE: ODAS_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: OPTIONAL, INTENT(IN) ! 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: OPTIONAL, INTENT(OUT) ! ! 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 Algorithm value is valid. ! == FAILURE the structure Algorithm value is NOT valid. ! UNITS: N/A ! TYPE: INTEGER ! DIMENSION: Scalar ! !---------------------------------------------------------------------------------- FUNCTION CheckAlgorithm_ODAS( ODAS , & ! Input RCS_Id , & ! Revision control Message_Log) & ! Error messaging RESULT( Error_Status ) ! Arguments TYPE(ODAS_type) , INTENT(IN) :: ODAS CHARACTER(*), OPTIONAL, INTENT(OUT) :: RCS_Id CHARACTER(*), OPTIONAL, INTENT(IN) :: Message_Log ! Function result INTEGER :: Error_Status ! Local parameters CHARACTER(*), PARAMETER :: ROUTINE_NAME = 'CheckAlgorithm_ODAS' ! Set up ! ------ Error_Status = SUCCESS IF ( PRESENT(RCS_Id) ) RCS_Id = MODULE_RCS_ID ! Check the algorithm ID ! ---------------------- IF ( ODAS%Algorithm /= ODAS_ALGORITHM ) THEN Error_Status = FAILURE CALL Display_Message( ROUTINE_NAME, & 'The ODAS Algorithm ID check failed. '//& 'The data structure is not an ODAS structure', & Error_Status, & Message_Log=Message_Log ) RETURN END IF END FUNCTION CheckAlgorithm_ODAS !------------------------------------------------------------------------------ ! ! NAME: ! Info_ODAS ! ! PURPOSE: ! Subroutine to return a string containing version and dimension ! information about the ODAS data structure. ! ! CALLING SEQUENCE: ! CALL Info_ODAS( ODAS , & ! Input ! Info , & ! Output ! RCS_Id=RCS_Id ) ! Revision control ! ! INPUT ARGUMENTS: ! ODAS: Filled ODAS structure. ! UNITS: N/A ! TYPE: ODAS_type ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN) ! ! OUTPUT ARGUMENTS: ! Info: String containing version and dimension information ! about the passed ODAS 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: OPTIONAL, INTENT(OUT) ! !------------------------------------------------------------------------------ SUBROUTINE Info_ODAS( ODAS , & ! Input Info , & ! Output RCS_Id ) ! Revision control ! Arguments TYPE(ODAS_type) , INTENT(IN) :: ODAS CHARACTER(*), INTENT(OUT) :: Info CHARACTER(*), OPTIONAL, INTENT(OUT) :: RCS_Id ! Local variables CHARACTER(2000) :: LongString ! Set up ! ------ IF ( PRESENT( RCS_Id ) ) RCS_Id = MODULE_RCS_ID ! Write the required data to the local string ! ------------------------------------------- WRITE( LongString,'( a,3x,"ODAS RELEASE.VERSION: ",i2,".",i2.2,2x,& &"N_PREDICTORS=",i2,2x,& &"N_ABSORBERS=",i2,2x,& &"N_CHANNELS=",i0,2x, & &"N_Alphas=",i2,2x, & &"N_Coeffs=",i0)' ) & ACHAR(CARRIAGE_RETURN)//ACHAR(LINEFEED), & ODAS%Release, ODAS%Version, & ODAS%n_Predictors, & ODAS%n_Absorbers, & ODAS%n_Channels, & ODAS%n_Alphas, & ODAS%n_Coeffs ! Trim the output based on the ! dummy argument string length ! ---------------------------- Info = LongString(1:MIN( LEN(Info), LEN_TRIM(LongString) )) END SUBROUTINE Info_ODAS !################################################################################## !################################################################################## !## ## !## ## PRIVATE MODULE ROUTINES ## ## !## ## !################################################################################## !################################################################################## !---------------------------------------------------------------------------------- ! ! NAME: ! Clear_ODAS ! ! PURPOSE: ! Subroutine to clear the scalar members of a ODAS structure. ! ! CALLING SEQUENCE: ! CALL Clear_ODAS( ODAS ) ! Output ! ! OUTPUT ARGUMENTS: ! ODAS: ODAS structure for which the scalar members have ! been cleared. ! UNITS: N/A ! TYPE: ODAS_type ! DIMENSION: Scalar ! ATTRIBUTES: INTENT(IN OUT) ! ! COMMENTS: ! Note the INTENT on the output ODAS 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_ODAS( ODAS ) TYPE(ODAS_type), INTENT(IN OUT) :: ODAS ODAS%Release = ODAS_RELEASE ODAS%Version = ODAS_VERSION ODAS%Algorithm = ODAS_ALGORITHM ODAS%Sensor_Id = ' ' ODAS%Sensor_Type = INVALID_SENSOR ODAS%WMO_Satellite_ID = INVALID_WMO_SATELLITE_ID ODAS%WMO_Sensor_ID = INVALID_WMO_SENSOR_ID END SUBROUTINE Clear_ODAS END MODULE ODAS_Define