21   USE iso_fortran_env       , 
ONLY: output_unit
    26                                     OPERATOR(.equalto.), &
    56   PUBLIC :: 
OPERATOR(==)
   101   INTERFACE OPERATOR(==)
   103   END INTERFACE OPERATOR(==)
   105   INTERFACE OPERATOR(+)
   107   END INTERFACE OPERATOR(+)
   109   INTERFACE OPERATOR(-)
   111   END INTERFACE OPERATOR(-)
   128   '$Id: CRTM_Surface_Define.f90 60152 2015-08-13 19:19:13Z paul.vandelst@noaa.gov $'   130   REAL(fp), 
PARAMETER :: 
zero = 0.0_fp
   131   REAL(fp), 
PARAMETER :: 
one  = 1.0_fp
   133   INTEGER, 
PARAMETER :: 
ml = 256
   149   CHARACTER(*), 
PARAMETER, 
DIMENSION( 0:N_VALID_SURFACE_TYPES ) :: &
   157                            'Land + water + snow      ', &
   161                            'Land + water + ice       ', &
   163                            'Land + snow + ice        ', &
   164                            'Water + snow + ice       ', &
   165                            'Land + water + snow + ice' /)
   204     LOGICAL :: is_allocated = .true.  
   208     REAL(fp) :: land_coverage  = 
zero   209     REAL(fp) :: water_coverage = 
zero   210     REAL(fp) :: snow_coverage  = 
zero   211     REAL(fp) :: ice_coverage   = 
zero   294     status = sfc%Is_Allocated
   325     sfc%Is_Allocated = .true.  
   366     INTEGER                , 
INTENT(IN)  :: n_channels
   369     IF ( n_channels < 0 ) 
RETURN   376     sfc%Is_Allocated = .true.
   414     sfc%Land_Coverage  = 
zero   415     sfc%Water_Coverage = 
zero   416     sfc%Snow_Coverage  = 
zero   417     sfc%Ice_Coverage   = 
zero   473     CHARACTER(*), 
PARAMETER :: routine_name = 
'CRTM_Surface_IsValid'   478     IF ( .NOT. isvalid ) 
THEN   479       msg = 
'Invalid surface coverage fraction(s) found'   532     INTEGER,       
OPTIONAL, 
INTENT(IN) :: unit
   538     IF ( 
PRESENT(unit) ) 
THEN   543     WRITE(fid,
'(1x,"Surface OBJECT")')
   545     WRITE(fid,
'(3x,"Land Coverage :",1x,f6.3)') sfc%Land_Coverage
   546     WRITE(fid,
'(3x,"Water Coverage:",1x,f6.3)') sfc%Water_Coverage
   547     WRITE(fid,
'(3x,"Snow Coverage :",1x,f6.3)') sfc%Snow_Coverage
   548     WRITE(fid,
'(3x,"Ice Coverage  :",1x,f6.3)') sfc%Ice_Coverage
   597     CHARACTER(*), 
PARAMETER :: routine_name = 
'CRTM_Surface_IsCoverageValid'   598     REAL(fp)    , 
PARAMETER :: 
tolerance = 1.0e-6_fp
   600     REAL(fp) :: total_coverage
   603     total_coverage = sfc%Land_Coverage + sfc%Water_Coverage + &
   604                      sfc%Snow_Coverage + sfc%Ice_Coverage
   614       WRITE( msg,
'("Total coverage fraction does not sum to 1 +/- ",2es13.6)' ) 
tolerance, total_coverage-
one   622       REAL(fp)    , 
INTENT(IN) :: coverage
   623       CHARACTER(*), 
INTENT(IN) :: name
   630         WRITE( msg,
'(a," coverage fraction is < ",es13.6)' ) trim(name), -
tolerance   637         WRITE( msg,
'(a," coverage fraction is > 1 +",es13.6)' ) trim(name), 
tolerance   684     INTEGER :: coverage_type
   688     IF ( sfc%Snow_Coverage  > 
zero ) coverage_type = coverage_type + 
snow_surface   689     IF ( sfc%Ice_Coverage   > 
zero ) coverage_type = coverage_type + 
ice_surface   717     CHARACTER(*), 
INTENT(OUT) :: id
   761   result( is_comparable )
   763     INTEGER,       
OPTIONAL, 
INTENT(IN) :: n_sigfig
   764     LOGICAL :: is_comparable
   769     is_comparable = .false.
   770     IF ( 
PRESENT(n_sigfig) ) 
THEN   801     is_comparable = .true.
   858     n_Channels , &  ! Optional output
   862     CHARACTER(*),           
INTENT(IN)  :: filename
   863     INTEGER     , 
OPTIONAL, 
INTENT(OUT) :: n_channels
   864     INTEGER     , 
OPTIONAL, 
INTENT(OUT) :: n_profiles
   868     CHARACTER(*), 
PARAMETER :: routine_name = 
'CRTM_Surface_InquireFile'   871     CHARACTER(ML) :: io_msg
   880       msg = 
'File '//trim(filename)//
' not found.'   886     IF ( err_stat /= 
success ) 
THEN   887       msg = 
'Error opening '//trim(filename)
   892     READ( fid, iostat=io_stat,iomsg=io_msg ) l, m
   893     IF ( io_stat /= 0 ) 
THEN   894       msg = 
'Error reading dimensions from '//trim(filename)//
' - '//trim(io_msg)
   899     CLOSE( fid, iostat=io_stat,iomsg=io_msg )
   900     IF ( io_stat /= 0 ) 
THEN   901       msg = 
'Error closing '//trim(filename)//
' - '//trim(io_msg)
   906     IF ( 
PRESENT(n_channels) ) n_channels = l
   907     IF ( 
PRESENT(n_profiles) ) n_profiles = m
   913         CLOSE( fid,iostat=io_stat,iomsg=io_msg )
   915           msg = trim(msg)//
