!--------------------------------------------------------------------------------
!M+
! NAME:
!       SpcCoeff_Define
!
! PURPOSE:
!       Module defining the SpcCoeff data structure and containing routines to 
!       manipulate it.
!       
! CATEGORY:
!       Instrument Information : SpcCoeff
!
! LANGUAGE:
!       Fortran-95
!
! CALLING SEQUENCE:
!       USE SpcCoeff_Define
!
! MODULES:
!       Type_Kinds:             Module containing definitions for kinds
!                               of variable types.
!
!       Error_Handler:          Module to define simple error codes and
!                               handle error conditions
!                               USEs: FILE_UTILITY module
!
!       Compare_Float_Numbers:  Module containing routines to perform equality
!                               and relational comparisons on floating point
!                               numbers.
!                               USEs: TYPE_KINDS module
!
! CONTAINS:
!       Associated_SpcCoeff:          Function to test the association status
!                                     of the pointer members of a SpcCoeff
!                                     structure.
!
!       Destroy_SpcCoeff:             Function to re-initialize an SpcCoeff
!                                     structure.
!
!       Allocate_SpcCoeff:            Function to allocate the pointer members
!                                     of an SpcCoeff structure.
!
!       Assign_SpcCoeff:              Function to copy an SpcCoeff structure.
!
!       Concatenate_SpcCoeff:         Function to concatenate two SpcCoeff
!                                     structures along the CHANNEL dimension.
!
!       Equal_SpcCoeff:               Function to test if two SpcCoeff
!                                     structures are equal.
!
!       Check_SpcCoeff_Release:       Function to check the SpcCoeff Release value.
!
!       Count_SpcCoeff_Sensors:       Subroutine to count the number of
!                                     different satellites/sensors in the
!                                     SpcCoeff data structure.
!
!       Version_SpcCoeff:             Subroutine to return a string containing
!                                     version and dimension information about
!                                     the SpcCoeff data structure.
!
! DERIVED TYPES:
!       SpcCoeff_type:   Definition of the SpcCoeff data structure. Fields
!                        are...
!
!         Release:                       Coefficient data release.
!                                        UNITS:      N/A
!                                        TYPE:       INTEGER
!                                        DIMENSION:  Scalar
!
!         Version:                       Coefficient data version.
!                                        UNITS:      N/A
!                                        TYPE:       INTEGER
!                                        DIMENSION:  Scalar
!
!         n_Stokes:                      Number of Stokes parameters used to represent
!                                        channel polarization.
!                                        UNITS:      N/A
!                                        TYPE:       INTEGER
!                                        DIMENSION:  Scalar
!
!         n_Channels:                    Total number of spectral channels.
!                                        "L" dimension.
!                                        UNITS:      N/A
!                                        TYPE:       INTEGER
!                                        DIMENSION:  Scalar
!
!         n_Sensors:                     Number of different satellite/sensors in the
!                                        data structure.
!                                        UNITS:      N/A
!                                        TYPE:       INTEGER
!                                        DIMENSION:  Scalar
!
!         Sensor_Descriptor:             String variable containing a short text
!                                        description of the sensor and satellite.
!                                        Descriptors are taken from the SensorInfo
!                                        file prefix member. Examples are:
!                                          - hirs3_n17
!                                          - airs_aqua
!                                          - ssmis_f16... etc
!                                        UNITS:      N/A
!                                        TYPE:       CHARACTER( 20 )
!                                        DIMENSION:  Rank-1 (n_Channels)
!                                        ATTRIBUTES: POINTER
!
!         NCEP_Sensor_ID:                An "in-house" value used at NOAA/NCEP/EMC 
!                                        to identify a satellite/sensor combination.
!                                        UNITS:      N/A
!                                        TYPE:       INTEGER
!                                        DIMENSION:  Rank-1 (n_Channels)
!                                        ATTRIBUTES: POINTER
!
!         WMO_Satellite_ID:              The WMO code for identifying satellite
!                                        platforms. Taken from the WMO common
!                                        code tables at:
!                                          http://www.wmo.ch/web/ddbs/Code-tables.html
!                                        The Satellite ID is from Common Code
!                                        table C-5, or code table 0 01 007 in BUFR
!                                        UNITS:      N/A
!                                        TYPE:       INTEGER
!                                        DIMENSION:  Rank-1 (n_Channels)
!                                        ATTRIBUTES: POINTER
!
!         WMO_Sensor_ID:                 The WMO code for identifying a satelite
!                                        sensor. Taken from the WMO common
!                                        code tables at:
!                                          http://www.wmo.ch/web/ddbs/Code-tables.html
!                                        The Sensor ID is from Common Code
!                                        table C-8, or code table 0 02 019 in BUFR
!                                        UNITS:      N/A
!                                        TYPE:       INTEGER
!                                        DIMENSION:  Rank-1 (n_Channels)
!                                        ATTRIBUTES: POINTER
!
!         Sensor_Channel:                This is the sensor channel number associated
!                                        with the data in the coefficient file. Helps
!                                        in identifying channels where the numbers are
!                                        not contiguous (e.g. AIRS).
!                                        UNITS:      N/A
!                                        TYPE:       INTEGER
!                                        DIMENSION:  Rank-1 (n_Channels)
!                                        ATTRIBUTES: POINTER
!
!         Frequency:                     Channel central frequencies in gigahertz.
!                                        UNITS:      Gigahertz (GHz)
!                                        TYPE:       REAL( Double )
!                                        DIMENSION:  Rank-1 (n_Channels )
!                                        ATTRIBUTES: POINTER
!
!         Wavenumber:                    Channel central frequencies in inverse
!                                        centimetres.
!                                        UNITS:      inverse centimetres (cm^-1)
!                                        TYPE:       REAL( Double )
!                                        DIMENSION:  Rank-1 (n_Channels )
!                                        ATTRIBUTES: POINTER
!
!         Planck_C1:                     First Planck function value for each
!                                        channel.
!                                        UNITS:      mW/(m^2.sr.cm^-1)
!                                        TYPE:       REAL( Double )
!                                        DIMENSION:  Rank-1 (n_Channels )
!                                        ATTRIBUTES: POINTER
!
!         Planck_C2:                     Second Planck function value for each
!                                        channel.
!                                        UNITS:      K
!                                        TYPE:       REAL( Double )
!                                        DIMENSION:  Rank-1 (n_Channels )
!                                        ATTRIBUTES: POINTER
!
!         Band_C1:                       Channel polychromaticity correction
!                                        offsets.
!                                        UNITS:      K
!                                        TYPE:       REAL( Double )
!                                        DIMENSION:  Rank-1 (n_Channels )
!                                        ATTRIBUTES: POINTER
!
!         Band_C2:                       Channel polychromaticity correction
!                                        slopes.
!                                        UNITS:      K/K
!                                        TYPE:       REAL( Double )
!                                        DIMENSION:  Rank-1 (n_Channels )
!                                        ATTRIBUTES: POINTER
!
!         Is_Microwave_Channel:          Array of flags indicating if a channel
!                                        is microwave.
!                                        UNITS:      N/A
!                                        TYPE:       INTEGER( Long )
!                                        DIMENSION:  Rank-1 (n_Channels )
!                                        ATTRIBUTES: POINTER
!
!         Polarization:                  Channel polarization represented using Stokes
!                                        vectors. IR channels are all assumed unpolarized.
!                                        UNITS:      N/A
!                                        TYPE:       REAL( Double )
!                                        DIMENSION:  Rank-1 ( n_Stokes x n_Channels )
!                                        ATTRIBUTES: POINTER
!
!         Cosmic_Background_Temperature: Effective cosmic background temperature.
!                                        UNITS:      K
!                                        TYPE:       REAL( Double )
!                                        DIMENSION:  Rank-1 (n_Channels )
!                                        ATTRIBUTES: POINTER
!
!         Cosmic_Background_Radiance:    Cosmic background radiance.
!                                        UNITS:      mW/(m^2.sr.cm^-1)
!                                        TYPE:       REAL( Double )
!                                        DIMENSION:  Rank-1 (n_Channels )
!                                        ATTRIBUTES: POINTER
!
!         Is_Solar_Channel:              Array of flags indicating if a channel
!                                        is sensitive to solar contribution.
!                                        UNITS:      N/A
!                                        TYPE:       INTEGER( Long )
!                                        DIMENSION:  Rank-1 (n_Channels )
!                                        ATTRIBUTES: POINTER
!
!         Solar_Irradiance:              Kurucz solar irradiance source function.
!                                        UNITS:      mW/(m^2.cm^-1)
!                                        TYPE:       REAL( Double )
!                                        DIMENSION:  Rank-1 (n_Channels )
!                                        ATTRIBUTES: POINTER
!
!         Blackbody_Irradiance:          Equivalent blackbody solar irradiance
!                                        source function.
!                                        UNITS:      mW/(m^2.cm^-1)
!                                        TYPE:       REAL( Double )
!                                        DIMENSION:  Rank-1 (n_Channels )
!                                        ATTRIBUTES: POINTER
!
!       *!IMPORTANT!*
!       -------------
!       Note that the SpcCoeff_type is PUBLIC and its members are not
!       encapsulated; that is, they can be fully accessed outside the
!       scope of this module. This makes it possible to manipulate
!       the structure and its data directly rather than, for e.g., via
!       get() and set() functions. This was done to eliminate the
!       overhead of the get/set type of structure access in using the
!       structure. *But*, it is recommended that the user initialize,
!       destroy, allocate, assign, and concatenate the structure
!       using only the routines in this module where possible to
!       eliminate -- or at least minimise -- the possibility of 
!       memory leakage since most of the structure members are
!       pointers.
!
! INCLUDE FILES:
!       None.
!
! EXTERNALS:
!       None.
!
! COMMON BLOCKS:
!       None.
!
! FILES ACCESSED:
!       None.
!
! CREATION HISTORY:
!       Written by:     Paul van Delst, CIMSS/SSEC 18-Mar-2002
!                       paul.vandelst@ssec.wisc.edu
!
!  Copyright (C) 2002 Paul van Delst
!
!  This program is free software; you can redistribute it and/or
!  modify it under the terms of the GNU General Public License
!  as published by the Free Software Foundation; either version 2
!  of the License, or (at your option) any later version.
!
!  This program is distributed in the hope that it will be useful,
!  but WITHOUT ANY WARRANTY; without even the implied warranty of
!  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
!  GNU General Public License for more details.
!
!  You should have received a copy of the GNU General Public License
!  along with this program; if not, write to the Free Software
!  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
!M-
!--------------------------------------------------------------------------------

