*IF DEF,FLUXPROC                                                           FPRD1FLD.2      
C ******************************COPYRIGHT******************************    FPRD1FLD.3      
C (c) CROWN COPYRIGHT 1998, METEOROLOGICAL OFFICE, All Rights Reserved.    FPRD1FLD.4      
C                                                                          FPRD1FLD.5      
C Use, duplication or disclosure of this code is subject to the            FPRD1FLD.6      
C restrictions as set forth in the contract.                               FPRD1FLD.7      
C                                                                          FPRD1FLD.8      
C                Meteorological Office                                     FPRD1FLD.9      
C                London Road                                               FPRD1FLD.10     
C                BRACKNELL                                                 FPRD1FLD.11     
C                Berkshire UK                                              FPRD1FLD.12     
C                RG12 2SZ                                                  FPRD1FLD.13     
C                                                                          FPRD1FLD.14     
C If no contract has been raised with this copy of the code, the use,      FPRD1FLD.15     
C duplication or disclosure of it is strictly prohibited.  Permission      FPRD1FLD.16     
C to do so must first be obtained in writing from the Head of Numerical    FPRD1FLD.17     
C Modelling at the above address.                                          FPRD1FLD.18     
C ******************************COPYRIGHT******************************    FPRD1FLD.19     
C                                                                          FPRD1FLD.20     
C Programming standard: Unified Model Documentation Paper No 3             FPRD1FLD.21     
C                       Version No 1 15/1/90                               FPRD1FLD.22     
C History:                                                                 FPRD1FLD.23     
C version  date         change                                             FPRD1FLD.24     
C 4.5      03/09/98     New code                                           FPRD1FLD.25     
C                                                                          FPRD1FLD.26     
! Author:     M. J. Bell                                                   FPRD1FLD.27     
!----------------------------------------------------------------------    FPRD1FLD.28     
! contains routines: read_one_field                                        FPRD1FLD.29     
!                                                                          FPRD1FLD.30     
! Purpose: Flux processing routine.                                        FPRD1FLD.31     
!          Selects a field from input data files and returns               FPRD1FLD.32     
!          data (in array field) and lookup table in PP_Int and PP_Real    FPRD1FLD.33     
!                                                                          FPRD1FLD.34     
! Uses:    readflds and coex                                               FPRD1FLD.35     
!                                                                          FPRD1FLD.36     
! also transfers bmks scale and offset from pp header to data field        FPRD1FLD.37     
!      outputs debugging information on field read in                      FPRD1FLD.38     
!----------------------------------------------------------------------    FPRD1FLD.39     

      subroutine read_one_field ( InUnit, item, itemvalue,                  16,8FPRD1FLD.40     
*CALL AVALTIM                                                              FPRD1FLD.41     
     #               Len_FixHd, FixHd, Len1_Lookup,                        FPRD1FLD.42     
     #               Len2_Lookup, Lookup, LookFldNo,                       FPRD1FLD.43     
     #               ldebug, l_climate_field,                              FPRD1FLD.44     
     #               Len_IntHd, Len_RealHd, IntHead, RealHead,             FPRD1FLD.45     
     #               ncols, nrows, field,                                  FPRD1FLD.46     
*CALL ARGPPX                                                               FPRD1FLD.47     
     #               icode)                                                FPRD1FLD.48     
                                                                           FPRD1FLD.49     
      implicit none                                                        FPRD1FLD.50     
                                                                           FPRD1FLD.51     
! declaration of parameters                                                FPRD1FLD.52     
*CALL CLOOKADD                                                             FPRD1FLD.53     
*CALL C_MDI                                                                FPRD1FLD.54     
                                                                           FPRD1FLD.55     
! Local parameters:                                                        FPRD1FLD.56     
      integer len_full_word   ! The length of a FULL_WORD                  FPRD1FLD.57     
      parameter ( len_full_word = 64 )                                     FPRD1FLD.58     
                                                                           FPRD1FLD.59     
! declaration of argument list                                             FPRD1FLD.60     
                                                                           FPRD1FLD.61     
! search conditions (all intent IN)                                        FPRD1FLD.62     
      integer InUnit    ! IN    unit number for input                      FPRD1FLD.63     
      integer item      ! IN    lookup header item to test                 FPRD1FLD.64     
      integer itemvalue ! IN    value to look for                          FPRD1FLD.65     
                                                                           FPRD1FLD.66     
! validity time to look for: intent IN                                     FPRD1FLD.67     
*CALL CVALTIM                                                              FPRD1FLD.68     
                                                                           FPRD1FLD.69     
! fixed headers and lookup tables to use: all intent IN                    FPRD1FLD.70     
      integer Len_FixHd                    ! length of fixed header        FPRD1FLD.71     
      integer FixHd(Len_FixHd)             ! fixed header                  FPRD1FLD.72     
      integer Len1_Lookup, Len2_Lookup     ! true lengths of tables        FPRD1FLD.73     
      integer Lookup(Len1_Lookup, Len2_Lookup)  ! lookup tables            FPRD1FLD.74     
      integer LookFldNo(Len2_Lookup)       ! field nos for lookups         FPRD1FLD.75     
                                                                           FPRD1FLD.76     
! control logical for debugging output                                     FPRD1FLD.77     
      logical ldebug          ! IN T => output debugging info              FPRD1FLD.78     
      logical l_climate_field ! IN T => trying to read climate field       FPRD1FLD.79     
                              !    F => trying to read NWP field           FPRD1FLD.80     
                                                                           FPRD1FLD.81     
! lengths of Lookup table                                                  FPRD1FLD.82     
      integer Len_IntHd         ! IN   length of integer part of lookup    FPRD1FLD.83     
      integer Len_RealHd        ! IN   length of real part of lookup       FPRD1FLD.84     
                                                                           FPRD1FLD.85     
! lookup tables of field found                                             FPRD1FLD.86     
      integer IntHead(Len_IntHd) ! OUT integer part                        FPRD1FLD.87     
      real RealHead(Len_RealHd)                                            FPRD1FLD.88     
! OUT real part                                                            FPRD1FLD.89     
                                                                           FPRD1FLD.90     
! output field                                                             FPRD1FLD.91     
      integer ncols             ! IN  number of columns                    FPRD1FLD.92     
      integer nrows             ! IN  number of rows                       FPRD1FLD.93     
      real field(ncols,nrows)   ! OUT field values                         FPRD1FLD.94     
      integer icode  ! IN/OUT error code ; > 0 => fatal error detected     FPRD1FLD.95     
                                                                           FPRD1FLD.96     
! declaration of globals used                                              FPRD1FLD.97     
*CALL CSUBMODL                                                             FPRD1FLD.98     
*CALL CPPXREF                                                              FPRD1FLD.99     
*CALL PPXLOOK                                                              FPRD1FLD.100    
*CALL CUNITNOS                                                             FPRD1FLD.101    
*CALL CMESS                                                                FPRD1FLD.102    
*CALL CDEBUG                                                               FPRD1FLD.103    
                                                                           FPRD1FLD.104    
! declaration of local arrays                                              FPRD1FLD.105    
      integer field_wgdos_packed(ncols*nrows)  ! wgdos packed field        FPRD1FLD.106    
                                                                           FPRD1FLD.107    
! declaration of local scalars                                             FPRD1FLD.108    
      integer fld_no      ! number of field matching search conditions     FPRD1FLD.109    
      integer i           ! do loop index                                  FPRD1FLD.110    
      integer nvalues     ! # values in wgdos packed field                 FPRD1FLD.111    
      integer idum        ! dummy integer                                  FPRD1FLD.112    
      integer ixx         ! # of columns in grid according to coex         FPRD1FLD.113    
      integer iyy         ! # of rows in grid according to coex            FPRD1FLD.114    
      logical ItemFound   ! T => item to search for has been found         FPRD1FLD.115    
      logical l_data_time ! T => use data time; F => use validity time     FPRD1FLD.116    
                                                                           FPRD1FLD.117    
      real offset         ! offset of data from zero                       FPRD1FLD.118    
      real scale          ! MKS scaling factor                             FPRD1FLD.119    
      real rmdit          ! rmdi read in from file                         FPRD1FLD.120    
                                                                           FPRD1FLD.121    
      character *256 cmessage  ! error message                             FPRD1FLD.122    
                                                                           FPRD1FLD.123    
      external time_to_use, readflds, copy_to_real, scalarmult,            FPRD1FLD.124    
     #         scalaradd,output_debug                                      FPRD1FLD.125    
                                                                           FPRD1FLD.126    
!----------------------------------------------------------------------    FPRD1FLD.127    
                                                                           FPRD1FLD.128    
!----------------------------------------------------------------------    FPRD1FLD.129    
! 0. Preliminaries                                                         FPRD1FLD.130    
      CSub = 'read_one_field'  ! subroutine name for error messages        FPRD1FLD.131    
      idum = 0                 ! dummy integer used in call coex           FPRD1FLD.132    
                                                                           FPRD1FLD.133    
! 1. Decide whether to search lookups using validity or data time          FPRD1FLD.134    
                                                                           FPRD1FLD.135    
      call time_to_use ( itemvalue, l_climate_field, l_data_time)          FPRD1FLD.136    
                                                                           FPRD1FLD.137    
! 2. Search lookup tables for match on date and stash item                 FPRD1FLD.138    
                                                                           FPRD1FLD.139    
! 2.1 search lookup tables using data time                                 FPRD1FLD.140    
                                                                           FPRD1FLD.141    
      ItemFound = .false.                                                  FPRD1FLD.142    
                                                                           FPRD1FLD.143    
      if ( l_data_time ) then                                              FPRD1FLD.144    
                                                                           FPRD1FLD.145    
        do i = 1, Len2_Lookup                                              FPRD1FLD.146    
          if ( Lookup(LBYRD,i)  .eq. ValidYear   .and.                     FPRD1FLD.147    
     #       Lookup(LBMOND,i) .eq. ValidMonth  .and.                       FPRD1FLD.148    
     #       Lookup(LBDATD,i) .eq. ValidDay    .and.                       FPRD1FLD.149    
     #       Lookup(LBHRD,i)  .eq. ValidHour   .and.                       FPRD1FLD.150    
     #       Lookup(LBMIND,i) .eq. ValidMin    .and.                       FPRD1FLD.151    
     #       Lookup(item,i)  .eq. itemvalue ) then                         FPRD1FLD.152    
            ItemFound = .true.                                             FPRD1FLD.153    
            fld_no = LookFldNo(i)                                          FPRD1FLD.154    
            go to 100                                                      FPRD1FLD.155    
          end if                                                           FPRD1FLD.156    
        end do                                                             FPRD1FLD.157    
                                                                           FPRD1FLD.158    
! 2.2 Search lookup tables using validity time                             FPRD1FLD.159    
      else   !  .not. l_data_time                                          FPRD1FLD.160    
                                                                           FPRD1FLD.161    
        do i = 1, Len2_Lookup                                              FPRD1FLD.162    
          if ( Lookup(LBYR,i)  .eq. ValidYear   .and.                      FPRD1FLD.163    
     #       Lookup(LBMON,i) .eq. ValidMonth  .and.                        FPRD1FLD.164    
     #       Lookup(LBDAT,i) .eq. ValidDay    .and.                        FPRD1FLD.165    
     #       Lookup(LBHR,i)  .eq. ValidHour   .and.                        FPRD1FLD.166    
     #       Lookup(LBMIN,i) .eq. ValidMin    .and.                        FPRD1FLD.167    
     #       Lookup(item,i)  .eq. itemvalue ) then                         FPRD1FLD.168    
            ItemFound = .true.                                             FPRD1FLD.169    
            fld_no = LookFldNo(i)                                          FPRD1FLD.170    
            go to 100                                                      FPRD1FLD.171    
          end if                                                           FPRD1FLD.172    
        end do                                                             FPRD1FLD.173    
                                                                           FPRD1FLD.174    
      endif   !  l_data_time                                               FPRD1FLD.175    
                                                                           FPRD1FLD.176    
100   continue                                                             FPRD1FLD.177    
                                                                           FPRD1FLD.178    
! if item has not been found set icode > 0 and exit routine                FPRD1FLD.179    
                                                                           FPRD1FLD.180    
      if ( .not. ItemFound ) then                                          FPRD1FLD.181    
        icode = 36                                                         FPRD1FLD.182    
        write(UnWarn,*)CWarn,CSub,                                         FPRD1FLD.183    
     #       ' step 2. unable to find required field '                     FPRD1FLD.184    
        go to 9999                                                         FPRD1FLD.185    
      end if                                                               FPRD1FLD.186    
                                                                           FPRD1FLD.187    
                                                                           FPRD1FLD.188    
! 3. check that nrows and ncols agree with those in lookup table           FPRD1FLD.189    
                                                                           FPRD1FLD.190    
      if ( Lookup(LBNPT,fld_no) .ne. ncols  ) then                         FPRD1FLD.191    
        icode = 37                                                         FPRD1FLD.192    
        write(UnWarn,*)CWarn,CSub,'3.1 number of columns do ',             FPRD1FLD.193    
     #  'not agree: ' ,ncols, Lookup(LBNPT,fld_no)                         FPRD1FLD.194    
        go to 9999                                                         FPRD1FLD.195    
       end if                                                              FPRD1FLD.196    
                                                                           FPRD1FLD.197    
      if ( Lookup(LBROW,fld_no) .ne. nrows  ) then                         FPRD1FLD.198    
        icode = 38                                                         FPRD1FLD.199    
        write(UnWarn,*)CWarn,CSub,'3.2 number of rows do ',                FPRD1FLD.200    
     #  'not agree: ' ,nrows, Lookup(LBROW,fld_no)                         FPRD1FLD.201    
        go to 9999                                                         FPRD1FLD.202    
      end if                                                               FPRD1FLD.203    
                                                                           FPRD1FLD.204    
! 4. If found: Use READFIELDS to extract field                             FPRD1FLD.205    
                                                                           FPRD1FLD.206    
! 4.1 extract field which is wgdos packed                                  FPRD1FLD.207    
                                                                           FPRD1FLD.208    
      if ( MOD ( Lookup(LBPACK,fld_no) ,10) .eq. 1) then                   FPRD1FLD.209    
                                                                           FPRD1FLD.210    
        nvalues = Lookup(LBLREC,fld_no)                                    FPRD1FLD.211    
                                                                           FPRD1FLD.212    
        call readflds (InUnit , 1, fld_no, LOOKUP,                         FPRD1FLD.213    
     #      Len1_Lookup, field_wgdos_packed, nvalues, FIXHD,               FPRD1FLD.214    
*CALL ARGPPX                                                               FPRD1FLD.215    
     #      icode, cmessage)                                               FPRD1FLD.216    
                                                                           FPRD1FLD.217    
        if ( icode .gt. 0 ) then                                           FPRD1FLD.218    
          write(UnWarn,*)CWarn,CSub,                                       FPRD1FLD.219    
     #       ' step 4.1 unable to read field: cmessage is ',               FPRD1FLD.220    
     #       cmessage                                                      FPRD1FLD.221    
          icode = 39                                                       FPRD1FLD.222    
          go to 9999                                                       FPRD1FLD.223    
        end if                                                             FPRD1FLD.224    
                                                                           FPRD1FLD.225    
        call coex(field,               ! OUT unpacked field                FPRD1FLD.226    
     &            nrows*ncols,         ! IN  size of unpacked field        FPRD1FLD.227    
     &            field_wgdos_packed,  ! IN  packed field                  FPRD1FLD.228    
     &            nvalues,             ! IN  size of packed field          FPRD1FLD.229    
     &            ixx,iyy,             ! OUT row and column sizes          FPRD1FLD.230    
     &            idum,idum,           ! IN  not used                      FPRD1FLD.231    
     &            .false.,             ! IN  => expansion                  FPRD1FLD.232    
     &            rmdi,                ! IN  real missing data value       FPRD1FLD.233    
     &            len_full_word)       ! IN  length of a full word         FPRD1FLD.234    
                                                                           FPRD1FLD.235    
        if ( ixx .ne. ncols  .or. iyy .ne. nrows ) then                    FPRD1FLD.236    
          icode = 40                                                       FPRD1FLD.237    
          write(UnWarn,*)CWarn,CSub,                                       FPRD1FLD.238    
     #       ' step 4.1 number of rows and columns garbled ?  ',           FPRD1FLD.239    
     #       ixx, ncols, iyy, nrows                                        FPRD1FLD.240    
          go to 9999                                                       FPRD1FLD.241    
        end if                                                             FPRD1FLD.242    
                                                                           FPRD1FLD.243    
! 4.2 or extract field which is not packed                                 FPRD1FLD.244    
                                                                           FPRD1FLD.245    
      else                                                                 FPRD1FLD.246    
                                                                           FPRD1FLD.247    
        if ( Lookup(LBLREC,fld_no) .ne. ncols*nrows) then                  FPRD1FLD.248    
           icode = 41                                                      FPRD1FLD.249    
           write(UnWarn,*)CWarn,CSub,                                      FPRD1FLD.250    
     #     ' step 4.2 wrong number of data points in field ',              FPRD1FLD.251    
     #     Lookup(LBLREC,fld_no), ncols*nrows, ncols, nrows                FPRD1FLD.252    
           go to 9999                                                      FPRD1FLD.253    
        end if                                                             FPRD1FLD.254    
                                                                           FPRD1FLD.255    
        call readflds (InUnit , 1, fld_no, LOOKUP,                         FPRD1FLD.256    
     #      Len1_Lookup, Field, ncols*nrows, FIXHD,                        FPRD1FLD.257    
*CALL ARGPPX                                                               FPRD1FLD.258    
     #      icode, cmessage)                                               FPRD1FLD.259    
                                                                           FPRD1FLD.260    
        if ( icode .gt. 0 ) then                                           FPRD1FLD.261    
          write(UnWarn,*)CWarn,CSub,                                       FPRD1FLD.262    
     #       ' step 4.2 unable to read field: cmessage is ',               FPRD1FLD.263    
     #       cmessage                                                      FPRD1FLD.264    
          icode = 42                                                       FPRD1FLD.265    
          go to 9999                                                       FPRD1FLD.266    
        end if                                                             FPRD1FLD.267    
                                                                           FPRD1FLD.268    
      end if ! Lookup(LBPACK,fld_no)                                       FPRD1FLD.269    
                                                                           FPRD1FLD.270    
! 5.  convert lookup table to Int_Head and Real_Head                       FPRD1FLD.271    
!     and field to a 2D field                                              FPRD1FLD.272    
                                                                           FPRD1FLD.273    
      do i = 1, Len_IntHd                                                  FPRD1FLD.274    
        IntHead(i) = Lookup(i,fld_no)                                      FPRD1FLD.275    
      end do                                                               FPRD1FLD.276    
                                                                           FPRD1FLD.277    
      do i = Len_IntHd+1, Len_IntHd+Len_RealHd                             FPRD1FLD.278    
        call copy_to_real( Lookup(i,fld_no),                               FPRD1FLD.279    
     #                        RealHead(i-Len_IntHd) )                      FPRD1FLD.280    
      end do                                                               FPRD1FLD.281    
                                                                           FPRD1FLD.282    
! 6.  correct data offset and change to SI units                           FPRD1FLD.283    
      rmdit = RealHead(BMDI   - Len_IntHd)                                 FPRD1FLD.284    
                                                                           FPRD1FLD.285    
      if ( rmdit .ne. rmdi ) then                                          FPRD1FLD.286    
        icode = 43                                                         FPRD1FLD.287    
        write(UnWarn,*)CWarn,CSub,                                         FPRD1FLD.288    
     #       ' step 6.1 real missing data indicators do not match: ',      FPRD1FLD.289    
     #       rmdit, rmdi                                                   FPRD1FLD.290    
        go to 9999                                                         FPRD1FLD.291    
      end if                                                               FPRD1FLD.292    
                                                                           FPRD1FLD.293    
      offset = RealHead(BDATUM - Len_IntHd)                                FPRD1FLD.294    
      if ( offset .ne. rmdi .and. offset .ne. 0.0 ) then                   FPRD1FLD.295    
        call ScalarAdd(ncols, nrows, rmdi, offset,                         FPRD1FLD.296    
     #                 Field, Field, icode, cmessage)                      FPRD1FLD.297    
        RealHead(BDATUM - Len_IntHd) = rmdi                                FPRD1FLD.298    
                                                                           FPRD1FLD.299    
        write(UnWarn,*)CWarn,CSub,                                         FPRD1FLD.300    
     #       ' step 6.2 adding offset factor  ', offset                    FPRD1FLD.301    
                                                                           FPRD1FLD.302    
      end if                                                               FPRD1FLD.303    
                                                                           FPRD1FLD.304    
      scale = RealHead(BMKS - Len_IntHd)                                   FPRD1FLD.305    
      if ( scale .ne. rmdi .and. scale .ne. 1.0 ) then                     FPRD1FLD.306    
        call ScalarMult(ncols, nrows, rmdi, scale,                         FPRD1FLD.307    
     #                 Field, Field, icode, cmessage)                      FPRD1FLD.308    
        RealHead(BMKS - Len_IntHd) = rmdi                                  FPRD1FLD.309    
                                                                           FPRD1FLD.310    
        write(UnWarn,*)CWarn,CSub,                                         FPRD1FLD.311    
     #       ' step 6.3 multiplying by factor  ', scale                    FPRD1FLD.312    
                                                                           FPRD1FLD.313    
      end if                                                               FPRD1FLD.314    
                                                                           FPRD1FLD.315    
! 7.  output debug info                                                    FPRD1FLD.316    
      if (ldebug) then                                                     FPRD1FLD.317    
        write(OutUnitDbg,*) ' read_data: unit ', InUnit,'; item ',         FPRD1FLD.318    
     #    '; itemvalue ', itemvalue                                        FPRD1FLD.319    
        CMessage = ' '                                                     FPRD1FLD.320    
        call  output_debug(CMessage, nrows, ncols, Field)                  FPRD1FLD.321    
      end if                                                               FPRD1FLD.322    
                                                                           FPRD1FLD.323    
9999  continue                                                             FPRD1FLD.324    
      return                                                               FPRD1FLD.325    
      end                                                                  FPRD1FLD.326    
!----------------------------------------------------------------------    FPRD1FLD.327    
*ENDIF                                                                     FPRD1FLD.328