'; Error closing input file during error cleanup - '//trim(io_msg)
  1008     Filename  , &  ! Input
  1009     Surface   , &  ! Output
  1010     Quiet     , &  ! Optional input
  1011     n_Channels, &  ! Optional output
  1012     n_Profiles, &  ! Optional output
  1016     CHARACTER(*),                         
INTENT(IN)  :: filename
  1018     LOGICAL,       
OPTIONAL,              
INTENT(IN)  :: quiet
  1019     INTEGER,       
OPTIONAL,              
INTENT(OUT) :: n_channels
  1020     INTEGER,       
OPTIONAL,              
INTENT(OUT) :: n_profiles
  1021     LOGICAL,       
OPTIONAL,              
INTENT(IN)  :: debug
  1025     CHARACTER(*), 
PARAMETER :: routine_name = 
'CRTM_Surface_ReadFile(M)'  1027     CHARACTER(ML) :: msg
  1028     CHARACTER(ML) :: io_msg
  1029     CHARACTER(ML) :: alloc_msg
  1031     INTEGER :: alloc_stat
  1034     INTEGER :: n_input_channels
  1035     INTEGER :: m, n_input_profiles
  1042     IF ( 
PRESENT(quiet) ) noisy = .NOT. quiet
  1044     IF ( 
PRESENT(debug) ) noisy = debug
  1049     IF ( err_stat /= 
success ) 
THEN  1050       msg = 
'Error opening '//trim(filename)
  1056     READ( fid,iostat=io_stat,iomsg=io_msg ) n_input_channels, n_input_profiles
  1057     IF ( io_stat /= 0 ) 
THEN  1058       msg = 
'Error reading dimensions from '//trim(filename)//
' - '//trim(io_msg)
  1062     IF ( n_input_channels /= 0 ) 
THEN  1063       msg = 
'n_Channels dimensions in '//trim(filename)//
' is not zero for a rank-1 '//&
  1064             '(i.e. profiles only) Surface read.'  1068     ALLOCATE(surface(n_input_profiles), stat=alloc_stat, errmsg=alloc_msg)
  1069     IF ( alloc_stat /= 0 ) 
THEN  1070       msg = 
'Error allocating Surface array - '//trim(alloc_msg)
  1076     profile_loop: 
DO m = 1, n_input_profiles
  1080       IF ( err_stat /= 
success ) 
THEN  1081         WRITE( msg,
'("Error reading Surface element (",i0,") from ",a)' ) m, trim(filename)
  1088     CLOSE( fid,iostat=io_stat,iomsg=io_msg )
  1089     IF ( io_stat /= 0 ) 
THEN  1090       msg = 
'Error closing '//trim(filename)//
' - '//trim(io_msg)
  1096     IF ( 
PRESENT(n_channels) ) n_channels = 0
  1097     IF ( 
PRESENT(n_profiles) ) n_profiles = n_input_profiles
  1102       WRITE( msg,
'("Number of profiles read from ",a,": ",i0)' ) trim(filename), n_input_profiles
  1110         CLOSE( fid,iostat=io_stat,iomsg=io_msg )
  1111         IF ( io_stat /= 0 ) &
  1112           msg = trim(msg)//
'; Error closing input file during error cleanup - '//trim(io_msg)
  1114       IF ( 
ALLOCATED(surface) ) 
THEN   1115         DEALLOCATE(surface, stat=alloc_stat, errmsg=alloc_msg)
  1116         IF ( alloc_stat /= 0 ) &
  1117           msg = trim(msg)//
'; Error deallocating Surface array during error cleanup - '//&
  1128     Filename  , &  ! Input
  1129     Surface   , &  ! Output
  1130     Quiet     , &  ! Optional input
  1131     n_Channels, &  ! Optional output
  1132     n_Profiles, &  ! Optional output
  1136     CHARACTER(*),                         
INTENT(IN)  :: filename
  1138     LOGICAL,       
OPTIONAL,              
INTENT(IN)  :: quiet
  1139     INTEGER,       
OPTIONAL,              
INTENT(OUT) :: n_channels
  1140     INTEGER,       
OPTIONAL,              
INTENT(OUT) :: n_profiles
  1141     LOGICAL,       
OPTIONAL,              
INTENT(IN)  :: debug
  1145     CHARACTER(*), 
PARAMETER :: routine_name = 
'CRTM_Surface_ReadFile(L x M)'  1147     CHARACTER(ML) :: msg
  1148     CHARACTER(ML) :: io_msg
  1149     CHARACTER(ML) :: alloc_msg
  1151     INTEGER :: alloc_stat
  1154     INTEGER :: l, n_input_channels
  1155     INTEGER :: m, n_input_profiles
  1162     IF ( 
PRESENT(quiet) ) noisy = .NOT. quiet
  1164     IF ( 
PRESENT(debug) ) noisy = debug
  1169     IF ( err_stat /= 
success ) 
THEN  1170       msg = 
'Error opening '//trim(filename)
  1176     READ( fid,iostat=io_stat,iomsg=io_msg ) n_input_channels, n_input_profiles
  1177     IF ( io_stat /= 0 ) 
THEN  1178       msg = 
'Error reading dimensions from '//trim(filename)//
' - '//trim(io_msg)
  1182     ALLOCATE(surface(n_input_channels, n_input_profiles), stat=alloc_stat, errmsg=alloc_msg)
  1183     IF ( alloc_stat /= 0 ) 
THEN  1184       msg = 
'Error allocating Surface array - '//trim(alloc_msg)
  1190     profile_loop: 
DO m = 1, n_input_profiles
  1191       channel_loop: 
DO l = 1, n_input_channels
  1195         IF ( err_stat /= 
success ) 
THEN  1196           WRITE( msg,
'("Error reading Surface element (",i0,",",i0,") from ",a)' ) &
  1197                  l, m, trim(filename)
  1205     CLOSE( fid,iostat=io_stat,iomsg=io_msg )
  1206     IF ( io_stat /= 0 ) 