MODULE SpcCoeff_Define

  ! ----------
  ! Module use
  ! ----------

  USE Type_Kinds
  USE Error_Handler
  USE Compare_Float_Numbers

  ! -----------------------
  ! Disable implicit typing
  ! -----------------------

  IMPLICIT NONE

  ! ------------
  ! Visibilities
  ! ------------

  ! -- Everything private by default
  PRIVATE

  ! -- Public procedures to manipulate the SpcCoeff structure
  PUBLIC :: Associated_SpcCoeff
  PUBLIC :: Destroy_SpcCoeff
  PUBLIC :: Allocate_SpcCoeff
  PUBLIC :: Assign_SpcCoeff
  PUBLIC :: Concatenate_SpcCoeff
  PUBLIC :: Equal_SpcCoeff
  PUBLIC :: Check_SpcCoeff_Release
  PUBLIC :: Count_SpcCoeff_Sensors
  PUBLIC :: Version_SpcCoeff

  ! -------------------------
  ! PRIVATE Module parameters
  ! -------------------------

  ! -- RCS Id for the module
  CHARACTER( * ), PRIVATE, PARAMETER :: MODULE_RCS_ID = &
  '$Id: SpcCoeff_Define.f90,v 4.7 2004/09/27 19:05:28 paulv Exp $'

  ! -- SpcCoeff scalar member invalid value
  INTEGER, PRIVATE, PARAMETER :: INVALID = -1

  ! -- Keyword set value
  INTEGER, PRIVATE, PARAMETER :: SET = 1

  ! -- Sensor descriptor component string length
  INTEGER, PRIVATE, PARAMETER :: DL = 20

  ! -- Current valid release and version numbers
  INTEGER, PRIVATE, PARAMETER :: SPCCOEFF_RELEASE = 4  ! This determines structure and file formats.
  INTEGER, PRIVATE, PARAMETER :: SPCCOEFF_VERSION = 1  ! This is just the data version.

  ! -- The number of Stokes parameters for describing polarization
  INTEGER, PRIVATE, PARAMETER :: N_STOKES_PARAMETERS = 4

  ! ------------------------
  ! PUBLIC Module parameters
  ! ------------------------

  ! -- Number of SpcCoeff pointer data items
  INTEGER( Long ), PUBLIC, PARAMETER :: N_SPCCOEFF_ITEMS = 18_Long

  ! -- Data types of the SpcCoeff pointer data
  !    7 = Character string
  !    5 = Double (i.e. 8-byte float)
  !    4 = Single (i.e. 4-byte float)
  !    3 = Long   (i.e. 4-byte integer)
  INTEGER( Long ), PUBLIC, PARAMETER, &
                   DIMENSION( N_SPCCOEFF_ITEMS ) :: SPCCOEFF_DATA_TYPE = &
                                                       (/ 7_Long, &  ! Sensor_Descriptor
                                                          3_Long, &  ! NCEP_Sensor_ID
                                                          3_Long, &  ! WMO_Satellite_ID
                                                          3_Long, &  ! WMO_Sensor_ID
                                                          3_Long, &  ! Sensor_Channel
                                                          5_Long, &  ! Frequency
                                                          5_Long, &  ! Wavenumber
                                                          5_Long, &  ! Planck_C1
                                                          5_Long, &  ! Planck_C2
                                                          5_Long, &  ! Band_C1
                                                          5_Long, &  ! Band_C2
                                                          3_Long, &  ! Is_Microwave_Channel
                                                          5_Long, &  ! Polarization
                                                          5_Long, &  ! Cosmic_Background_Temperature
                                                          5_Long, &  ! Cosmic_Background_Radiance
                                                          3_Long, &  ! Is_Solar_Channel
                                                          5_Long, &  ! Solar_Irradiance
                                                          5_Long /)  ! Blackbody_Irradiance

  ! -- Names of the pointer data items (for error processing)
  CHARACTER( * ), PUBLIC, PARAMETER, &
                  DIMENSION( N_SPCCOEFF_ITEMS ) :: SPCCOEFF_DATA_NAME = &
                                                    (/ 'Sensor_Descriptor            ', &
                                                       'NCEP_Sensor_ID               ', &
                                                       'WMO_Satellite_ID             ', &
                                                       'WMO_Sensor_id                ', &
                                                       'Sensor_Channel               ', &
                                                       'Frequency                    ', &
                                                       'Wavenumber                   ', &
                                                       'Planck_C1                    ', &
                                                       'Planck_C2                    ', &
                                                       'Band_C1                      ', &
                                                       'Band_C2                      ', &
                                                       'Is_Microwave_Channel         ', &
                                                       'Polarization                 ', &
                                                       'Cosmic_Background_Temperature', &
                                                       'Cosmic_Background_Radiance   ', &
                                                       'Is_Solar_Channel             ', &
                                                       'Solar_Irradiance             ', &
                                                       'Blackbody_Irradiance         ' /)

  ! ------------------------------
  ! SpcCoeff data type definition
  ! ------------------------------

  TYPE, PUBLIC :: SpcCoeff_type
    INTEGER :: n_Allocates = 0

    INTEGER( Long ) :: Release = SPCCOEFF_RELEASE
    INTEGER( Long ) :: Version = SPCCOEFF_VERSION

    INTEGER( Long ) :: Sensor_Descriptor_StrLen = DL

    INTEGER( Long ) :: n_Stokes   = 0  ! Is dimension
    INTEGER( Long ) :: n_Channels = 0  ! L  dimension

    INTEGER( Long ) :: n_Sensors = 0

    CHARACTER( DL ), POINTER, DIMENSION( : )    :: Sensor_Descriptor => NULL()
    INTEGER( Long ), POINTER, DIMENSION( : )    :: NCEP_Sensor_ID   => NULL()               ! L
    INTEGER( Long ), POINTER, DIMENSION( : )    :: WMO_Satellite_ID => NULL()               ! L
    INTEGER( Long ), POINTER, DIMENSION( : )    :: WMO_Sensor_ID    => NULL()               ! L
    INTEGER( Long ), POINTER, DIMENSION( : )    :: Sensor_Channel   => NULL()               ! L
    REAL( Double ),  POINTER, DIMENSION( : )    :: Frequency  => NULL()                     ! L
    REAL( Double ),  POINTER, DIMENSION( : )    :: Wavenumber => NULL()                     ! L
    REAL( Double ),  POINTER, DIMENSION( : )    :: Planck_C1 => NULL()                      ! L
    REAL( Double ),  POINTER, DIMENSION( : )    :: Planck_C2 => NULL()                      ! L
    REAL( Double ),  POINTER, DIMENSION( : )    :: Band_C1 => NULL()                        ! L
    REAL( Double ),  POINTER, DIMENSION( : )    :: Band_C2 => NULL()                        ! L
    INTEGER( Long ), POINTER, DIMENSION( : )    :: Is_Microwave_Channel => NULL()           ! L
    REAL( Double ),  POINTER, DIMENSION( :, : ) :: Polarization  => NULL()                  ! Is x L
    REAL( Double ),  POINTER, DIMENSION( : )    :: Cosmic_Background_Temperature => NULL()  ! L
    REAL( Double ),  POINTER, DIMENSION( : )    :: Cosmic_Background_Radiance    => NULL()  ! L
    INTEGER( Long ), POINTER, DIMENSION( : )    :: Is_Solar_Channel     => NULL()           ! L
    REAL( Double ),  POINTER, DIMENSION( : )    :: Solar_Irradiance     => NULL()           ! L
    REAL( Double ),  POINTER, DIMENSION( : )    :: Blackbody_Irradiance => NULL()           ! L
  END TYPE SpcCoeff_type

CONTAINS

!##################################################################################
!##################################################################################
!##                                                                              ##
!##                          ## PRIVATE MODULE ROUTINES ##                       ##
!##                                                                              ##
!##################################################################################
!##################################################################################

!----------------------------------------------------------------------------------
!
! NAME:
!       Clear_SpcCoeff
!
! PURPOSE:
!       Subroutine to clear the scalar members of a SpcCoeff structure.
!
! CATEGORY:
!       Instrument Information : SpcCoeff
!
! LANGUAGE:
!       Fortran-95
!
! CALLING SEQUENCE:
!       CALL Clear_SpcCoeff( SpcCoeff) ! Output
!
! INPUT ARGUMENTS:
!       None.
!
! OPTIONAL INPUT ARGUMENTS:
!       None.
!
! 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 )
!
! OPTIONAL OUTPUT ARGUMENTS:
!       None.
!
! CALLS:
!       None.
!
! SIDE EFFECTS:
!       None.
!
! RESTRICTIONS:
!       None.
!
! 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.
!
! CREATION HISTORY:
!       Written by:     Paul van Delst, CIMSS/SSEC 18-Mar-2002
!                       paul.vandelst@ssec.wisc.edu
!
!----------------------------------------------------------------------------------

  SUBROUTINE Clear_SpcCoeff( SpcCoeff )

    TYPE( SpcCoeff_type ), INTENT( IN OUT ) :: SpcCoeff

    SpcCoeff%Sensor_Descriptor_StrLen = DL
    SpcCoeff%n_Stokes   = 0
    SpcCoeff%n_Channels = 0
    SpcCoeff%n_Sensors  = 0
  END SUBROUTINE Clear_SpcCoeff

!################################################################################
!################################################################################
!##                                                                            ##
!##                         ## PUBLIC MODULE ROUTINES ##                       ##
!##                                                                            ##
!################################################################################
!################################################################################

!--------------------------------------------------------------------------------
!S+
! NAME:
!       Associated_SpcCoeff
!
! PURPOSE:
!       Function to test the association status of the pointer members of a
!       SpcCoeff structure.
!
! CATEGORY:
!       Instrument Information : SpcCoeff
!
! LANGUAGE:
!       Fortran-95
!
! 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
!
! OUTPUT ARGUMENTS:
!       None.
!
! OPTIONAL OUTPUT ARGUMENTS:
!       None.
!
! 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
!
! CALLS:
!       None.
!
! SIDE EFFECTS:
!       None.
!
! RESTRICTIONS:
!       None.
!
! CREATION HISTORY:
!       Written by:     Paul van Delst, CIMSS/SSEC 27-Mar-2003
!                       paul.vandelst@ssec.wisc.edu
!S-
!--------------------------------------------------------------------------------

  FUNCTION Associated_SpcCoeff( SpcCoeff,  & ! Input
                                ANY_Test ) & ! Optional input
                              RESULT( Association_Status )

    !#--------------------------------------------------------------------------#
    !#                        -- TYPE DECLARATIONS --                           #
    !#--------------------------------------------------------------------------#

    ! ---------
    ! Arguments
    ! ---------

    ! -- Input
    TYPE( SpcCoeff_type ), INTENT( IN ) :: SpcCoeff

    ! -- Optional input
    INTEGER,     OPTIONAL, INTENT( IN ) :: ANY_Test

    ! ---------------
    ! Function result
    ! ---------------

    LOGICAL :: Association_Status

    ! ---------------
    ! Local variables
    ! ---------------

    LOGICAL :: ALL_Test

    !#--------------------------------------------------------------------------#
    !#                           -- CHECK INPUT --                              #
    !#--------------------------------------------------------------------------#

    ! -- 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 STRUCTURE POINTER MEMBER ASSOCIATION --            #
    !#--------------------------------------------------------------------------#

    Association_Status = .FALSE.

    IF ( ALL_Test ) THEN

      IF ( ASSOCIATED( SpcCoeff%Sensor_Descriptor )             .AND. &
           ASSOCIATED( SpcCoeff%NCEP_Sensor_ID )                .AND. &
           ASSOCIATED( SpcCoeff%WMO_Satellite_ID )              .AND. &
           ASSOCIATED( SpcCoeff%WMO_Sensor_ID )                 .AND. &
           ASSOCIATED( SpcCoeff%Sensor_Channel )                .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%Is_Microwave_Channel )          .AND. &
           ASSOCIATED( SpcCoeff%Polarization )                  .AND. &
           ASSOCIATED( SpcCoeff%Cosmic_Background_Temperature ) .AND. &
           ASSOCIATED( SpcCoeff%Cosmic_Background_Radiance )    .AND. &
           ASSOCIATED( SpcCoeff%Is_Solar_Channel )              .AND. &
           ASSOCIATED( SpcCoeff%Solar_Irradiance )              .AND. &
           ASSOCIATED( SpcCoeff%Blackbody_Irradiance )                ) THEN
        Association_Status = .TRUE.
      END IF

    ELSE

      IF ( ASSOCIATED( SpcCoeff%Sensor_Descriptor )             .OR. &
           ASSOCIATED( SpcCoeff%NCEP_Sensor_ID )                .OR. &
           ASSOCIATED( SpcCoeff%WMO_Satellite_ID )              .OR. &
           ASSOCIATED( SpcCoeff%WMO_Sensor_ID )                 .OR. &
           ASSOCIATED( SpcCoeff%Sensor_Channel )                .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%Is_Microwave_Channel )          .OR. &
           ASSOCIATED( SpcCoeff%Polarization )                  .OR. &
           ASSOCIATED( SpcCoeff%Cosmic_Background_Temperature ) .OR. &
           ASSOCIATED( SpcCoeff%Cosmic_Background_Radiance )    .OR. &
           ASSOCIATED( SpcCoeff%Is_Solar_Channel )              .OR. &
           ASSOCIATED( SpcCoeff%Solar_Irradiance )              .OR. &
           ASSOCIATED( SpcCoeff%Blackbody_Irradiance )               ) THEN
        Association_Status = .TRUE.
      END IF

    END IF

  END FUNCTION Associated_SpcCoeff