THEN  1207       msg = 
'Error closing '//trim(filename)//
' - '//trim(io_msg)
  1213     IF ( 
PRESENT(n_channels) ) n_channels = n_input_channels
  1214     IF ( 
PRESENT(n_profiles) ) n_profiles = n_input_profiles
  1219       WRITE( msg,
'("Number of channels and profiles read from ",a,": ",i0,1x,i0)' ) &
  1220              trim(filename), n_input_channels, n_input_profiles
  1228         CLOSE( fid,iostat=io_stat,iomsg=io_msg )
  1229         IF ( io_stat /= 0 ) &
  1230           msg = trim(msg)//
'; Error closing input file during error cleanup - '//trim(io_msg)
  1232       IF ( 
ALLOCATED(surface) ) 
THEN   1233         DEALLOCATE(surface, stat=alloc_stat, errmsg=alloc_msg)
  1234         IF ( alloc_stat /= 0 ) &
  1235           msg = trim(msg)//
'; Error deallocating Surface array during error cleanup - '//&
  1319     Quiet   , &  ! Optional input
  1323     CHARACTER(*),            
INTENT(IN) :: filename
  1325     LOGICAL,       
OPTIONAL, 
INTENT(IN) :: quiet
  1326     LOGICAL,       
OPTIONAL, 
INTENT(IN) :: debug
  1330     CHARACTER(*), 
PARAMETER :: routine_name = 
'CRTM_Surface_WriteFile(M)'  1332     CHARACTER(ML) :: msg
  1333     CHARACTER(ML) :: io_msg
  1337     INTEGER :: m, n_output_profiles
  1343     IF ( 
PRESENT(quiet) ) noisy = .NOT. quiet
  1345     IF ( 
PRESENT(debug) ) 
THEN  1346       IF ( debug ) noisy = .true.
  1349     n_output_profiles = 
SIZE(surface)
  1354     IF ( err_stat /= 
success ) 
THEN  1355       msg = 
'Error opening '//trim(filename)
  1361     WRITE( fid,iostat=io_stat,iomsg=io_msg ) 0, n_output_profiles
  1362     IF ( io_stat /= 0 ) 
THEN  1363       msg = 
'Error writing dimensions to '//trim(filename)//
'- '//trim(io_msg)
  1369     profile_loop: 
DO m = 1, n_output_profiles
  1373       IF ( err_stat /= 
success ) 
THEN  1374         WRITE( msg,
'("Error writing Surface element (",i0,") to ",a)' ) m, trim(filename)
  1381     CLOSE( fid,status=
'KEEP',iostat=io_stat,iomsg=io_msg )
  1382     IF ( io_stat /= 0 ) 
THEN  1383       msg = 
'Error closing '//trim(filename)//
'- '//trim(io_msg)
  1390       WRITE( msg,
'("Number of profiles written to ",a,": ",i0)' ) &
  1391              trim(filename), n_output_profiles
  1400         IF ( io_stat /= 0 ) &
  1401           msg = trim(msg)//
'; Error deleting output file during error cleanup - '//trim(io_msg)
  1413     Quiet   , &  ! Optional input
  1417     CHARACTER(*),            
INTENT(IN)  :: filename
  1419     LOGICAL,       
OPTIONAL, 
INTENT(IN)  :: quiet
  1420     LOGICAL,       
OPTIONAL, 
INTENT(IN)  :: debug
  1424     CHARACTER(*), 
PARAMETER :: routine_name = 
'CRTM_Surface_WriteFile(L x M)'  1426     CHARACTER(ML) :: msg
  1427     CHARACTER(ML) :: io_msg
  1431     INTEGER :: l, n_output_channels
  1432     INTEGER :: m, n_output_profiles
  1438     IF ( 
PRESENT(quiet) ) noisy = .NOT. quiet
  1440     IF ( 
PRESENT(debug) ) 
THEN  1441       IF ( debug ) noisy = .true.
  1444     n_output_channels = 
SIZE(surface,dim=1)
  1445     n_output_profiles = 
SIZE(surface,dim=2)
  1450     IF ( err_stat /= 
success ) 
THEN  1451       msg = 
'Error opening '//trim(filename)
  1457     WRITE( fid,iostat=io_stat,iomsg=io_msg ) n_output_channels, n_output_profiles
  1458     IF ( io_stat /= 0 ) 
THEN  1459       msg = 
'Error writing dimensions to '//trim(filename)//
'- '//trim(io_msg)
  1465     profile_loop: 
DO m = 1, n_output_profiles
  1466       channel_loop: 
DO l = 1, n_output_channels
  1470         IF ( err_stat /= 
success ) 
THEN  1471           WRITE( msg,
'("Error writing Surface element (",i0,",",i0,") to ",a)' ) &
  1472                  l, m, trim(filename)
  1480     CLOSE( fid,status=
'KEEP',iostat=io_stat,iomsg=io_msg )
  1481     IF ( io_stat /= 0 ) 
THEN  1482       msg = 
'Error closing '//trim(filename)//
'- '//trim(io_msg)
  1489       WRITE( msg,
'("Number of channels and profiles written to ",a,": ",i0,1x,i0 )' ) &
  1490              trim(filename), n_output_channels, n_output_profiles
  1499         IF ( io_stat /= 0 ) &
  1500           msg = trim(msg)//
'; Error deleting output file during error cleanup - '//trim(io_msg)
  1556     is_equal = ( (x%Land_Coverage  .equalto. y%Land_Coverage ) .AND. &
  1557                  (x%Water_Coverage .equalto. y%Water_Coverage) .AND. &
  1558                  (x%Snow_Coverage  .equalto. y%Snow_Coverage ) .AND. &
  1559                  (x%Ice_Coverage   .equalto. y%Ice_Coverage  )       )
  1560     IF ( .NOT. is_equal ) 
RETURN  1564     IF ( .NOT. is_equal ) 
RETURN  1568     IF ( .NOT. is_equal ) 
RETURN  1572     IF ( .NOT. is_equal ) 
RETURN  1576     IF ( .NOT. is_equal ) 
RETURN  1581       is_equal = is_equal .AND. (x%SensorData == y%SensorData)
  1627     sfcsum%Land_Temperature      = sfcsum%Land_Temperature      + sfc2%Land_Temperature
  1628     sfcsum%Soil_Moisture_Content = sfcsum%Soil_Moisture_Content + sfc2%Soil_Moisture_Content
  1629     sfcsum%Canopy_Water_Content  = sfcsum%Canopy_Water_Content  + sfc2%Canopy_Water_Content
  1630     sfcsum%Vegetation_Fraction   = sfcsum%Vegetation_Fraction   + sfc2%Vegetation_Fraction
  1631     sfcsum%Soil_Temperature      = sfcsum%Soil_Temperature      + sfc2%Soil_Temperature
  1632     sfcsum%LAI                   = sfcsum%LAI                   + sfc2%LAI
  1633     sfcsum%Water_Temperature     = sfcsum%Water_Temperature     + sfc2%Water_Temperature
  1634     sfcsum%Wind_Speed            = sfcsum%Wind_Speed            + sfc2%Wind_Speed
  1635     sfcsum%Wind_Direction        = sfcsum%Wind_Direction        + sfc2%Wind_Direction
  1636     sfcsum%Salinity              = sfcsum%Salinity              + sfc2%Salinity
  1637     sfcsum%Snow_Temperature      = sfcsum%Snow_Temperature      + sfc2%Snow_Temperature
  1638     sfcsum%Snow_Depth            = sfcsum%Snow_Depth            + sfc2%Snow_Depth
  1639     sfcsum%Snow_Density          = sfcsum%Snow_Density          + sfc2%Snow_Density
  1640     sfcsum%Snow_Grain_Size       = sfcsum%Snow_Grain_Size       + sfc2%Snow_Grain_Size
  1641     sfcsum%Ice_Temperature       = sfcsum%Ice_Temperature       + sfc2%Ice_Temperature
  1642     sfcsum%Ice_Thickness         = sfcsum%Ice_Thickness         + sfc2%Ice_Thickness
  1643     sfcsum%Ice_Density           = sfcsum%Ice_Density           + sfc2%Ice_Density
  1644     sfcsum%Ice_Roughness         = sfcsum%Ice_Roughness         + sfc2%Ice_Roughness
  1648       sfcsum%SensorData = sfcsum%SensorData + sfc2%SensorData
  1694     sfcdiff%Land_Temperature      = sfcdiff%Land_Temperature      - sfc2%Land_Temperature
  1695     sfcdiff%Soil_Moisture_Content = sfcdiff%Soil_Moisture_Content - sfc2%Soil_Moisture_Content
  1696     sfcdiff%Canopy_Water_Content  = sfcdiff%Canopy_Water_Content  - sfc2%Canopy_Water_Content
  1697     sfcdiff%Vegetation_Fraction   = sfcdiff%Vegetation_Fraction   - sfc2%Vegetation_Fraction
  1698     sfcdiff%Soil_Temperature      = sfcdiff%Soil_Temperature      - sfc2%Soil_Temperature
  1699     sfcdiff%LAI                   = sfcdiff%LAI                   - sfc2%LAI
  1700     sfcdiff%Water_Temperature     = sfcdiff%Water_Temperature     - sfc2%Water_Temperature
  1701     sfcdiff%Wind_Speed            = sfcdiff%Wind_Speed            - sfc2%Wind_Speed
  1702     sfcdiff%Wind_Direction        = sfcdiff%Wind_Direction        - sfc2%Wind_Direction
  1703     sfcdiff%Salinity              = sfcdiff%Salinity              - sfc2%Salinity
  1704     sfcdiff%Snow_Temperature      = sfcdiff%Snow_Temperature      - sfc2%Snow_Temperature
  1705     sfcdiff%Snow_Depth            = sfcdiff%Snow_Depth            - sfc2%Snow_Depth
  1706     sfcdiff%Snow_Density          = sfcdiff%Snow_Density          - sfc2%Snow_Density
  1707     sfcdiff%Snow_Grain_Size       = sfcdiff%Snow_Grain_Size       - sfc2%Snow_Grain_Size
  1708     sfcdiff%Ice_Temperature       = sfcdiff%Ice_Temperature       - sfc2%Ice_Temperature
  1709     sfcdiff%Ice_Thickness         = sfcdiff%Ice_Thickness         - sfc2%Ice_Thickness
  1710     sfcdiff%Ice_Density           = sfcdiff%Ice_Density           - sfc2%Ice_Density
  1711     sfcdiff%Ice_Roughness         = sfcdiff%Ice_Roughness         - sfc2%Ice_Roughness
  1715       sfcdiff%SensorData = sfcdiff%SensorData - sfc2%SensorData
  1736     sfc%Land_Temperature      = 
zero  1737     sfc%Soil_Moisture_Content = 
zero  1738     sfc%Canopy_Water_Content  = 
zero  1739     sfc%Vegetation_Fraction   = 
zero  1740     sfc%Soil_Temperature      = 
zero  1748     CHARACTER(*), 
PARAMETER :: routine_name = 
'CRTM_LandSurface_IsValid'  1749     CHARACTER(ML) :: msg
  1755     IF ( sfc%Land_Type < 1 ) 
THEN  1756       msg = 
'Invalid Land Surface type'  1760     IF ( sfc%Land_Temperature      < 
zero .OR. &
  1761          sfc%Soil_Moisture_Content < 
zero .OR. &
  1762          sfc%Canopy_Water_Content  < 
zero .OR. &
  1763          sfc%Vegetation_Fraction   < 
zero .OR. &
  1764          sfc%Soil_Temperature      < 
zero .OR. &
  1765          sfc%LAI                   < 
zero      ) 
THEN  1766       msg = 
'Invalid Land Surface data'  1775     TYPE(CRTM_Surface_type), 
INTENT(IN) :: Sfc
  1776     INTEGER,       