!--------------------------------------------------------------------------------
!S+
! NAME:
!       Destroy_SpcCoeff
! 
! PURPOSE:
!       Function to re-initialize the scalar and pointer members of SpcCoeff
!       data structures.
!
! CATEGORY:
!       Instrument Information : SpcCoeff
!
! LANGUAGE:
!       Fortran-95
!
! CALLING SEQUENCE:
!       Error_Status = Destroy_SpcCoeff( SpcCoeff,                 &  ! Output
!                                        RCS_Id = RCS_Id,          &  ! Revision control
!                                        Message_Log = Message_Log )  ! Error messaging
!
! INPUT ARGUMENTS:
!       None.
!
! 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:      None
!                     TYPE:       CHARACTER(*)
!                     DIMENSION:  Scalar
!                     ATTRIBUTES: INTENT( IN ), OPTIONAL
!
! OUTPUT ARGUMENTS:
!       SpcCoeff:     Re-initialized SpcCoeff structure.
!                     UNITS:      N/A
!                     TYPE:       SpcCoeff_type
!                     DIMENSION:  Scalar
!                     ATTRIBUTES: INTENT( IN OUT )
!
! OPTIONAL OUTPUT ARGUMENTS:
!       RCS_Id:       Character string containing the Revision Control
!                     System Id field for the module.
!                     UNITS:      None
!                     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 ERROR_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
!
! CALLS:
!       Display_Message:    Subroutine to output messages
!                           SOURCE: ERROR_HANDLER module
!
! SIDE EFFECTS:
!       None.
!
! RESTRICTIONS:
!       None.
!
! 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.
!
! CREATION HISTORY:
!       Written by:     Paul van Delst, CIMSS/SSEC 18-Mar-2002
!                       paul.vandelst@ssec.wisc.edu
!S-
!--------------------------------------------------------------------------------

  FUNCTION Destroy_SpcCoeff( SpcCoeff,     &  ! Output
                             No_Clear,     &  ! Optional input
                             RCS_Id,       &  ! Revision control
                             Message_Log ) &  ! Error messaging
                           RESULT( Error_Status )

    !#--------------------------------------------------------------------------#
    !#                        -- TYPE DECLARATIONS --                           #
    !#--------------------------------------------------------------------------#

    ! ---------
    ! Arguments
    ! ---------

    ! -- Output
    TYPE( SpcCoeff_type ),    INTENT( IN OUT ) :: SpcCoeff

    ! -- Optional input
    INTEGER,        OPTIONAL, INTENT( IN )     :: No_Clear

    ! -- Revision control
    CHARACTER( * ), OPTIONAL, INTENT( OUT )    :: RCS_Id

    ! - Error messaging
    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 :: Allocate_Status

    !#--------------------------------------------------------------------------#
    !#                    -- SET SUCCESSFUL RETURN STATUS --                    #
    !#--------------------------------------------------------------------------#

    Error_Status = SUCCESS

    !#--------------------------------------------------------------------------#
    !#                -- SET THE RCS ID ARGUMENT IF SUPPLIED --                 #
    !#--------------------------------------------------------------------------#

    IF ( PRESENT( RCS_Id ) ) THEN
      RCS_Id = ' '
      RCS_Id = MODULE_RCS_ID
    END IF

    !#--------------------------------------------------------------------------#
    !#                      -- CHECK OPTIONAL ARGUMENTS --                      #
    !#--------------------------------------------------------------------------#

    ! -- 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

    
    !#--------------------------------------------------------------------------#
    !#                       -- PERFORM REINITIALISATION --                     #
    !#--------------------------------------------------------------------------#

    ! -----------------------------
    ! Initialise the scalar members
    ! -----------------------------

    IF ( Clear ) CALL Clear_SpcCoeff( SpcCoeff )

    ! -----------------------------------------------------
    ! If ALL pointer members are NOT associated, do nothing
    ! -----------------------------------------------------

    IF ( .NOT. Associated_SpcCoeff( SpcCoeff ) ) RETURN

    ! ------------------------------
    ! Deallocate the pointer members
    ! ------------------------------

    ! -- Deallocate the Sensor Descriptor
    IF ( ASSOCIATED( SpcCoeff%Sensor_Descriptor ) ) THEN

      DEALLOCATE( SpcCoeff%Sensor_Descriptor, STAT = Allocate_Status )

      IF ( Allocate_Status /= 0 ) THEN
        Error_Status = FAILURE
        WRITE( Message, '( "Error deallocating SpcCoeff Sensor_Descriptor ", &
                          &"member. STAT = ", i5 )' ) &
                        Allocate_Status
        CALL Display_Message( ROUTINE_NAME,    &
                              TRIM( Message ), &
                              Error_Status,    &
                              Message_Log = Message_Log )
      END IF
    END IF

    ! -- Deallocate the NCEP Sensor ID
    IF ( ASSOCIATED( SpcCoeff%NCEP_Sensor_ID ) ) THEN

      DEALLOCATE( SpcCoeff%NCEP_Sensor_ID, STAT = Allocate_Status )

      IF ( Allocate_Status /= 0 ) THEN
        Error_Status = FAILURE
        WRITE( Message, '( "Error deallocating SpcCoeff NCEP_Sensor_ID ", &
                          &"member. STAT = ", i5 )' ) &
                        Allocate_Status
        CALL Display_Message( ROUTINE_NAME,    &
                              TRIM( Message ), &
                              Error_Status,    &
                              Message_Log = Message_Log )
      END IF
    END IF

    ! -- Deallocate the WMO Satellite ID
    IF ( ASSOCIATED( SpcCoeff%WMO_Satellite_ID ) ) THEN

      DEALLOCATE( SpcCoeff%WMO_Satellite_ID, STAT = Allocate_Status )

      IF ( Allocate_Status /= 0 ) THEN
        Error_Status = FAILURE
        WRITE( Message, '( "Error deallocating SpcCoeff WMO_Satellite_ID ", &
                          &"member. STAT = ", i5 )' ) &
                        Allocate_Status
        CALL Display_Message( ROUTINE_NAME,    &
                              TRIM( Message ), &
                              Error_Status,    &
                              Message_Log = Message_Log )
      END IF
    END IF

    ! -- Deallocate the WMO Sensor ID
    IF ( ASSOCIATED( SpcCoeff%WMO_Sensor_ID ) ) THEN

      DEALLOCATE( SpcCoeff%WMO_Sensor_ID, STAT = Allocate_Status )

      IF ( Allocate_Status /= 0 ) THEN
        Error_Status = FAILURE
        WRITE( Message, '( "Error deallocating SpcCoeff WMO_Sensor_ID ", &
                          &"member. STAT = ", i5 )' ) &
                        Allocate_Status
        CALL Display_Message( ROUTINE_NAME,    &
                              TRIM( Message ), &
                              Error_Status,    &
                              Message_Log = Message_Log )
      END IF
    END IF

    ! -- Deallocate the sensor channel number array
    IF ( ASSOCIATED( SpcCoeff%Sensor_Channel ) ) THEN

      DEALLOCATE( SpcCoeff%Sensor_Channel, STAT = Allocate_Status )

      IF ( Allocate_Status /= 0 ) THEN
        Error_Status = FAILURE
        WRITE( Message, '( "Error deallocating SpcCoeff Sensor_Channel ", &
                          &"member. STAT = ", i5 )' ) &
                        Allocate_Status
        CALL Display_Message( ROUTINE_NAME,    &
                              TRIM( Message ), &
                              Error_Status,    &
                              Message_Log = Message_Log )
      END IF
    END IF

    ! -- Deallocate Frequency
    IF ( ASSOCIATED( SpcCoeff%Frequency ) ) THEN

      DEALLOCATE( SpcCoeff%Frequency, STAT = Allocate_Status )

      IF ( Allocate_Status /= 0 ) THEN
        Error_Status = FAILURE
        WRITE( Message, '( "Error deallocating SpcCoeff Frequency ", &
                          &"member. STAT = ", i5 )' ) &
                        Allocate_Status
        CALL Display_Message( ROUTINE_NAME,    &
                              TRIM( Message ), &
                              Error_Status,    &
                              Message_Log = Message_Log )
      END IF
    END IF

    ! -- Deallocate Wavenumber
    IF ( ASSOCIATED( SpcCoeff%Wavenumber ) ) THEN

      DEALLOCATE( SpcCoeff%Wavenumber, STAT = Allocate_Status )

      IF ( Allocate_Status /= 0 ) THEN
        Error_Status = FAILURE
        WRITE( Message, '( "Error deallocating SpcCoeff Wavenumber ", &
                          &"member. STAT = ", i5 )' ) &
                        Allocate_Status
        CALL Display_Message( ROUTINE_NAME,    &
                              TRIM( Message ), &
                              Error_Status,    &
                              Message_Log = Message_Log )
      END IF
    END IF

    ! -- Deallocate Planck_C1
    IF ( ASSOCIATED( SpcCoeff%Planck_C1 ) ) THEN

      DEALLOCATE( SpcCoeff%Planck_C1, STAT = Allocate_Status )

      IF ( Allocate_Status /= 0 ) THEN
        Error_Status = FAILURE
        WRITE( Message, '( "Error deallocating SpcCoeff Planck_C1 ", &
                          &"member. STAT = ", i5 )' ) &
                        Allocate_Status
        CALL Display_Message( ROUTINE_NAME,    &
                              TRIM( Message ), &
                              Error_Status,    &
                              Message_Log = Message_Log )
      END IF
    END IF

    ! -- Deallocate Planck_C2
    IF ( ASSOCIATED( SpcCoeff%Planck_C2 ) ) THEN

      DEALLOCATE( SpcCoeff%Planck_C2, STAT = Allocate_Status )

      IF ( Allocate_Status /= 0 ) THEN
        Error_Status = FAILURE
        WRITE( Message, '( "Error deallocating SpcCoeff Planck_C2 ", &
                          &"member. STAT = ", i5 )' ) &
                        Allocate_Status
        CALL Display_Message( ROUTINE_NAME,    &
                              TRIM( Message ), &
                              Error_Status,    &
                              Message_Log = Message_Log )
      END IF
    END IF

    ! -- Deallocate Band_C1
    IF ( ASSOCIATED( SpcCoeff%Band_C1 ) ) THEN

      DEALLOCATE( SpcCoeff%Band_C1, STAT = Allocate_Status )

      IF ( Allocate_Status /= 0 ) THEN
        Error_Status = FAILURE
        WRITE( Message, '( "Error deallocating SpcCoeff Band_C1 ", &
                          &"member. STAT = ", i5 )' ) &
                        Allocate_Status
        CALL Display_Message( ROUTINE_NAME,    &
                              TRIM( Message ), &
                              Error_Status,    &
                              Message_Log = Message_Log )
      END IF
    END IF

    ! -- Deallocate Band_C2
    IF ( ASSOCIATED( SpcCoeff%Band_C2 ) ) THEN

      DEALLOCATE( SpcCoeff%Band_C2, STAT = Allocate_Status )

      IF ( Allocate_Status /= 0 ) THEN
        Error_Status = FAILURE
        WRITE( Message, '( "Error deallocating SpcCoeff Band_C2 ", &
                          &"member. STAT = ", i5 )' ) &
                        Allocate_Status
        CALL Display_Message( ROUTINE_NAME,    &
                              TRIM( Message ), &
                              Error_Status,    &
                              Message_Log = Message_Log )
      END IF
    END IF

    ! -- Deallocate Is_Microwave_Channel
    IF ( ASSOCIATED( SpcCoeff%Is_Microwave_Channel ) ) THEN

      DEALLOCATE( SpcCoeff%Is_Microwave_Channel, STAT = Allocate_Status )

      IF ( Allocate_Status /= 0 ) THEN
        Error_Status = FAILURE
        WRITE( Message, '( "Error deallocating SpcCoeff Is_Microwave_Channel ", &
                          &"member. STAT = ", i5 )' ) &
                        Allocate_Status
        CALL Display_Message( ROUTINE_NAME,    &
                              TRIM( Message ), &
                              Error_Status,    &
                              Message_Log = Message_Log )
      END IF
    END IF

    ! -- Deallocate Polarization
    IF ( ASSOCIATED( SpcCoeff%Polarization ) ) THEN

      DEALLOCATE( SpcCoeff%Polarization, STAT = Allocate_Status )

      IF ( Allocate_Status /= 0 ) THEN
        Error_Status = FAILURE
        WRITE( Message, '( "Error deallocating SpcCoeff Polarization ", &
                          &"member. STAT = ", i5 )' ) &
                        Allocate_Status
        CALL Display_Message( ROUTINE_NAME,    &
                              TRIM( Message ), &
                              Error_Status,    &
                              Message_Log = Message_Log )
      END IF
    END IF

    ! -- Deallocate Cosmic_Background_Temperature
    IF ( ASSOCIATED( SpcCoeff%Cosmic_Background_Temperature ) ) THEN

      DEALLOCATE( SpcCoeff%Cosmic_Background_Temperature, STAT = Allocate_Status )

      IF ( Allocate_Status /= 0 ) THEN
        Error_Status = FAILURE
        WRITE( Message, '( "Error deallocating SpcCoeff Cosmic_Background_Temperature ", &
                          &"member. STAT = ", i5 )' ) &
                        Allocate_Status
        CALL Display_Message( ROUTINE_NAME,    &
                              TRIM( Message ), &
                              Error_Status,    &
                              Message_Log = Message_Log )
      END IF
    END IF

    ! -- Deallocate Cosmic_Background_Radiance
    IF ( ASSOCIATED( SpcCoeff%Cosmic_Background_Radiance ) ) THEN

      DEALLOCATE( SpcCoeff%Cosmic_Background_Radiance, STAT = Allocate_Status )

      IF ( Allocate_Status /= 0 ) THEN
        Error_Status = FAILURE
        WRITE( Message, '( "Error deallocating SpcCoeff Cosmic_Background_Radiance ", &
                          &"member. STAT = ", i5 )' ) &
                        Allocate_Status
        CALL Display_Message( ROUTINE_NAME,    &
                              TRIM( Message ), &
                              Error_Status,    &
                              Message_Log = Message_Log )
      END IF
    END IF

    ! -- Deallocate Is_Solar_Channel
    IF ( ASSOCIATED( SpcCoeff%Is_Solar_Channel ) ) THEN

      DEALLOCATE( SpcCoeff%Is_Solar_Channel, STAT = Allocate_Status )

      IF ( Allocate_Status /= 0 ) THEN
        Error_Status = FAILURE
        WRITE( Message, '( "Error deallocating SpcCoeff Is_Solar_Channel ", &
                          &"member. STAT = ", i5 )' ) &
                        Allocate_Status
        CALL Display_Message( ROUTINE_NAME,    &
                              TRIM( Message ), &
                              Error_Status,    &
                              Message_Log = Message_Log )
      END IF
    END IF

    ! -- Deallocate Solar_Irradiance
    IF ( ASSOCIATED( SpcCoeff%Solar_Irradiance ) ) THEN

      DEALLOCATE( SpcCoeff%Solar_Irradiance, STAT = Allocate_Status )

      IF ( Allocate_Status /= 0 ) THEN
        Error_Status = FAILURE
        WRITE( Message, '( "Error deallocating SpcCoeff Solar_Irradiance ", &
                          &"member. STAT = ", i5 )' ) &
                        Allocate_Status
        CALL Display_Message( ROUTINE_NAME,    &
                              TRIM( Message ), &
                              Error_Status,    &
                              Message_Log = Message_Log )
      END IF
    END IF

    ! -- Deallocate Blackbody_Irradiance
    IF ( ASSOCIATED( SpcCoeff%Blackbody_Irradiance ) ) THEN

      DEALLOCATE( SpcCoeff%Blackbody_Irradiance, STAT = Allocate_Status )

      IF ( Allocate_Status /= 0 ) THEN
        Error_Status = FAILURE
        WRITE( Message, '( "Error deallocating SpcCoeff Blackbody_Irradiance ", &
                          &"member. STAT = ", i5 )' ) &
                        Allocate_Status
        CALL Display_Message( ROUTINE_NAME,    &
                              TRIM( Message ), &
                              Error_Status,    &
                              Message_Log = Message_Log )
      END IF
    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 = ", i5 )' ) &
                      SpcCoeff%n_Allocates
      CALL Display_Message( ROUTINE_NAME,    &
                            TRIM( Message ), &
                            Error_Status,    &
                            Message_Log = Message_Log )
    END IF

  END FUNCTION Destroy_SpcCoeff

!--------------------------------------------------------------------------------
!S+
! NAME:
!       Allocate_SpcCoeff
! 
! PURPOSE:
!       Function to allocate the pointer members of the SpcCoeff
!       data structure.
!
! CATEGORY:
!       Instrument Information : SpcCoeff
!
! LANGUAGE:
!       Fortran-95
!
! CALLING SEQUENCE:
!       Error_Status = Allocate_SpcCoeff( n_Channels,               &  ! Input
!                                         SpcCoeff,                 &  ! Output
!                                         RCS_Id = RCS_Id,          &  ! Revision control
!                                         Message_Log = Message_Log )  ! Error messaging
!
! INPUT ARGUMENTS:
!       n_Channels:   Required dimension of SpcCoeff structure pointer
!                     members.
!                     Must be > 0.
!                     UNITS:      N/A
!                     TYPE:       INTEGER
!                     DIMENSION:  Scalar
!                     ATTRIBUTES: INTENT( IN )
!
! 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:      None
!                     TYPE:       CHARACTER(*)
!                     DIMENSION:  Scalar
!                     ATTRIBUTES: INTENT( IN ), OPTIONAL
!
! OUTPUT ARGUMENTS:
!       SpcCoeff:     SpcCoeff structure with allocated pointer members
!                     UNITS:      N/A
!                     TYPE:       SpcCoeff_type
!                     DIMENSION:  Scalar
!                     ATTRIBUTES: INTENT( IN OUT )
!
!
! OPTIONAL OUTPUT ARGUMENTS:
!       RCS_Id:       Character string containing the Revision Control
!                     System Id field for the module.
!                     UNITS:      None
!                     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 ERROR_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
!                                     decremented for every structure allocation
!                                     and deallocation respectively.
!                     UNITS:      N/A
!                     TYPE:       INTEGER
!                     DIMENSION:  Scalar
!
! CALLS:
!       Associated_SpcCoeff:  Function to test the association status of the
!                             pointer members of a SpcCoeff structure.
!
!       Destroy_SpcCoeff:     Function to re-initialize the scalar and pointer
!                             members of SpcCoeff data structures.
!
!       Display_Message:      Subroutine to output messages
!                             SOURCE: ERROR_HANDLER module
!
! SIDE EFFECTS:
!       None.
!
! RESTRICTIONS:
!       None.
!
! 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.
!
! CREATION HISTORY:
!       Written by:     Paul van Delst, CIMSS/SSEC 18-Mar-2002
!                       paul.vandelst@ssec.wisc.edu
!S-
!--------------------------------------------------------------------------------

  FUNCTION Allocate_SpcCoeff( n_Channels,   &  ! Input
                              SpcCoeff,     &  ! Output
                              RCS_Id,       &  ! Revision control
                              Message_Log ) &  ! Error messaging
                            RESULT( Error_Status )

    !#--------------------------------------------------------------------------#
    !#                        -- TYPE DECLARATIONS --                           #
    !#--------------------------------------------------------------------------#

    ! ---------
    ! Arguments
    ! ---------

    ! -- Input
    INTEGER,                  INTENT( IN )     :: n_Channels

    ! -- Output
    TYPE( SpcCoeff_type ),    INTENT( IN OUT ) :: SpcCoeff

    ! -- Revision control
    CHARACTER( * ), OPTIONAL, INTENT( OUT )    :: RCS_Id

    ! - Error messaging
    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

    !#--------------------------------------------------------------------------#
    !#                    -- SET SUCCESSFUL RETURN STATUS --                    #
    !#--------------------------------------------------------------------------#

    Error_Status = SUCCESS

    !#--------------------------------------------------------------------------#
    !#                -- SET THE RCS ID ARGUMENT IF SUPPLIED --                 #
    !#--------------------------------------------------------------------------#

    IF ( PRESENT( RCS_Id ) ) THEN
      RCS_Id = ' '
      RCS_Id = MODULE_RCS_ID
    END IF

    !#--------------------------------------------------------------------------#
    !#                            -- CHECK INPUT --                             #
    !#--------------------------------------------------------------------------#

    ! ------------------
    ! Spectral dimension
    ! ------------------

    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

    ! -----------------------------------------------
    ! 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

    !#--------------------------------------------------------------------------#
    !#                       -- PERFORM THE ALLOCATION --                       #
    !#--------------------------------------------------------------------------#

    ALLOCATE( SpcCoeff%Sensor_Descriptor( n_Channels ),                 &
              SpcCoeff%NCEP_Sensor_ID( n_Channels ),                    &
              SpcCoeff%WMO_Satellite_ID ( n_Channels ),                 &
              SpcCoeff%WMO_Sensor_ID( n_Channels ),                     &
              SpcCoeff%Sensor_Channel( 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%Is_Microwave_Channel( n_Channels ),              &
              SpcCoeff%Polarization( N_STOKES_PARAMETERS, n_Channels ), &
              SpcCoeff%Cosmic_Background_Temperature( n_Channels ),     &
              SpcCoeff%Cosmic_Background_Radiance( n_Channels ),        &
              SpcCoeff%Is_Solar_Channel( n_Channels ),                  &
              SpcCoeff%Solar_Irradiance( n_Channels ),                  &
              SpcCoeff%Blackbody_Irradiance( n_Channels ),              &
              STAT = Allocate_Status                                    )

    IF ( Allocate_Status /= 0 ) THEN
      Error_Status = FAILURE
      WRITE( Message, '( "Error allocating SpcCoeff data arrays. STAT = ", i5 )' ) &
                      Allocate_Status
      CALL Display_Message( ROUTINE_NAME,    &
                            TRIM( Message ), &
                            Error_Status,    &
                            Message_Log = Message_Log )
      RETURN
    END IF

    !#--------------------------------------------------------------------------#
    !#                      -- ASSIGN THE DIMENSIONS --                         #
    !#--------------------------------------------------------------------------#

    SpcCoeff%n_Stokes   = N_STOKES_PARAMETERS
    SpcCoeff%n_Channels = n_Channels

    !#--------------------------------------------------------------------------#
    !#                -- 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

!--------------------------------------------------------------------------------
!S+
! NAME:
!       Assign_SpcCoeff
!
! PURPOSE:
!       Function to copy valid SpcCoeff structures.
!
! CATEGORY:
!       Instrument Information : SpcCoeff
!
! LANGUAGE:
!       Fortran-95
!
! 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 )
!
! 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:      None
!                      TYPE:       CHARACTER(*)
!                      DIMENSION:  Scalar
!                      ATTRIBUTES: INTENT( IN ), OPTIONAL
!
! OUTPUT ARGUMENTS:
!       SpcCoeff_out:  Copy of the input structure, SpcCoeff_in.
!                      UNITS:      N/A
!                      TYPE:       SpcCoeff_type
!                      DIMENSION:  Scalar
!                      ATTRIBUTES: INTENT( IN OUT )
!
!
! OPTIONAL OUTPUT ARGUMENTS:
!       RCS_Id:        Character string containing the Revision Control
!                      System Id field for the module.
!                      UNITS:      None
!                      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 ERROR_HANDLER module.
!                     If == SUCCESS the structure assignment was successful
!                        == FAILURE an error occurred
!                     UNITS:      N/A
!                     TYPE:       INTEGER
!                     DIMENSION:  Scalar
!
! CALLS:
!       Associated_SpcCoeff:  Function to test the association status of the
!                             pointer members of a SpcCoeff structure.
!
!       Allocate_SpcCoeff:    Function to allocate the pointer members of
!                             the SpcCoeff data structure.
!
!       Display_Message:      Subroutine to output messages
!                             SOURCE: ERROR_HANDLER module
!
! SIDE EFFECTS:
!       None.
!
! RESTRICTIONS:
!       None.
!
! 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.
!
! CREATION HISTORY:
!       Written by:     Paul van Delst, CIMSS/SSEC 18-Mar-2002
!                       paul.vandelst@ssec.wisc.edu
!S-
!--------------------------------------------------------------------------------

  FUNCTION Assign_SpcCoeff( SpcCoeff_in,  &  ! Input
                            SpcCoeff_out, &  ! Output
                            RCS_Id,       &  ! Revision control
                            Message_Log ) &  ! Error messaging
                          RESULT( Error_Status )

    !#--------------------------------------------------------------------------#
    !#                        -- TYPE DECLARATIONS --                           #
    !#--------------------------------------------------------------------------#

    ! ---------
    ! Arguments
    ! ---------

    ! -- Input
    TYPE( SpcCoeff_type ),    INTENT( IN )     :: SpcCoeff_in

    ! -- Output
    TYPE( SpcCoeff_type ),    INTENT( IN OUT ) :: SpcCoeff_out

    ! -- Revision control
    CHARACTER( * ), OPTIONAL, INTENT( OUT )    :: RCS_Id

    ! - Error messaging
    CHARACTER( * ), OPTIONAL, INTENT( IN )     :: Message_Log

    ! ---------------
    ! Function result
    ! ---------------

    INTEGER :: Error_Status

    ! ----------------
    ! Local parameters
    ! ----------------

    CHARACTER( * ), PARAMETER :: ROUTINE_NAME = 'Assign_SpcCoeff'

    !#--------------------------------------------------------------------------#
    !#                -- SET THE RCS ID ARGUMENT IF SUPPLIED --                 #
    !#--------------------------------------------------------------------------#

    IF ( PRESENT( RCS_Id ) ) THEN
      RCS_Id = ' '
      RCS_Id = MODULE_RCS_ID
    END IF

    !#--------------------------------------------------------------------------#
    !#           -- TEST THE STRUCTURE ARGUMENT POINTER ASSOCIATION --          #
    !#--------------------------------------------------------------------------#

    ! ---------------------------------------
    ! ALL *input* pointers must be associated
    ! ---------------------------------------

    IF ( .NOT. Associated_SpcCoeff( SpcCoeff_In ) ) THEN

      Error_Status = FAILURE
      CALL Display_Message( ROUTINE_NAME,    &
                            'Some or all INPUT SpcCoeff pointer '//&
                            'members are NOT associated.', &
                            Error_Status,    &
                            Message_Log = Message_Log )
      RETURN
    END IF

    !#--------------------------------------------------------------------------#
    !#                       -- PERFORM THE ASSIGNMENT --                       #
    !#--------------------------------------------------------------------------#

    ! ----------------------
    ! Allocate the structure
    ! ----------------------

    Error_Status = Allocate_SpcCoeff( SpcCoeff_in%n_Channels,  &
                                      SpcCoeff_out,            &
                                      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 non-dimension scalar members
    ! -----------------------------------

    SpcCoeff_out%Release = SpcCoeff_in%Release
    SpcCoeff_out%Version = SpcCoeff_in%Version

    SpcCoeff_out%n_Sensors = SpcCoeff_in%n_Sensors

    ! -----------------
    ! Assign array data
    ! -----------------

    SpcCoeff_out%Sensor_Descriptor             = SpcCoeff_in%Sensor_Descriptor
    SpcCoeff_out%NCEP_Sensor_ID                = SpcCoeff_in%NCEP_Sensor_ID
    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%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%Is_Microwave_Channel          = SpcCoeff_in%Is_Microwave_Channel
    SpcCoeff_out%Polarization                  = SpcCoeff_in%Polarization
    SpcCoeff_out%Cosmic_Background_Temperature = SpcCoeff_in%Cosmic_Background_Temperature
    SpcCoeff_out%Cosmic_Background_Radiance    = SpcCoeff_in%Cosmic_Background_Radiance
    SpcCoeff_out%Is_Solar_Channel              = SpcCoeff_in%Is_Solar_Channel
    SpcCoeff_out%Solar_Irradiance              = SpcCoeff_in%Solar_Irradiance
    SpcCoeff_out%Blackbody_Irradiance          = SpcCoeff_in%Blackbody_Irradiance

  END FUNCTION Assign_SpcCoeff

!--------------------------------------------------------------------------------
!S+
! NAME:
!       Concatenate_SpcCoeff
!
! PURPOSE:
!       Function to concatenate two valid SpcCoeff structures along
!       the channel dimension.
!
! CATEGORY:
!       Instrument Information : SpcCoeff
!
! LANGUAGE:
!       Fortran-95
!
! CALLING SEQUENCE:
!       Error_Status = Concatenate_SpcCoeff( SpcCoeff1,                &  ! Input/Output
!                                            SpcCoeff2,                &  ! Input
!                                            RCS_Id = RCS_Id,          &  ! Revision control
!                                            Message_Log = Message_Log )  ! Error messaging
!
! INPUT ARGUMENTS:
!       SpcCoeff1:     First SpcCoeff structure to concatenate.
!                      UNITS:      N/A
!                      TYPE:       SpcCoeff_type
!                      DIMENSION:  Scalar
!                      ATTRIBUTES: INTENT( IN OUT )
!
!       SpcCoeff2:     Second SpcCoeff structure to concatenate.
!                      UNITS:      N/A
!                      TYPE:       SpcCoeff_type
!                      DIMENSION:  Scalar
!                      ATTRIBUTES: INTENT( IN )
!
! 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:      None
!                      TYPE:       CHARACTER(*)
!                      DIMENSION:  Scalar
!                      ATTRIBUTES: INTENT( IN ), OPTIONAL
!
! OUTPUT ARGUMENTS:
!       SpcCoeff1:     The concatenated SpcCoeff structure. The order of
!                      concatenation is SpcCoef1,SpcCoeff2.
!                      UNITS:      N/A
!                      TYPE:       SpcCoeff_type
!                      DIMENSION:  Scalar
!                      ATTRIBUTES: INTENT( IN OUT )
!
! OPTIONAL OUTPUT ARGUMENTS:
!       RCS_Id:        Character string containing the Revision Control
!                      System Id field for the module.
!                      UNITS:      None
!                      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 ERROR_HANDLER module.
!                      If == SUCCESS the structure concatenation was successful
!                         == FAILURE an error occurred, or
!                         == WARNING - the version numbers of the SpcCoeff structure
!                                      data are different.
!                                    - the destruction of a temporary, local SpcCoeff
!                                      structure failed.
!                      UNITS:      N/A
!                      TYPE:       INTEGER
!                      DIMENSION:  Scalar
!
! CALLS:
!       Associated_SpcCoeff:     Function to test the association status of the
!                                pointer members of a SpcCoeff structure.
!
!       Assign_SpcCoeff:         Function to copy valid SpcCoeff data structures.
!
!       Destroy_SpcCoeff:        Function to re-initialize the scalar and pointer
!                                members of SpcCoeff data structures.
!
!       Allocate_SpcCoeff:       Function to allocate the pointer members of
!                                the SpcCoeff data structure.
!
!       Count_SpcCoeff_Sensors:  Subroutine to count the number of different
!                                satellite/sensors in the SpcCoeff structure
!                                and set the n_Sensors field.
!
!       Display_Message:         Subroutine to output messages
!                                SOURCE: ERROR_HANDLER module
!
! SIDE EFFECTS:
!       The input SpcCoeff1 argument contains the concatenated structure
!       data (in character-speak: SpcCoeff1//SpcCoeff2) on output. It is
!       reallocated within this routine so if an error occurs during the
!       reallocation, the contents of the input SpcCoeff1 structure will
!       be lost.
!
!       Because of the structure reallocation there is a potential that 
!       available memory will become fragmented. Use this routine in a
!       manner that will minimise this effect (e.g. destroying structures or
!       allocatable arrays in the opposite order in which they were created). 
!
! RESTRICTIONS:
!       None.
!
! CREATION HISTORY:
!       Written by:     Paul van Delst, CIMSS/SSEC 06-Feb-2003
!                       paul.vandelst@ssec.wisc.edu
!S-
!--------------------------------------------------------------------------------

  FUNCTION Concatenate_SpcCoeff( SpcCoeff1,     &  ! Input/Output
                                 SpcCoeff2,     &  ! Input
                                 RCS_Id,        &  ! Revision control
                                 Message_Log )  &  ! Error messaging
                               RESULT( Error_Status )

    !#--------------------------------------------------------------------------#
    !#                        -- TYPE DECLARATIONS --                           #
    !#--------------------------------------------------------------------------#

    ! ---------
    ! Arguments
    ! ---------

    ! -- Input/Output
    TYPE( SpcCoeff_type ),    INTENT( IN OUT )  :: SpcCoeff1
    TYPE( SpcCoeff_type ),    INTENT( IN )      :: SpcCoeff2

    ! -- Revision control
    CHARACTER( * ), OPTIONAL, INTENT( OUT )     :: RCS_Id

    ! - Error messaging
    CHARACTER( * ), OPTIONAL, INTENT( IN )      :: Message_Log

    ! ---------------
    ! Function result
    ! ---------------

    INTEGER :: Error_Status

    ! ----------------
    ! Local parameters
    ! ----------------

    CHARACTER( * ), PARAMETER :: ROUTINE_NAME = 'Concatenate_SpcCoeff'

    ! ---------------
    ! Local variables
    ! ---------------

    INTEGER :: n_Channels, l1, l2

    TYPE( SpcCoeff_type ) :: SpcCoeff_Tmp

    !#--------------------------------------------------------------------------#
    !#                -- SET THE RCS ID ARGUMENT IF SUPPLIED --                 #
    !#--------------------------------------------------------------------------#

    IF ( PRESENT( RCS_Id ) ) THEN
      RCS_Id = ' '
      RCS_Id = MODULE_RCS_ID
    END IF

    !#--------------------------------------------------------------------------#
    !#             -- CHECK STRUCTURE POINTER ASSOCIATION STATUS --             #
    !#--------------------------------------------------------------------------#

    ! -------------------
    ! The first structure
    ! -------------------

    IF ( .NOT. Associated_SpcCoeff( SpcCoeff1 ) ) THEN
      Error_Status = FAILURE
      CALL Display_Message( ROUTINE_NAME,    &
                            'Some or all INPUT SpcCoeff1 pointer '//&
                            'members are NOT associated.', &
                            Error_Status,    &
                            Message_Log = Message_Log )
      RETURN
    END IF

    ! --------------------
    ! The second structure
    ! --------------------

    IF ( .NOT. Associated_SpcCoeff( SpcCoeff2 ) ) THEN
      Error_Status = FAILURE
      CALL Display_Message( ROUTINE_NAME,    &
                            'Some or all INPUT SpcCoeff2 pointer '//&
                            'members are NOT associated.', &
                            Error_Status,    &
                            Message_Log = Message_Log )
      RETURN
    END IF

    !#--------------------------------------------------------------------------#
    !#           -- COMPARE THE INPUT SpcCoeff RELEASE AND VERSION --           #
    !#--------------------------------------------------------------------------#

    ! -------
    ! Release
    ! -------

    IF ( SpcCoeff1%Release /= SpcCoeff2%Release ) THEN
      Error_Status = FAILURE
      CALL Display_Message( ROUTINE_NAME, &
                            'Input SpcCoeff Release values are different.', &
                            Error_Status, &
                            Message_Log = Message_Log )
      RETURN
    END IF

    ! -------
    ! Version
    ! -------

    IF ( SpcCoeff1%Version /= SpcCoeff2%Version ) THEN
      CALL Display_Message( ROUTINE_NAME, &
                            'Input SpcCoeff Version values are different.', &
                            WARNING, &
                            Message_Log = Message_Log )
    END IF

    !#--------------------------------------------------------------------------#
    !#                 -- COPY FIRST INPUT SpcCoeff STRUCTURE --                #
    !#--------------------------------------------------------------------------#

    Error_Status = Assign_SpcCoeff( SpcCoeff1, SpcCoeff_Tmp, &
                                    Message_Log = Message_Log )

    IF ( Error_Status /= SUCCESS ) THEN
      CALL Display_Message( ROUTINE_NAME, &
                            'Error copying SpcCoeff1 structure.', &
                            Error_Status, &
                            Message_Log = Message_Log )
      RETURN
    END IF
   

    !#--------------------------------------------------------------------------#
    !#             -- REALLOCATE FIRST INPUT SpcCoeff STRUCTURE --              #
    !#--------------------------------------------------------------------------#

    ! ----------
    ! Destroy it
    ! ----------

    Error_Status = Destroy_SpcCoeff( SpcCoeff1, &
                                     Message_Log = Message_Log )

    IF ( Error_Status /= SUCCESS ) THEN
      CALL Display_Message( ROUTINE_NAME, &
                            'Error destroying SpcCoeff1 structure.', &
                            Error_Status, &
                            Message_Log = Message_Log )
      RETURN
    END IF

    ! --------------
    ! Re-Allocate it
    ! --------------

    ! -- Set the total number of channels
    n_Channels = SpcCoeff_Tmp%n_Channels + SpcCoeff2%n_Channels

    ! -- Perform the allocation
    Error_Status = Allocate_SpcCoeff( n_Channels, &
                                      SpcCoeff1, &
                                      Message_Log = Message_Log )

    IF ( Error_Status /= SUCCESS ) THEN
      CALL Display_Message( ROUTINE_NAME, &
                            'Error reallocating SpcCoeff1 structure.', &
                            Error_Status, &
                            Message_Log = Message_Log )
      RETURN
    END IF

    !#--------------------------------------------------------------------------#
    !#                       -- PERFORM THE CONCATENATION --                    #
    !#--------------------------------------------------------------------------#

    SpcCoeff1%Version = MAX( SpcCoeff_Tmp%Version, SpcCoeff2%Version )

    ! ----------------------
    ! Concatenate array data
    ! ----------------------

    ! -- The first part
    l1 = 1
    l2 = SpcCoeff_Tmp%n_Channels

    SpcCoeff1%Sensor_Descriptor(l1:l2)             = SpcCoeff_Tmp%Sensor_Descriptor
    SpcCoeff1%NCEP_Sensor_ID(l1:l2)                = SpcCoeff_Tmp%NCEP_Sensor_ID
    SpcCoeff1%WMO_Satellite_ID(l1:l2)              = SpcCoeff_Tmp%WMO_Satellite_ID
    SpcCoeff1%WMO_Sensor_ID(l1:l2)                 = SpcCoeff_Tmp%WMO_Sensor_ID
    SpcCoeff1%Sensor_Channel(l1:l2)                = SpcCoeff_Tmp%Sensor_Channel
    SpcCoeff1%Frequency(l1:l2)                     = SpcCoeff_Tmp%Frequency
    SpcCoeff1%Wavenumber(l1:l2)                    = SpcCoeff_Tmp%Wavenumber
    SpcCoeff1%Planck_C1(l1:l2)                     = SpcCoeff_Tmp%Planck_C1
    SpcCoeff1%Planck_C2(l1:l2)                     = SpcCoeff_Tmp%Planck_C2
    SpcCoeff1%Band_C1(l1:l2)                       = SpcCoeff_Tmp%Band_C1
    SpcCoeff1%Band_C2(l1:l2)                       = SpcCoeff_Tmp%Band_C2
    SpcCoeff1%Is_Microwave_Channel(l1:l2)          = SpcCoeff_Tmp%Is_Microwave_Channel
    SpcCoeff1%Polarization(:,l1:l2)                = SpcCoeff_Tmp%Polarization
    SpcCoeff1%Cosmic_Background_Temperature(l1:l2) = SpcCoeff_Tmp%Cosmic_Background_Temperature
    SpcCoeff1%Cosmic_Background_Radiance(l1:l2)    = SpcCoeff_Tmp%Cosmic_Background_Radiance
    SpcCoeff1%Is_Solar_Channel(l1:l2)              = SpcCoeff_Tmp%Is_Solar_Channel
    SpcCoeff1%Solar_Irradiance(l1:l2)              = SpcCoeff_Tmp%Solar_Irradiance
    SpcCoeff1%Blackbody_Irradiance(l1:l2)          = SpcCoeff_Tmp%Blackbody_Irradiance

    ! -- The second part
    l1 = l2 + 1
    l2 = n_Channels

    SpcCoeff1%Sensor_Descriptor(l1:l2)             = SpcCoeff2%Sensor_Descriptor
    SpcCoeff1%NCEP_Sensor_ID(l1:l2)                = SpcCoeff2%NCEP_Sensor_ID
    SpcCoeff1%WMO_Satellite_ID(l1:l2)              = SpcCoeff2%WMO_Satellite_ID
    SpcCoeff1%WMO_Sensor_ID(l1:l2)                 = SpcCoeff2%WMO_Sensor_ID
    SpcCoeff1%Sensor_Channel(l1:l2)                = SpcCoeff2%Sensor_Channel
    SpcCoeff1%Frequency(l1:l2)                     = SpcCoeff2%Frequency
    SpcCoeff1%Wavenumber(l1:l2)                    = SpcCoeff2%Wavenumber
    SpcCoeff1%Planck_C1(l1:l2)                     = SpcCoeff2%Planck_C1
    SpcCoeff1%Planck_C2(l1:l2)                     = SpcCoeff2%Planck_C2
    SpcCoeff1%Band_C1(l1:l2)                       = SpcCoeff2%Band_C1
    SpcCoeff1%Band_C2(l1:l2)                       = SpcCoeff2%Band_C2
    SpcCoeff1%Is_Microwave_Channel(l1:l2)          = SpcCoeff2%Is_Microwave_Channel
    SpcCoeff1%Polarization(:,l1:l2)                = SpcCoeff2%Polarization
    SpcCoeff1%Cosmic_Background_Temperature(l1:l2) = SpcCoeff2%Cosmic_Background_Temperature
    SpcCoeff1%Cosmic_Background_Radiance(l1:l2)    = SpcCoeff2%Cosmic_Background_Radiance
    SpcCoeff1%Is_Solar_Channel(l1:l2)              = SpcCoeff2%Is_Solar_Channel
    SpcCoeff1%Solar_Irradiance(l1:l2)              = SpcCoeff2%Solar_Irradiance
    SpcCoeff1%Blackbody_Irradiance(l1:l2)          = SpcCoeff2%Blackbody_Irradiance

    !#--------------------------------------------------------------------------#
    !#                    -- COUNT THE NUMBER OF SENSORS --                     #
    !#--------------------------------------------------------------------------#

    CALL Count_SpcCoeff_Sensors( SpcCoeff1, Use_WMO_Id = SET )

    !#--------------------------------------------------------------------------#
    !#             -- DEALLOCATE THE TEMPORARY SpcCoeff STRUCTURE --            #
    !#--------------------------------------------------------------------------#

    Error_Status = Destroy_SpcCoeff( SpcCoeff_Tmp, &
                                     Message_Log = Message_Log )

    IF ( Error_Status /= SUCCESS ) THEN
      Error_Status = WARNING
      CALL Display_Message( ROUTINE_NAME, &
                            'Error destroying SpcCoeff_Tmp structure.', &
                            Error_Status, &
                            Message_Log = Message_Log )
    END IF

  END FUNCTION Concatenate_SpcCoeff

!--------------------------------------------------------------------------------
!S+
! NAME:
!       Equal_SpcCoeff
!
! PURPOSE:
!       Function to test if two SpcCoeff structures are equal.
!
! CATEGORY:
!       Instrument Information : SpcCoeff
!
! LANGUAGE:
!       Fortran-95
!
! 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:       SpcCoeff_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: 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:      None
!                      TYPE:       CHARACTER(*)
!                      DIMENSION:  Scalar
!                      ATTRIBUTES: INTENT( IN ), OPTIONAL
!
! OUTPUT ARGUMENTS:
!       None.
!
! OPTIONAL OUTPUT ARGUMENTS:
!       RCS_Id:        Character string containing the Revision Control
!                      System Id field for the module.
!                      UNITS:      None
!                      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 ERROR_HANDLER module.
!                      If == SUCCESS the structures were equal
!                         == FAILURE - an error occurred, or
!                                    - the structures were different.
!                      UNITS:      N/A
!                      TYPE:       INTEGER
!                      DIMENSION:  Scalar
!
! CALLS:
!       Compare_Float:        Function to compare floating point scalars and
!                             arrays with adjustible precision tolerance.
!                             SOURCE: COMPARE_FLOAT_NUMBERS module
!
!       Display_Message:      Subroutine to output messages
!                             SOURCE: ERROR_HANDLER module
!
! CONTAINS:
!       Construct_Message:    Internal subprogram to construct a standard message
!                             when a floating point number comparison fails.
!
! SIDE EFFECTS:
!       None.
!
! RESTRICTIONS:
!       None.
!
! CREATION HISTORY:
!       Written by:     Paul van Delst, CIMSS/SSEC 18-Mar-2002
!                       paul.vandelst@ssec.wisc.edu
!S-
!--------------------------------------------------------------------------------

  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 )

    !#--------------------------------------------------------------------------#
    !#                        -- TYPE DECLARATIONS --                           #
    !#--------------------------------------------------------------------------#

    ! ---------
    ! Arguments
    ! ---------

    ! -- Input
    TYPE( SpcCoeff_type ),    INTENT( IN )  :: SpcCoeff_LHS
    TYPE( SpcCoeff_type ),    INTENT( IN )  :: SpcCoeff_RHS

    ! -- Optional input
    INTEGER,        OPTIONAL, INTENT( IN )  :: ULP_Scale
    INTEGER,        OPTIONAL, INTENT( IN )  :: Check_All

    ! -- Revision control
    CHARACTER( * ), OPTIONAL, INTENT( OUT ) :: RCS_Id

    ! - Error messaging
    CHARACTER( * ), OPTIONAL, INTENT( IN )  :: Message_Log

    ! ---------------
    ! Function result
    ! ---------------

    INTEGER :: Error_Status

    ! ----------------
    ! Local parameters
    ! ----------------

    CHARACTER( * ), PARAMETER :: ROUTINE_NAME = 'Equal_SpcCoeff'
    CHARACTER( * ), PARAMETER :: INT_FORMAT = 'i4'

    ! ---------------
    ! Local variables
    ! ---------------

    CHARACTER( 256 ) :: Message
    CHARACTER( 256 ) :: Format_String
    INTEGER :: ULP
    LOGICAL :: Check_Once
    INTEGER :: l

    !#--------------------------------------------------------------------------#
    !#                -- SET THE RCS ID ARGUMENT IF SUPPLIED --                 #
    !#--------------------------------------------------------------------------#

    IF ( PRESENT( RCS_Id ) ) THEN
      RCS_Id = ' '
      RCS_Id = MODULE_RCS_ID
    END IF

    !#--------------------------------------------------------------------------#
    !#                  -- DEFINE A SUCCESSFUL EXIT STATUS --                   #
    !#--------------------------------------------------------------------------#

    Error_Status = SUCCESS

    !#--------------------------------------------------------------------------#
    !#                   -- CHECK THE OPTIONAL ARGUMENTS --                     #
    !#--------------------------------------------------------------------------#

    ! ---------------------------
    ! Test the ULP_Scale argument
    ! ---------------------------

    ! -- 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

    ! ---------------------------
    ! Test the Check_All argument
    ! ---------------------------

    ! -- 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 STRUCTURE POINTER ASSOCIATION STATUS --             #
    !#                                                                          #
    !#                ALL structure pointers must be associated                 #
    !#--------------------------------------------------------------------------#

    ! -----------------
    ! The LHS structure
    ! -----------------

    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

    ! -----------------
    ! The RHS structure
    ! -----------------

    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 SCALAR MEMBERS --                        #
    !#--------------------------------------------------------------------------#

    ! --------------------
    ! 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 )
      RETURN
    END IF

    ! -----------------
    ! Channel dimension
    ! -----------------

    IF ( SpcCoeff_LHS%n_Channels /= SpcCoeff_RHS%n_Channels ) THEN
      Error_Status = FAILURE
      WRITE( Message, '( "n_Channels dimensions are different : ", &
                        &i4, " vs. ", i4 )' ) &
                      SpcCoeff_LHS%n_Channels, SpcCoeff_RHS%n_Channels
      CALL Display_Message( ROUTINE_NAME, &
                            TRIM( Message ), &
                            Error_Status, &
                            Message_Log = Message_Log )
      RETURN
    END IF

    ! ---------------
    ! n_Sensors value
    ! ---------------

    IF ( SpcCoeff_LHS%n_Sensors /= SpcCoeff_RHS%n_Sensors ) THEN
      Error_Status = FAILURE
      WRITE( Message, '( "n_Sensors values are different : ", &
                        &i4, " vs. ", i4 )' ) &
                      SpcCoeff_LHS%n_Sensors, SpcCoeff_RHS%n_Sensors
      CALL Display_Message( ROUTINE_NAME, &
                            TRIM( Message ), &
                            Error_Status, &
                            Message_Log = Message_Log )
      RETURN
    END IF

    !#--------------------------------------------------------------------------#
    !#                  -- CHECK POINTER MEMBERS BY CHANNEL --                  #
    !#                                                                          #
    !# Each structure member is tested separately. It's a bit of a brain dead   #
    !# way to do it, but easiest to implement since the data types differ.      #
    !# Also, each channel is tested explicitly, rather than using the ANY       #
    !# or ALL intrinsic functions, since I wanted to highlight the actual       #
    !# channel index where any difference occured so it would be very easy to   #
    !# track down the location of the difference.                               #
    !#--------------------------------------------------------------------------#

    l_Channel_loop: DO l = 1, SpcCoeff_RHS%n_Channels

      ! ---------------------
      ! The Sensor Descriptor
      ! ---------------------

      IF ( SpcCoeff_LHS%Sensor_Descriptor(l) /= SpcCoeff_RHS%Sensor_Descriptor(l) ) THEN
        Error_Status = FAILURE
        WRITE( Message, '( "Descriptor values are different, ", &
                          &a, " vs. ", a, ",  for channel index # ", i4 )' ) &
                        TRIM( SpcCoeff_LHS%Sensor_Descriptor(l) ), &
                        TRIM( SpcCoeff_RHS%Sensor_Descriptor(l) ), &
                        l
        CALL Display_Message( ROUTINE_NAME, &
                              TRIM( Message ), &
                              Error_Status, &
                             Message_Log = Message_Log )
        RETURN
      END IF

      ! ------------------
      ! The NCEP sensor ID
      ! ------------------

      IF ( SpcCoeff_LHS%NCEP_Sensor_ID(l) /= SpcCoeff_RHS%NCEP_Sensor_ID(l) ) THEN
        Error_Status = FAILURE
        Format_String = '( "NCEP_Sensor_ID values are different, ", '//INT_FORMAT//&
                        ', " vs. ", '//INT_FORMAT//', ",  for channel index # ", i4 )'
        WRITE( Message, FMT = TRIM( Format_String ) ) &
                        SpcCoeff_LHS%NCEP_Sensor_ID(l), &
                        SpcCoeff_RHS%NCEP_Sensor_ID(l), &
                        l
        CALL Display_Message( ROUTINE_NAME, &
                              TRIM( Message ), &
                              Error_Status, &
                             Message_Log = Message_Log )
        RETURN
      END IF

      ! --------------------
      ! The WMO Satellite ID
      ! --------------------

      IF ( SpcCoeff_LHS%WMO_Satellite_ID(l) /= SpcCoeff_RHS%WMO_Satellite_ID(l) ) THEN
        Error_Status = FAILURE
        Format_String = '( "WMO_Satellite_ID values are different, ", '//INT_FORMAT//&
                        ', " vs. ", '//INT_FORMAT//', ",  for channel index # ", i4 )'
        WRITE( Message, FMT = TRIM( Format_String ) ) &
                        SpcCoeff_LHS%WMO_Satellite_ID(l), &
                        SpcCoeff_RHS%WMO_Satellite_ID(l), &
                        l
        CALL Display_Message( ROUTINE_NAME, &
                              TRIM( Message ), &
                              Error_Status, &
                             Message_Log = Message_Log )
        RETURN
      END IF

      ! -----------------
      ! The WMO Sensor ID
      ! -----------------

      IF ( SpcCoeff_LHS%WMO_Sensor_ID(l) /= SpcCoeff_RHS%WMO_Sensor_ID(l) ) THEN
        Error_Status = FAILURE
        Format_String = '( "WMO_Sensor_ID values are different, ", '//INT_FORMAT//&
                        ', " vs. ", '//INT_FORMAT//', ",  for channel index # ", i4 )'
        WRITE( Message, FMT = TRIM( Format_String ) ) &
                        SpcCoeff_LHS%WMO_Sensor_ID(l), &
                        SpcCoeff_RHS%WMO_Sensor_ID(l), &
                        l
        CALL Display_Message( ROUTINE_NAME, &
                              TRIM( Message ), &
                              Error_Status, &
                             Message_Log = Message_Log )
        RETURN
      END IF

      ! --------------------------
      ! The sensor channel numbers
      ! --------------------------

      IF ( SpcCoeff_LHS%Sensor_Channel(l) /= SpcCoeff_RHS%Sensor_Channel(l) ) THEN
        Error_Status = FAILURE
        Format_String = '( "Sensor_Channel values are different, ", '//INT_FORMAT//&
                        ', " vs. ", '//INT_FORMAT//', ",  for channel index # ", i4 )'
        WRITE( Message, FMT = TRIM( Format_String ) ) &
                        SpcCoeff_LHS%Sensor_Channel(l), &
                        SpcCoeff_RHS%Sensor_Channel(l), &
                        l
        CALL Display_Message( ROUTINE_NAME, &
                              TRIM( Message ), &
                              Error_Status, &
                             Message_Log = Message_Log )
        RETURN
      END IF

      ! -----------------------------
      ! The channel central frequency
      ! -----------------------------

      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

      ! ------------------------------
      ! The channel central wavenumber
      ! ------------------------------

      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

      ! ----------------------------------
      ! The first Planck function constant
      ! ----------------------------------

      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

      ! -----------------------------------
      ! The second Planck function constant
      ! -----------------------------------

      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

      ! --------------------------
      ! The band correction offset
      ! --------------------------

      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

      ! -------------------------
      ! The band correction slope
      ! -------------------------

      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

      ! ---------------------------
      ! The microwave channel flags
      ! ---------------------------

      IF ( SpcCoeff_LHS%Is_Microwave_Channel(l) /= SpcCoeff_RHS%Is_Microwave_Channel(l) ) THEN
        Error_Status = FAILURE
        Format_String = '( "Is_Microwave_Channel values are different, ", '//INT_FORMAT//&
                        ', " vs. ", '//INT_FORMAT//', ",  for channel index # ", i4 )'
        WRITE( Message, FMT = TRIM( Format_String ) ) &
                        SpcCoeff_LHS%Is_Microwave_Channel(l), &
                        SpcCoeff_RHS%Is_Microwave_Channel(l), &
                        l
        CALL Display_Message( ROUTINE_NAME, &
                              TRIM( Message ), &
                              Error_Status, &
                             Message_Log = Message_Log )
        IF ( Check_Once ) RETURN
      END IF

      ! ------------------------
      ! The channel polarization
      ! ------------------------

      IF ( ANY( .NOT. ( Compare_Float( SpcCoeff_LHS%Polarization(:,l), &
                                       SpcCoeff_RHS%Polarization(:,l), &
                                       ULP = ULP                       ) ) ) ) THEN
        Error_Status = FAILURE
        WRITE( Message, '( "Polarization values are different for channel index # ", i4 )' ) l
        CALL Display_Message( ROUTINE_NAME, &
                              TRIM( Message ), &
                              Error_Status, &
                              Message_Log = Message_Log )
        IF ( Check_Once ) RETURN
      END IF

      ! -------------------------------------------
      ! The effective cosmic background temperature
      ! -------------------------------------------

      IF ( .NOT. ( Compare_Float( SpcCoeff_LHS%Cosmic_Background_Temperature(l), &
                                  SpcCoeff_RHS%Cosmic_Background_Temperature(l), &
                                  ULP = ULP                                      ) ) ) THEN
        Error_Status = FAILURE
        Message = Construct_Message( 'Cosmic_Background_Temperature', l, &
                                     SpcCoeff_LHS%Cosmic_Background_Temperature(l), &
                                     SpcCoeff_RHS%Cosmic_Background_Temperature(l) )
        CALL Display_Message( ROUTINE_NAME, &
                              TRIM( Message ), &
                              Error_Status, &
                              Message_Log = Message_Log )
        IF ( Check_Once ) RETURN
      END IF

      ! ------------------------------
      ! The cosmic background radiance
      ! ------------------------------

      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

      ! --------------------------------
      ! The solar affected channel flags
      ! --------------------------------

      IF ( SpcCoeff_LHS%Is_Solar_Channel(l) /= SpcCoeff_RHS%Is_Solar_Channel(l) ) THEN
        Error_Status = FAILURE
        Format_String = '( "Is_Solar_Channel values are different, ", '//INT_FORMAT//&
                        ', " vs. ", '//INT_FORMAT//', ",  for channel index # ", i4 )'
        WRITE( Message, FMT = TRIM( Format_String ) ) &
                        SpcCoeff_LHS%Is_Solar_Channel(l), &
                        SpcCoeff_RHS%Is_Solar_Channel(l), &
                        l
        CALL Display_Message( ROUTINE_NAME, &
                              TRIM( Message ), &
                              Error_Status, &
                             Message_Log = Message_Log )
        IF ( Check_Once ) RETURN
      END IF

      ! -----------------------------------------------
      ! The Kurucz TOA solar irradiance source function
      ! -----------------------------------------------

      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

      ! --------------------------------------------
      ! The TOA blackbody irradiance source function
      ! --------------------------------------------

      IF ( .NOT. ( Compare_Float( SpcCoeff_LHS%Blackbody_Irradiance(l), &
                                  SpcCoeff_RHS%Blackbody_Irradiance(l), &
                                  ULP = ULP                             ) ) ) THEN
        Error_Status = FAILURE
        Message = Construct_Message( 'Blackbody_Irradiance', l, &
                                     SpcCoeff_LHS%Blackbody_Irradiance(l) , &
                                     SpcCoeff_RHS%Blackbody_Irradiance(l) )
        CALL Display_Message( ROUTINE_NAME, &
                              TRIM( Message ), &
                              Error_Status, &
                              Message_Log = Message_Log )
        IF ( Check_Once ) RETURN
      END IF

    END DO l_Channel_loop

  CONTAINS

    ! --------------------------------------------------------
    ! Internal subprogram to construct a standard message when
    ! a floating point number comparison fails.
    ! --------------------------------------------------------

    FUNCTION Construct_Message( Label, l, x1, x2 ) RESULT( Message )

      ! -- Arguments
      CHARACTER( * ),  INTENT( IN ) :: Label
      INTEGER,         INTENT( IN ) :: l
      REAL( fp_kind ), INTENT( IN ) :: x1, x2

      ! -- Function result
      CHARACTER( 256 ) :: Message

      ! -- Local parameters
      INTEGER,         PARAMETER :: WIDTH = 20
      REAL( fp_kind ), PARAMETER :: HUNDRED = 100.0_fp_kind

      ! -- Local variables
      CHARACTER(  6  ) :: Real_Format
      CHARACTER( LEN(SPCCOEFF_DATA_NAME) ) :: Data_Name
      CHARACTER( 256 ) :: Format_String
      INTEGER :: n
      REAL( fp_kind ) :: dx

      ! -- Determine the print format for the floating
      ! -- point numbers based on their magnitudes
      n = WIDTH - INT( MAX( LOG10( x1 ), LOG10( x2 ), 0.0_fp_kind ) ) - 2
      WRITE( Real_Format, FMT = '( "f", i2.2, ".", i2.2 )' ) WIDTH, n

      ! -- Construct the format string used to create the message
      Data_Name = TRIM( Label )
      Format_String = '( "'//Data_Name//' 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, l

    END FUNCTION Construct_Message

  END FUNCTION Equal_SpcCoeff