OPTIONAL, 
INTENT(IN) :: Unit
  1779     IF ( 
PRESENT(unit) ) 
THEN  1782     WRITE(fid,
'(3x,"Land type index      :",1x,i0)') sfc%Land_Type
  1783     WRITE(fid,
'(3x,"Land Temperature     :",1x,es13.6)') sfc%Land_Temperature
  1784     WRITE(fid,
'(3x,"Soil Moisture Content:",1x,es13.6)') sfc%Soil_Moisture_Content
  1785     WRITE(fid,
'(3x,"Canopy Water Content :",1x,es13.6)') sfc%Canopy_Water_Content
  1786     WRITE(fid,
'(3x,"Vegetation Fraction  :",1x,es13.6)') sfc%Vegetation_Fraction
  1787     WRITE(fid,
'(3x,"Soil Temperature     :",1x,es13.6)') sfc%Soil_Temperature
  1788     WRITE(fid,
'(3x,"Leaf Area Index      :",1x,es13.6)') sfc%LAI
  1789     WRITE(fid,
'(3x,"Soil type index      :",1x,i0)') sfc%Soil_Type
  1790     WRITE(fid,
'(3x,"Vegetation type index:",1x,i0)') sfc%Vegetation_Type
  1796     INTEGER,       
OPTIONAL, 
INTENT(IN) :: n_sigfig
  1797     LOGICAL :: is_comparable
  1802     is_comparable = .false.
  1803     IF ( 
PRESENT(n_sigfig) ) 
THEN  1810     IF ( x%Land_Type       /= y%Land_Type .OR. &
  1811          x%Soil_Type       /= y%Soil_Type .OR. &
  1812          x%Vegetation_Type /= y%Vegetation_Type ) 
RETURN  1823     is_comparable = .true.
  1831     is_equal = ( (x%Land_Type                ==     y%Land_Type            ) .AND. &
  1832                  (x%Land_Temperature      .equalto. y%Land_Temperature     ) .AND. &
  1833                  (x%Soil_Moisture_Content .equalto. y%Soil_Moisture_Content) .AND. &
  1834                  (x%Canopy_Water_Content  .equalto. y%Canopy_Water_Content ) .AND. &
  1835                  (x%Vegetation_Fraction   .equalto. y%Vegetation_Fraction  ) .AND. &
  1836                  (x%Soil_Temperature      .equalto. y%Soil_Temperature     ) .AND. &
  1837                  (x%LAI                   .equalto. y%LAI                  ) .AND. &
  1838                  (x%Soil_Type                ==     y%Soil_Type            ) .AND. &
  1839                  (x%Vegetation_Type          ==     y%Vegetation_Type      )       )
  1849     sfc%Water_Temperature = 
zero  1850     sfc%Wind_Speed        = 
zero  1851     sfc%Wind_Direction    = 
zero  1859     CHARACTER(*), 
PARAMETER :: routine_name = 
'CRTM_WaterSurface_IsValid'  1860     CHARACTER(ML) :: msg
  1866     IF ( sfc%Water_Type < 1 ) 
THEN  1867       msg = 
'Invalid Water Surface type'  1871     IF ( sfc%Water_Temperature < 
zero .OR. &
  1872          sfc%Wind_Speed        < 
zero .OR. &
  1873          sfc%Wind_Direction    < 
zero .OR. &
  1874          sfc%Salinity          < 
zero      ) 
THEN  1875       msg = 
'Invalid Water Surface data'  1884     TYPE(CRTM_Surface_type), 
INTENT(IN) :: Sfc
  1885     INTEGER,       
OPTIONAL, 
INTENT(IN) :: Unit
  1888     IF ( 
PRESENT(unit) ) 
THEN  1891     WRITE(fid,
'(3x,"Water Type index :",1x,i0)') sfc%Water_Type
  1892     WRITE(fid,
'(3x,"Water Temperature:",1x,es13.6)') sfc%Water_Temperature
  1893     WRITE(fid,
'(3x,"Wind Speed       :",1x,es13.6)') sfc%Wind_Speed
  1894     WRITE(fid,
'(3x,"Wind Direction   :",1x,es13.6)') sfc%Wind_Direction
  1895     WRITE(fid,
'(3x,"Salinity         :",1x,es13.6)') sfc%Salinity
  1901     INTEGER,       
OPTIONAL, 
INTENT(IN) :: n_sigfig
  1902     LOGICAL :: is_comparable
  1907     is_comparable = .false.
  1908     IF ( 
PRESENT(n_sigfig) ) 
THEN  1915     IF ( x%Water_Type /= y%Water_Type ) 
RETURN  1924     is_comparable = .true.
  1932     is_equal = ( (x%Water_Type           ==     y%Water_Type       ) .AND. &
  1933                  (x%Water_Temperature .equalto. y%Water_Temperature) .AND. &
  1934                  (x%Wind_Speed        .equalto. y%Wind_Speed       ) .AND. &
  1935                  (x%Wind_Direction    .equalto. y%Wind_Direction   ) .AND. &
  1936                  (x%Salinity          .equalto. y%Salinity         )       )
  1946     sfc%Snow_Temperature = 
zero  1947     sfc%Snow_Depth       = 
zero  1948     sfc%Snow_Density     = 
zero  1949     sfc%Snow_Grain_Size  = 
zero  1956     CHARACTER(*), 
PARAMETER :: routine_name = 
'CRTM_SnowSurface_IsValid'  1957     CHARACTER(ML) :: msg
  1963     IF ( sfc%Snow_Type < 1 ) 