!----------------------------------------------------------------------------------
!S+
! NAME:
!       Check_SpcCoeff_Release
!
! PURPOSE:
!       Function to check the SpcCoeff Release value.
!
! CATEGORY:
!       Instrument Information : SpcCoeff
!
! LANGUAGE:
!       Fortran-95
!
! CALLING SEQUENCE:
!       Error_Status = Check_SpcCoeff_Release( 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:      None
!                      TYPE:       CHARACTER(*)
!                      DIMENSION:  Scalar
!                      ATTRIBUTES: INTENT( IN ), OPTIONAL
!
! OUTPUT ARGUMENTS:
!       None.
!
! OPTIONAL OUTPUT ARGUMENTS:
!       RCS_Id:        Character string containing the Revision Control
!                      System Id field for the module.
!                      UNITS:      None
!                      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 ERROR_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
!
! CALLS:
!       Display_Message:      Subroutine to output messages
!                             SOURCE: ERROR_HANDLER module
!
! SIDE EFFECTS:
!       None.
!
! RESTRICTIONS:
!       None.
!
! CREATION HISTORY:
!       Written by:     Paul van Delst, CIMSS/SSEC 19-Jun-2003
!                       paul.vandelst@ssec.wisc.edu
!S-
!----------------------------------------------------------------------------------

  FUNCTION Check_SpcCoeff_Release( SpcCoeff,     &  ! Input
                                   RCS_Id,       &  ! Revision control
                                   Message_Log ) &  ! Error messaging
                                 RESULT( Error_Status )

    !#--------------------------------------------------------------------------#
    !#                        -- TYPE DECLARATIONS --                           #
    !#--------------------------------------------------------------------------#

    ! ---------
    ! Arguments
    ! ---------

    ! -- Input
    TYPE( SpcCoeff_type ),    INTENT( IN )  :: SpcCoeff

    ! -- Optional output
    CHARACTER( * ), OPTIONAL, INTENT( OUT ) :: RCS_Id

    ! - Error messaging
    CHARACTER( * ), OPTIONAL, INTENT( IN )  :: Message_Log

    ! ---------------
    ! Function result
    ! ---------------

    INTEGER :: Error_Status

    ! ----------------
    ! Local parameters
    ! ----------------

    CHARACTER( * ), PARAMETER :: ROUTINE_NAME = 'Check_SpcCoeff_Release'

    ! ---------------
    ! Local variables
    ! ---------------

    CHARACTER( 256 ) :: Message

    !#--------------------------------------------------------------------------#
    !#                  -- DEFINE A SUCCESSFUL EXIT STATUS --                   #
    !#--------------------------------------------------------------------------#

    Error_Status = SUCCESS

    !#--------------------------------------------------------------------------#
    !#                -- SET THE RCS ID ARGUMENT IF SUPPLIED --                 #
    !#--------------------------------------------------------------------------#

    IF ( PRESENT( RCS_Id ) ) THEN
      RCS_Id = ' '
      RCS_Id = MODULE_RCS_ID
    END IF

    !#--------------------------------------------------------------------------#
    !#               -- CHECK THAT THE RELEASE IS NOT TOO OLD --                #
    !#--------------------------------------------------------------------------#

    IF ( SpcCoeff%Release < SPCCOEFF_RELEASE ) THEN
      Error_Status = FAILURE
      WRITE( Message, '( "A SpcCoeff data update is needed. ", &
                        &"SpcCoeff release is ", i2, &
                        &". Valid release is ",i2,"." )' ) &
                      SpcCoeff%Release, SPCCOEFF_RELEASE
      CALL Display_Message( ROUTINE_NAME, &
                            TRIM( Message ), &
                            Error_Status, &
                            Message_Log = Message_Log )
      RETURN
    END IF

    !#--------------------------------------------------------------------------#
    !#               -- CHECK THAT THE 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( ROUTINE_NAME, &
                            TRIM( Message ), &
                            Error_Status, &
                            Message_Log = Message_Log )
      RETURN
    END IF

  END FUNCTION Check_SpcCoeff_Release

!--------------------------------------------------------------------------------
!S+
! NAME:
!       Count_SpcCoeff_Sensors
!
! PURPOSE:
!       Subroutine to count the number of different satellite/sensors in the
!       SpcCoeff structure and set the n_Sensors field.
!
! CATEGORY:
!       Instrument Information : SpcCoeff
!
! LANGUAGE:
!       Fortran-95
!
! CALLING SEQUENCE:
!       CALL Count_SpcCoeff_Sensors( SpcCoeff,                &  ! In/Output
!                                    Use_WMO_ID = Use_WMO_ID, &  ! Optional input
!                                    RCS_Id = RCS_Id          )  ! Revision control
!
! INPUT ARGUMENTS:
!       SpcCoeff_in:   Filled SpcCoeff structure.
!                      UNITS:      N/A
!                      TYPE:       SpcCoeff_type
!                      DIMENSION:  Scalar
!                      ATTRIBUTES: INTENT( IN OUT )
!
! OPTIONAL INPUT ARGUMENTS:
!       Use_WMO_ID:    Set this argument to use the WMO satellite and sensor
!                      IDs in the SpcCoeff structure to count the number of
!                      different sensors. By default, the NCEP sensor ID is
!                      used.
!                      If = 0, use NCEP sensor ID (default)
!                         = 1, use WMO satellite/sensor ID
!                      UNITS:      N/A
!                      TYPE:       INTEGER
!                      DIMENSION:  Scalar
!                      ATTRIBUTES: INTENT( IN ), OPTIONAL
!
! OUTPUT ARGUMENTS:
!       None.
!
! OPTIONAL OUTPUT ARGUMENTS:
!       RCS_Id:        Character string containing the Revision Control
!                      System Id field for the module.
!                      UNITS:      None
!                      TYPE:       CHARACTER(*)
!                      DIMENSION:  Scalar
!                      ATTRIBUTES: INTENT( OUT ), OPTIONAL
!
!
! CALLS:
!       None.
!
! SIDE EFFECTS:
!       The N_SENSORS field of the input SpcCoeff structure is modified.
!
! RESTRICTIONS:
!       None.
!
! CREATION HISTORY:
!       Written by:     Paul van Delst, CIMSS/SSEC 22-Dec-2002
!                       paul.vandelst@ssec.wisc.edu
!S-
!--------------------------------------------------------------------------------

  SUBROUTINE Count_SpcCoeff_Sensors( SpcCoeff,   &  ! In/Output
                                     Use_WMO_ID, &  ! Optional input
                                     RCS_Id      )  ! Revision control

    !#--------------------------------------------------------------------------#
    !#                        -- TYPE DECLARATIONS --                           #
    !#--------------------------------------------------------------------------#

    ! ---------
    ! Arguments
    ! ---------

    ! -- Input
    TYPE( SpcCoeff_type ),    INTENT( IN OUT ) :: SpcCoeff

    ! -- Optional input
    INTEGER,        OPTIONAL, INTENT( IN )     :: Use_WMO_ID

    ! -- Revision control
    CHARACTER( * ), OPTIONAL, INTENT( OUT )    :: RCS_Id

    ! ---------------
    ! Local variables
    ! ---------------

    LOGICAL :: Use_NCEP_ID
    INTEGER :: l, j, n

    INTEGER, DIMENSION( SpcCoeff%n_Channels ) :: idx

    !#--------------------------------------------------------------------------#
    !#                -- SET THE RCS ID ARGUMENT IF SUPPLIED --                 #
    !#--------------------------------------------------------------------------#

    IF ( PRESENT( RCS_Id ) ) THEN
      RCS_Id = ' '
      RCS_Id = MODULE_RCS_ID
    END IF

    !#--------------------------------------------------------------------------#
    !#                -- CHECK/SET OPTIONAL KEYWORD ARGUMENT --                 #
    !#--------------------------------------------------------------------------#

    Use_NCEP_ID = .TRUE.
    IF ( PRESENT( Use_WMO_ID ) ) THEN
      IF ( Use_WMO_ID == SET ) Use_NCEP_ID = .FALSE.
    END IF

    !#--------------------------------------------------------------------------#
    !#                   -- INITIALISE INVALID RESULT VALUE --                  #
    !#--------------------------------------------------------------------------#

    SpcCoeff%n_Sensors = INVALID

    !#--------------------------------------------------------------------------#
    !#                     -- COUNT THE DIFFERENT SENSORS --                    #
    !#--------------------------------------------------------------------------#

    ID_Type: IF ( Use_NCEP_ID ) THEN

      !#------------------------------------------------------------------------#
      !#                     -- USING THE NCEP SENSOR ID --                     #
      !#------------------------------------------------------------------------#

      ! --------------------
      ! Check the data array
      ! --------------------

      ! -- Check that the pointer member is associated
      IF ( .NOT. ASSOCIATED( SpcCoeff%NCEP_Sensor_ID ) ) RETURN

      ! -- Check that all the values are valid 
      IF ( ANY( SpcCoeff%NCEP_Sensor_ID == INVALID ) ) RETURN

      ! ---------------------------
      ! Initialise the sensor count
      ! ---------------------------

      SpcCoeff%n_Sensors = 1

      ! ------------------
      ! Loop over channels
      ! ------------------

      DO l = 2, SpcCoeff%n_Channels

        ! -- Only increment sensor count if the current channel's
        ! -- value has not been previously encountered
        IF ( ALL( SpcCoeff%NCEP_Sensor_ID(1:l-1) /= SpcCoeff%NCEP_Sensor_ID(l) ) ) THEN
          SpcCoeff%n_Sensors = SpcCoeff%n_Sensors + 1
        END IF

      END DO

    ELSE ! Use WMO ID

      !#------------------------------------------------------------------------#
      !#                       -- USING THE WMO IDs --                          #
      !#------------------------------------------------------------------------#

      ! ---------------------
      ! Check the data arrays
      ! ---------------------

      ! -- Check that the pointer members are associated
      IF ( .NOT. ASSOCIATED( SpcCoeff%WMO_Satellite_ID ) .OR. &
           .NOT. ASSOCIATED( SpcCoeff%WMO_Sensor_ID    )      ) RETURN

      ! -- Check that all the values are valid 
      IF ( ANY( SpcCoeff%WMO_Satellite_ID == INVALID ) .OR. &
           ANY( SpcCoeff%WMO_Sensor_ID    == INVALID )      ) RETURN

      ! ---------------------------
      ! Initialise the sensor count
      ! ---------------------------

      SpcCoeff%n_Sensors = 1

      ! ------------------
      ! Loop over channels
      ! ------------------

      l_Channel_loop: DO l = 2, SpcCoeff%n_Channels

        ! ------------------------------------------
        ! Count the number of channels with the SAME
        ! WMO SENSOR ID as the current channel
        ! ------------------------------------------

        n = COUNT( SpcCoeff%WMO_Sensor_ID(1:l-1) == SpcCoeff%WMO_Sensor_ID(l) )

        ! ----------------------------------------------
        ! How many channels have the same WMO SENSOR ID?
        ! ----------------------------------------------

        IF ( n == 0 ) THEN

          ! -- None. Increment the sensor count
          SpcCoeff%n_Sensors = SpcCoeff%n_Sensors + 1

        ELSE

          ! -- Some channels have the same SENSOR ID.
          ! -- Now get those corresponding array indices
          idx(1:n) = PACK( (/ ( j, j=1,l-1 ) /), &
                           SpcCoeff%WMO_Sensor_ID(1:l-1) == SpcCoeff%WMO_Sensor_ID(l) )

          ! -- If ALL of the previous channels' SATELLITE ID
          ! -- values are different from the current channel,
          ! -- then we have a different sensor so increment
          ! -- the sensor count.
          IF ( ALL( SpcCoeff%WMO_Satellite_ID(idx(1:n)) /= SpcCoeff%WMO_Satellite_ID(l) ) ) THEN
            SpcCoeff%n_Sensors = SpcCoeff%n_Sensors + 1
          END IF

        END IF

      END DO l_Channel_loop

    END IF ID_Type

  END SUBROUTINE Count_SpcCoeff_Sensors