THEN  1964       msg = 
'Invalid Snow Surface type'  1968     IF ( sfc%Snow_Temperature < 
zero .OR. &
  1969          sfc%Snow_Depth       < 
zero .OR. &
  1970          sfc%Snow_Density     < 
zero .OR. &
  1971          sfc%Snow_Grain_Size  < 
zero      ) 
THEN  1972       msg = 
'Invalid Snow Surface data'  1981     TYPE(CRTM_Surface_type), 
INTENT(IN) :: Sfc
  1982     INTEGER,       
OPTIONAL, 
INTENT(IN) :: Unit
  1985     IF ( 
PRESENT(unit) ) 
THEN  1988     WRITE(fid,
'(3x,"Snow Type index :",1x,i0)') sfc%Snow_Type
  1989     WRITE(fid,
'(3x,"Snow Temperature:",1x,es13.6)') sfc%Snow_Temperature
  1990     WRITE(fid,
'(3x,"Snow Depth      :",1x,es13.6)') sfc%Snow_Depth
  1991     WRITE(fid,
'(3x,"Snow Density    :",1x,es13.6)') sfc%Snow_Density
  1992     WRITE(fid,
'(3x,"Snow Grain_Size :",1x,es13.6)') sfc%Snow_Grain_Size
  1998     INTEGER,       
OPTIONAL, 
INTENT(IN) :: n_sigfig
  1999     LOGICAL :: is_comparable
  2004     is_comparable = .false.
  2005     IF ( 
PRESENT(n_sigfig) ) 
THEN  2012     IF ( x%Snow_Type /= y%Snow_Type ) 
RETURN  2021     is_comparable = .true.
  2029     is_equal = ( (x%Snow_Type           ==     y%Snow_Type       ) .AND. &
  2030                  (x%Snow_Temperature .equalto. y%Snow_Temperature) .AND. &
  2031                  (x%Snow_Depth       .equalto. y%Snow_Depth      ) .AND. &
  2032                  (x%Snow_Density     .equalto. y%Snow_Density    ) .AND. &
  2033                  (x%Snow_Grain_Size  .equalto. y%Snow_Grain_Size )       )
  2043     sfc%Ice_Temperature = 
zero  2044     sfc%Ice_Thickness   = 
zero  2045     sfc%Ice_Density     = 
zero  2046     sfc%Ice_Roughness   = 
zero  2053     CHARACTER(*), 
PARAMETER :: routine_name = 
'CRTM_IceSurface_IsValid'  2054     CHARACTER(ML) :: msg
  2060     IF ( sfc%Ice_Type < 1 ) 
THEN  2061       msg = 
'Invalid Ice Surface type'  2065     IF ( sfc%Ice_Temperature < 
zero .OR. &
  2066          sfc%Ice_Thickness   < 
zero .OR. &
  2067          sfc%Ice_Density     < 
zero .OR. &
  2068          sfc%Ice_Roughness   < 
zero      ) 
THEN  2069       msg = 
'Invalid Ice Surface data'  2078     TYPE(CRTM_Surface_type), 
INTENT(IN) :: Sfc
  2079     INTEGER,       
OPTIONAL, 
INTENT(IN) :: Unit
  2082     IF ( 
PRESENT(unit) ) 
THEN  2085     WRITE(fid,
'(3x,"Ice Type index :",1x,i0)') sfc%Ice_Type
  2086     WRITE(fid,
'(3x,"Ice Temperature:",1x,es13.6)') sfc%Ice_Temperature
  2087     WRITE(fid,
'(3x,"Ice Thickness  :",1x,es13.6)') sfc%Ice_Thickness
  2088     WRITE(fid,
'(3x,"Ice Density    :",1x,es13.6)') sfc%Ice_Density
  2089     WRITE(fid,
'(3x,"Ice Roughness  :",1x,es13.6)') sfc%Ice_Roughness
  2095     INTEGER,       
OPTIONAL, 
INTENT(IN) :: n_sigfig
  2096     LOGICAL :: is_comparable
  2101     is_comparable = .false.
  2102     IF ( 
PRESENT(n_sigfig) ) 
THEN  2109     IF ( x%Ice_Type /= y%Ice_Type ) 
RETURN  2118     is_comparable = .true.
  2126     is_equal = ( (x%Ice_Type           ==     y%Ice_Type       ) .AND. &
  2127                  (x%Ice_Temperature .equalto. y%Ice_Temperature) .AND. &
  2128                  (x%Ice_Thickness   .equalto. y%Ice_Thickness  ) .AND. &
  2129                  (x%Ice_Density     .equalto. y%Ice_Density    ) .AND. &
  2130                  (x%Ice_Roughness   .equalto. y%Ice_Roughness  )       )
  2145     Quiet      , &  ! Optional input
  2149     INTEGER,                 
INTENT(IN)  :: fid
  2151     LOGICAL,       
OPTIONAL, 
INTENT(IN)  :: quiet
  2152     LOGICAL,       
OPTIONAL, 
INTENT(IN)  :: debug
  2156     CHARACTER(*), 
PARAMETER :: routine_name = 
'CRTM_Surface_ReadFile(Record)'  2158     CHARACTER(ML) :: msg
  2159     CHARACTER(ML) :: io_msg
  2162     INTEGER :: coverage_type
  2163     INTEGER :: n_channels
  2169     IF ( 
PRESENT(quiet) ) noisy = .NOT. quiet
  2171     IF ( 
PRESENT(debug) ) 
THEN  2172       IF ( debug ) noisy = .true.
  2177     READ( fid,iostat=io_stat,iomsg=io_msg ) &
  2179       sfc%Land_Coverage, &
  2180       sfc%Water_Coverage, &
  2181       sfc%Snow_Coverage, &
  2183     IF ( io_stat /= 0 ) 
THEN  2184       msg = 
'Error reading gross surface type data - '//trim(io_msg)
  2189       msg = 