!--------------------------------------------------------------------------------
!S+
! NAME:
!       Version_SpcCoeff
!
! PURPOSE:
!       Subroutine to return a string containing version and dimension
!       information about the SpcCoeff data structure.
!
! CATEGORY:
!       Instrument Information : SpcCoeff
!
! LANGUAGE:
!       Fortran-95
!
! CALLING SEQUENCE:
!       CALL Version_SpcCoeff( SpcCoeff,       &  ! Input
!                              Version_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 )
!
! OPTIONAL INPUT ARGUMENTS:
!       None.
!
! OUTPUT ARGUMENTS:
!       Version_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:      None
!                      TYPE:       CHARACTER(*)
!                      DIMENSION:  Scalar
!                      ATTRIBUTES: INTENT( OUT ), OPTIONAL
!
! CALLS:
!       None.
!
! SIDE EFFECTS:
!       None.
!
! RESTRICTIONS:
!       None.
!
! CREATION HISTORY:
!       Written by:     Paul van Delst, CIMSS/SSEC 22-Dec-2002
!                       paul.vandelst@ssec.wisc.edu
!S-
!--------------------------------------------------------------------------------

  SUBROUTINE Version_SpcCoeff( SpcCoeff,     &  ! Input
                               Version_Info, &  ! Output
                               RCS_Id        )  ! Revision control

    !#--------------------------------------------------------------------------#
    !#                        -- TYPE DECLARATIONS --                           #
    !#--------------------------------------------------------------------------#

    ! ---------
    ! Arguments
    ! ---------

    ! -- Input
    TYPE( SpcCoeff_type ),    INTENT( IN )  :: SpcCoeff

    ! -- Output
    CHARACTER( * ),           INTENT( OUT ) :: Version_Info

    ! -- Revision control
    CHARACTER( * ), OPTIONAL, INTENT( OUT ) :: RCS_Id

    ! ----------
    ! Parameters
    ! ----------

    INTEGER, PARAMETER :: CARRIAGE_RETURN = 13
    INTEGER, PARAMETER :: LINEFEED = 10

    ! ---------------
    ! Local variables
    ! ---------------

    CHARACTER( 512 ) :: Long_String

    !#--------------------------------------------------------------------------#
    !#                -- SET THE RCS ID ARGUMENT IF SUPPLIED --                 #
    !#--------------------------------------------------------------------------#

    IF ( PRESENT( RCS_Id ) ) THEN
      RCS_Id = ' '
      RCS_Id = MODULE_RCS_ID
    END IF

    !#--------------------------------------------------------------------------#
    !#                     -- FILL THE VERSION INFO STRING --                   #
    !#--------------------------------------------------------------------------#

    ! -------------------------------------------
    ! Write the required data to the local string
    ! -------------------------------------------

    WRITE( Long_String, '( a,1x,"SpcCoeff RELEASE.VERSION: ", i2, ".", i2.2, 2x, &
                           &"N_CHANNELS=",i4,2x,&
                           &"N_SENSORS=",i2 )' ) &
                        ACHAR(CARRIAGE_RETURN)//ACHAR(LINEFEED), &
                        SpcCoeff%Release, SpcCoeff%Version, &
                        SpcCoeff%n_Channels, &
                        SpcCoeff%n_Sensors

    ! ----------------------------
    ! Trim the output based on the
    ! dummy argument string length
    ! ----------------------------

    Version_Info = Long_String(1:MIN( LEN( Version_Info ), LEN_TRIM( Long_String ) ))

  END SUBROUTINE Version_SpcCoeff

END MODULE SpcCoeff_Define

!---------------------------------------------------------------------------------
!                          -- MODIFICATION HISTORY --
!---------------------------------------------------------------------------------
!
! $Id: SpcCoeff_Define.f90,v 4.7 2004/09/27 19:05:28 paulv Exp $
!
! $Date: 2004/09/27 19:05:28 $
!
! $Revision: 4.7 $
!
! $Name: RTM_beta_2-3_p1 $
!
! $State: Exp $
!
! $Log: SpcCoeff_Define.f90,v $
! Revision 4.7  2004/09/27 19:05:28  paulv
! - Concatenation now uses newest version number for result.
!
! Revision 4.6  2004/09/09 20:25:43  paulv
! - Added association test in destroy function. If no pointer components
!   are associated, the function returns without modifying the n_Allocates
!   counter. Thus, calling the destroy function on an already destroyed
!   structure want flag an error.
!
! Revision 4.5  2004/09/02 16:47:19  paulv
! - Added optional ULP_Scale argument to Equal_SpcCoeff() function.
! - Replaced .EqualTo. operator with Compare_Float() function call in
!   Equal_SpcCoeff() function to allow user to specify an ULP scale value
!   for the floating point comparisons.
! - Added internal subprogram Construct_Message() to Equal_SpcCoeff() function
!   to construct a standard message when a floating point comparison fails.
!
! Revision 4.4  2004/08/31 23:00:06  paulv
! - Replaced calls to Compare_Float() function with use of .EqualTo. operator
!   in Equal_SpcCoeff() function.
!
! Revision 4.3  2004/08/23 14:39:22  paulv
! - Removed warning message from Allocate() function when the structure argument
!   is already allocated. Now it is silently destroyed and reallocated.
!
! Revision 4.2  2004/08/18 16:16:43  paulv
! - Upgraded to Fortran95.
! - Derived type component initialisation is now done in the defintion block.
! - Init_SpcCoeff() subroutine has been removed.
! - Intent of SpcCoeff dummy argument in Clear_SpcCoeff() routine changed from
!   OUT to IN OUT to prevent memory leaks.
! - Added optional No_Clear argument to Destroy_SpcCoeff() function.
! - Intent of SpcCoeff dummy argument in Allocate_SpcCoeff() routine changed from
!   OUT to IN OUT to prevent memory leaks.
! - Call to Destroy_SpcCoeff() added to Allocate_SpcCoeff() function for the case
!   where the input SpcCoeff argument is already allocated.
! - Intent of SpcCoeff_out dummy argument in Assign_SpcCoeff() routine changed from
!   OUT to IN OUT to prevent memory leaks.
! - Using new Compare_Float_Numbers module with elemental function. This required
!   changing the comparison of the polarisation component from
!     IF ( .NOT. Compare_Float( SpcCoeff_LHS%Polarization(:,l), &
!                               SpcCoeff_RHS%Polarization(:,l)  ) ) THEN
!   to
!     IF ( ANY( .NOT. Compare_Float( SpcCoeff_LHS%Polarization(:,l), &
!                                    SpcCoeff_RHS%Polarization(:,l)  ) ) ) THEN
! - Updated header documentation.
!
! Revision 4.1  2004/06/25 22:31:32  paulv
! - Minor header documentation update.
!
! Revision 4.0  2004/06/25 19:40:18  paulv
! - Updated polarization component to a full Stokes vector.
!
! Revision 3.2  2004/06/25 17:12:07  paulv
! - Removed unused variables from type declarations.
! - Cosmetic changes.
!
! Revision 3.1  2004/06/24 18:56:44  paulv
! - Minor documentation update.
!
! Revision 3.0  2004/05/17 17:40:41  paulv
! - Added Sensor_Descriptor component to SpcCoeff structure. Modified the
!   netCDF and Binary I/O modules to handle the new component. New SpcCoeff
!   release number is 3.
!
! Revision 2.15  2004/05/12 20:48:22  paulv
! - Added assignment of optional RCS_ID argument in the Count_SpcCoeff_Sensors()
!   routine. Forgot to include it, even though the RCS_Id is an optional argument.
!
! Revision 2.14  2004/03/09 17:24:36  paulv
! - Mostly cosmetic changes. Some fixes to eliminate possibilities of
!   exceeding string lengths.
!
! Revision 2.13  2003/11/13 19:35:47  paulv
! - Updated header documentation.
!
! Revision 2.12  2003/10/24 18:18:14  paulv
! - Code category changed from
!     NCEP RTM : Coefficients : SpcCoeff
!   to
!     Instrument Information : SpcCoeff
!
! Revision 2.11  2003/10/24 18:04:07  paulv
! - Changed scalar component reinitialisation in Clear() routine to 0 from INVALID.
! - Intent of SpcCoeff structure in Destroy() routine cahnged to IN OUT from OUT.
! - Added CHECK_ALL optional argument to Equal() routine. Default action is to
!   return as soon as ANY difference is found. Setting this argument will still
!   check ALL the SpcCoeff floating point data even if differences are found.
! - Added MESSAGE_LOG optional argument to CHECK_SPCCOEFF_RELEASE() function.
!
! Revision 2.10  2003/06/19 21:32:24  paulv
! - Added SPCCOEFF_RELEASE and SPCCOEFF_VERSION parameters to assign to SpcCoeff
!   structure Release and Version members during initialisation.
! - Added optional VERSION argument to the Initialize_SpcCoeff() function to
!   allow user to override default initialisation value.
! - Added Check_SpcCoeff_Release() function.
!
! Revision 2.9  2003/04/14 19:54:38  paulv
! - Corrected bug in sensor counting routine when the WMO Ids were used to
!   identify separate sensors.
!
! Revision 2.8  2003/04/02 17:07:24  paulv
! - Added USE of Compare_Float_Numbers module. All floating point comparisons
!   in the Equal_SpcCoeff() function are now done using the Compare_Float()
!   function.
!
! Revision 2.7  2003/04/01 14:48:50  paulv
! - Minor documentation corrections.
!
! Revision 2.6  2003/03/31 16:49:59  paulv
! - Added RCS_Id optional output argument to public functions.
! - Removed Check_SpcCoeff_Status routine and replaced it with the PRIVATE
!   Associated_SpcCoeff function. All references to the former routine have been replaced
!   with the latter.
! - Updated documentation.
!
! Revision 2.5  2003/02/10 22:54:33  paulv
! - Added SpcCoeff structure concatenation function.
!
! Revision 2.4  2002/12/26 17:34:06  paulv
! - Added Equal_SpcCoeff() function to compare SpcCoeff structures.
! - Added Check_SpcCoeff_Status() function to check the association
!   status of pointer members in an SpcCoeff structure.
! - Added Version_SpcCoeff() function to generate an info string used in
!   INFORMATION message output.
!
! Revision 2.3  2002/12/24 00:13:46  paulv
! - Corrected bug in WMO_Satellite_ID variable name.
!
! Revision 2.2  2002/12/23 12:51:26  paulv
! - Completed new versions. Untested.
!
! Revision 2.1  2002/12/20 22:22:23  paulv
! - New version with more sensor channel information.
!
! Revision 1.2  2002/08/16 20:49:32  paulv
! - Corrected bug in SpcCoeff TYPE specification.
!
! Revision 1.1  2002/08/13 20:05:39  paulv
! Initial checkin
!
!
!
!
!