'Invalid surface coverage fraction(s) found'  2194       msg = 
'Coverage surface type, '//&
  2196             ', inconsistent with that specified in file.'  2202     READ( fid,iostat=io_stat,iomsg=io_msg ) sfc%Wind_Speed
  2203     IF ( io_stat /= 0 ) 
THEN  2204       msg = 
'Error reading surface type independent data - '//trim(io_msg)
  2210     READ( fid,iostat=io_stat,iomsg=io_msg ) &
  2212       sfc%Land_Temperature, &
  2213       sfc%Soil_Moisture_Content, &
  2214       sfc%Canopy_Water_Content , &
  2215       sfc%Vegetation_Fraction, &
  2216       sfc%Soil_Temperature, &
  2218     IF ( io_stat /= 0 ) 
THEN  2219       msg = 
'Error reading land surface type data - '//trim(io_msg)
  2225     READ( fid,iostat=io_stat,iomsg=io_msg ) &
  2227       sfc%Water_Temperature, &
  2228       sfc%Wind_Direction, &
  2230     IF ( io_stat /= 0 ) 
THEN  2231       msg = 
'Error reading water surface type data - '//trim(io_msg)
  2237     READ( fid,iostat=io_stat,iomsg=io_msg ) &
  2239       sfc%Snow_Temperature, &
  2243     IF ( io_stat /= 0 ) 
THEN  2244       msg = 
'Error reading snow surface type data - '//trim(io_msg)
  2250     READ( fid,iostat=io_stat,iomsg=io_msg ) &
  2252       sfc%Ice_Temperature, &
  2253       sfc%Ice_Thickness, &
  2256     IF ( io_stat /= 0 ) 
THEN  2257       msg = 
'Error reading ice surface type data - '//trim(io_msg)
  2264     READ( fid,iostat=io_stat,iomsg=io_msg ) n_channels
  2265     IF ( io_stat /= 0 ) 
THEN  2266       msg = 
'Error reading SensorData dimensions - '//trim(io_msg)
  2270     IF ( n_channels > 0 ) 
THEN  2273         msg = 
'Error creating SensorData object.'  2276       READ( fid,iostat=io_stat,iomsg=io_msg ) &
  2277         sfc%SensorData%Sensor_ID       , &
  2278         sfc%SensorData%WMO_Satellite_ID, &
  2279         sfc%SensorData%WMO_Sensor_ID   , &
  2280         sfc%SensorData%Sensor_Channel  , &
  2282       IF ( io_stat /= 0 ) 
THEN  2283         msg = 
'Error reading SensorData  - '//trim(io_msg)
  2292       CLOSE( fid,iostat=io_stat,iomsg=io_msg )
  2294         msg = trim(msg)//
'; Error closing file during error cleanup - '//trim(io_msg)
  2313     Quiet, &  ! Optional input
  2317     INTEGER,                 
INTENT(IN) :: fid
  2319     LOGICAL,       
OPTIONAL, 
INTENT(IN) :: quiet
  2320     LOGICAL,       
OPTIONAL, 
INTENT(IN) :: debug
  2324     CHARACTER(*), 
PARAMETER :: routine_name = 
'CRTM_Surface_WriteFile(Record)'  2326     CHARACTER(ML) :: msg
  2327     CHARACTER(ML) :: io_msg
  2336     IF ( 
PRESENT(quiet) ) noisy = .NOT. quiet
  2338     IF ( 
PRESENT(debug) ) 
THEN  2339       IF ( debug ) noisy = .true.
  2344     WRITE( fid,iostat=io_stat,iomsg=io_msg ) &
  2346       sfc%Land_Coverage, &
  2347       sfc%Water_Coverage, &
  2348       sfc%Snow_Coverage, &
  2350     IF ( io_stat /= 0 ) 
THEN  2351       msg = 
'Error writing gross surface type data - '//trim(io_msg)
  2357     WRITE( fid,iostat=io_stat,iomsg=io_msg ) sfc%Wind_Speed
  2358     IF ( io_stat /= 0 ) 
THEN  2359       msg = 
'Error writing surface type independent data - '//trim(io_msg)
  2365     WRITE( fid,iostat=io_stat,iomsg=io_msg ) &
  2367       sfc%Land_Temperature, &
  2368       sfc%Soil_Moisture_Content, &
  2369       sfc%Canopy_Water_Content, &
  2370       sfc%Vegetation_Fraction, &
  2371       sfc%Soil_Temperature, &
  2373     IF ( io_stat /= 0 ) 
THEN  2374       msg = 
'Error writing land surface type data - '//trim(io_msg)
  2380     WRITE( fid,iostat=io_stat,iomsg=io_msg ) &
  2382       sfc%Water_Temperature, &
  2383       sfc%Wind_Direction, &
  2385     IF ( io_stat /= 0 ) 
THEN  2386       msg = 
'Error writing water surface type data - '//trim(io_msg)
  2392     WRITE( fid,iostat=io_stat,iomsg=io_msg ) &
  2394       sfc%Snow_Temperature, &
  2398     IF ( io_stat /= 0 ) 
THEN  2399       msg = 
'Error writing snow surface type data - '//trim(io_msg)
  2405     WRITE( fid,iostat=io_stat,iomsg=io_msg ) &
  2407       sfc%Ice_Temperature, &
  2408       sfc%Ice_Thickness, &
  2411     IF ( io_stat /= 0 ) 
THEN  2412       msg = 
'Error writing ice surface type data - '//trim(io_msg)
  2419     WRITE( fid,iostat=io_stat,iomsg=io_msg ) sfc%SensorData%n_Channels
  2420     IF ( io_stat /= 0 ) 
THEN  2421       msg = 
'Error writing SensorData dimensions - '//trim(io_msg)
  2425     IF ( sfc%SensorData%n_Channels > 0 ) 
THEN  2426       WRITE( fid,iostat=io_stat,iomsg=io_msg ) &
  2427         sfc%SensorData%Sensor_ID       , &
  2428         sfc%SensorData%WMO_Satellite_ID, &
  2429         sfc%SensorData%WMO_Sensor_ID   , &
  2430         sfc%SensorData%Sensor_Channel  , &
  2432       IF ( io_stat /= 0 ) 
THEN  2433         msg = 
'Error writing SensorData - '//trim(io_msg)
  2443         msg = trim(msg)//
'; Error closing file during error cleanup - '//trim(io_msg)
 logical function crtm_watersurface_isvalid(Sfc)
integer, parameter default_vegetation_type
real(fp), parameter default_vegetation_fraction
elemental subroutine, public crtm_sensordata_create(SensorData, n_Channels)
elemental subroutine crtm_landsurface_zero(Sfc)
integer, parameter, public failure
subroutine, public crtm_surface_inspect(Sfc, Unit)
subroutine, public crtm_sensordata_inspect(SensorData, Unit)
elemental integer function, public crtm_surface_coveragetype(sfc)
integer, parameter, public warning
real(fp), parameter default_snow_temperature
elemental logical function crtm_watersurface_equal(x, y)
real(fp), parameter default_ice_roughness
logical function crtm_icesurface_isvalid(Sfc)
integer, parameter, public fp
elemental logical function, public crtm_sensordata_associated(SensorData)
character(*), parameter module_version_id
integer function, public readgatts_binary_file(fid, Write_Module, Created_On, Title, History, Comment)
elemental logical function crtm_icesurface_equal(x, y)
subroutine crtm_watersurface_inspect(Sfc, Unit)
elemental logical function, public crtm_sensordata_compare(x, y, n_SigFig)
integer, parameter default_land_type
integer function, public crtm_sensordata_writefile(Filename, SensorData, Quiet, No_Close, Debug)
integer function, public crtm_surface_inquirefile(Filename, n_Channels, n_Profiles)
real(fp), parameter default_land_temperature
real(fp), parameter default_snow_grain_size
integer, parameter, public ice_surface
elemental logical function crtm_surface_equal(x, y)
real(fp), parameter default_soil_temperature
real(fp), parameter default_wind_speed
elemental logical function crtm_snowsurface_compare(x, y, n_SigFig)
subroutine inquire_cleanup()
elemental logical function crtm_landsurface_compare(x, y, n_SigFig)
integer function read_record(fid, sfc, Quiet, Debug)
logical function, public crtm_sensordata_isvalid(SensorData)
integer, parameter, public n_valid_surface_types
character(*), dimension(0:n_valid_surface_types), parameter, public surface_type_name
elemental subroutine crtm_watersurface_zero(Sfc)
real(fp), parameter default_ice_temperature
character(*), parameter write_error_status
subroutine read_cleanup()
elemental subroutine, public crtm_sensordata_destroy(SensorData)
integer, parameter, public invalid_surface
subroutine write_cleanup()
real(fp), parameter default_snow_depth
elemental subroutine, public crtm_sensordata_zero(SensorData)
subroutine read_record_cleanup()
elemental logical function crtm_icesurface_compare(x, y, n_SigFig)
elemental subroutine crtm_snowsurface_zero(Sfc)
elemental subroutine, public crtm_surface_destroy(Sfc)
elemental logical function, public crtm_surface_associated(Sfc)
real(fp), parameter default_wind_direction
real(fp), parameter default_soil_moisture_content
integer function, public open_binary_file(Filename, FileID, For_Output, No_Check)
recursive subroutine, public display_message(Routine_Name, Message, Error_State, Message_Log)
real(fp), parameter default_water_temperature
integer, parameter default_soil_type
elemental subroutine crtm_icesurface_zero(Sfc)
logical function, public crtm_surface_iscoveragevalid(Sfc)
elemental subroutine, public crtm_surface_zero(Sfc)
elemental logical function crtm_snowsurface_equal(x, y)
integer, parameter default_water_type
integer, parameter default_ice_type
logical function, public crtm_surface_isvalid(Sfc)
integer function write_surface_rank1(Filename, Surface, Quiet, Debug)
integer, parameter, public land_surface
elemental logical function crtm_watersurface_compare(x, y, n_SigFig)
integer, parameter, public default_n_sigfig
logical function iscoveragevalid(Coverage, Name)
real(fp), parameter default_canopy_water_content
subroutine crtm_snowsurface_inspect(Sfc, Unit)
elemental logical function crtm_landsurface_equal(x, y)
elemental type(crtm_surface_type) function crtm_surface_subtract(sfc1, sfc2)
integer function, public writegatts_binary_file(fid, Write_Module, Created_On, Title, History, Comment)
subroutine, public crtm_sensordata_defineversion(Id)
integer function write_surface_rank2(Filename, Surface, Quiet, Debug)
subroutine write_record_cleanup()
real(fp), parameter default_snow_density
integer function read_surface_rank2(Filename, Surface, Quiet, n_Channels, n_Profiles, Debug)
real(fp), parameter default_ice_density
integer function read_surface_rank1(Filename, Surface, Quiet, n_Channels, n_Profiles, Debug)
integer, parameter default_snow_type
subroutine, public crtm_surface_defineversion(Id)
integer function, public crtm_sensordata_readfile(Filename, SensorData, Quiet, No_Close, n_DataSets, Debug)
logical function crtm_landsurface_isvalid(Sfc)
subroutine crtm_icesurface_inspect(Sfc, Unit)
elemental logical function, public crtm_surface_compare(x, y, n_SigFig)
subroutine crtm_landsurface_inspect(Sfc, Unit)
real(fp), parameter default_ice_thickness
elemental type(crtm_surface_type) function crtm_surface_add(sfc1, sfc2)
logical function crtm_snowsurface_isvalid(Sfc)
real(fp), parameter default_salinity
integer, parameter, public water_surface
elemental subroutine, public crtm_surface_create(Sfc, n_Channels)
real(fp), parameter default_lai
integer, parameter, public success
integer, parameter, public snow_surface
integer, parameter, public information