obsUtil_mod sourceΒΆ

  1module obsUtil_mod
  2  ! MODULE obsUtil_mod (prefix='obsu' category='3. Observation input/output')
  3  !
  4  !:Purpose: Common routines used by burpfiles_mod and sqlitefiles_mod
  5  !
  6  use obsSpaceData_mod
  7  use bufr_mod
  8  use mathPhysConstants_mod
  9  use codePrecision_mod
 10  use codtyp_mod
 11  use obsVariableTransforms_mod
 12  use utilities_mod
 13
 14  implicit none
 15  save
 16  private
 17  public :: obsu_setassflg, obsu_updateSourceVariablesFlag
 18  public :: obsu_computeVertCoordSurfObs, obsu_setGbgpsError, obsu_cvt_obs_instrum
 19  
 20contains
 21
 22  !--------------------------------------------------------------------------
 23  ! obsu_updateSourceVariablesFlag
 24  !--------------------------------------------------------------------------
 25  subroutine obsu_updateSourceVariablesFlag(obsSpaceData)
 26    implicit none
 27
 28    ! Arguments:
 29    type(struct_obs), intent(inout) :: obsSpaceData
 30
 31    ! Locals:
 32    integer          :: transformBufrCode, transformBufrCodeExtra
 33    integer          :: flag, flagExtra, mergedFlag
 34    integer          :: sourceBufrCode, sourceBufrCodeExtra
 35    integer          :: headerIndex, bodyIndexStart, bodyIndexEnd, bodyIndex, bodyIndex2
 36    real(pre_obsReal)   :: level
 37
 38    body : do bodyIndex = 1, obs_numBody(obsSpaceData) 
 39
 40      if (ovt_isTransformedVariable(obs_bodyElem_i(obsSpaceData,OBS_VNM,bodyIndex))) then
 41
 42        ! We have found a transformed variable
 43        transformBufrCode = obs_bodyElem_i(obsSpaceData,OBS_VNM,bodyIndex)
 44
 45        ! We will assign his assimilation flag to its source variable
 46        sourceBufrCode = ovt_getSourceBufrCode(transformBufrCode)
 47
 48        headerIndex      = obs_bodyElem_i(obsSpaceData, OBS_HIND, bodyIndex   )
 49        bodyIndexStart   = obs_headElem_i(obsSpaceData, OBS_RLN , headerIndex )
 50        bodyIndexEnd     = obs_headElem_i(obsSpaceData, OBS_NLV , headerIndex ) + bodyIndexStart - 1
 51        level            = obs_bodyElem_r(obsSpaceData, OBS_PPP , bodyIndex   )
 52        flag             = obs_bodyElem_i(obsSpaceData, OBS_FLG , bodyIndex   )
 53
 54        if (ovt_isWindObs(sourceBufrCode)) then
 55
 56           ! Get the flag of the companion transformed variable
 57          transformBufrCodeExtra = ovt_getDestinationBufrCode(sourceBufrCode, &
 58                                                                   extra_opt=.true.)
 59
 60          flagExtra = -999
 61          do bodyIndex2 = bodyIndexStart, bodyIndexEnd
 62            if ( obs_bodyElem_i(obsSpaceData, OBS_VNM, bodyIndex2 ) == transformBufrCodeExtra .and. &
 63                 obs_bodyElem_r(obsSpaceData, OBS_PPP, bodyIndex2 ) == level ) then
 64              flagExtra = obs_bodyElem_i(obsSpaceData, OBS_FLG , bodyIndex2)
 65            end if
 66          end do
 67
 68          ! Combine flags
 69          if (flagExtra /= -999) then
 70            mergedFlag = ior(flag,flagExtra)
 71          else
 72            call utl_abort('obsu_updateSourceVariablesFlag: could not find the wind companion variable')
 73          end if
 74          
 75          ! Find sourceBufrCode and sourceBufrCodeExtra and update their flag
 76          sourceBufrCodeExtra = ovt_getSourceBufrCode(transformBufrCode,&
 77                                                                      extra_opt=.true.)
 78          do bodyIndex2 = bodyIndexStart, bodyIndexEnd
 79            if ( obs_bodyElem_i(obsSpaceData, OBS_VNM, bodyIndex2 ) == sourceBufrCode .and. &
 80                 obs_bodyElem_r(obsSpaceData, OBS_PPP, bodyIndex2 ) == level ) then
 81              call obs_bodySet_i(obsSpaceData, OBS_FLG, bodyIndex2, mergedFlag ) 
 82            end if
 83            if ( obs_bodyElem_i(obsSpaceData, OBS_VNM, bodyIndex2 ) == sourceBufrCodeExtra .and. &
 84                 obs_bodyElem_r(obsSpaceData, OBS_PPP, bodyIndex2 ) == level ) then
 85              call obs_bodySet_i(obsSpaceData, OBS_FLG, bodyIndex2, mergedFlag ) 
 86            end if
 87          end do
 88          
 89        else
 90          
 91          ! Find sourceBufrCode and update its flag
 92          do bodyIndex2 = bodyIndexStart, bodyIndexEnd
 93            if ( obs_bodyElem_i(obsSpaceData, OBS_VNM, bodyIndex2 ) == sourceBufrCode .and. &
 94                 obs_bodyElem_r(obsSpaceData, OBS_PPP, bodyIndex2 ) == level ) then
 95              call obs_bodySet_i(obsSpaceData, OBS_FLG, bodyIndex2, flag ) 
 96            end if
 97          end do
 98
 99        end if
100        
101      end if
102      
103    end do body
104
105  end subroutine obsu_updateSourceVariablesFlag
106
107  !--------------------------------------------------------------------------
108  ! obsu_setassflg
109  !--------------------------------------------------------------------------
110  subroutine obsu_setassflg(obsSpaceData)
111    !
112    !:Purpose: Set banco quality control bit #12 for all data assimilated
113    !           by current analysis.
114    !
115    implicit none
116
117    ! Argument:
118    type(struct_obs), intent(inout) :: obsSpaceData
119
120    ! Locals:
121    integer :: bodyIndex
122
123    ! Process all data
124    BODY: do bodyIndex = 1, obs_numBody(obsSpaceData)
125
126      if (obs_bodyElem_i(obsSpaceData, OBS_ASS, bodyIndex ) == obs_assimilated ) &
127        call obs_bodySet_i( obsSpaceData, OBS_FLG, bodyIndex, &
128                            ibset( obs_bodyElem_i(obsSpaceData, OBS_FLG,bodyIndex), 12 ))
129    end do BODY
130
131  end subroutine obsu_setassflg
132
133  !--------------------------------------------------------------------------
134  ! surfvcord
135  !--------------------------------------------------------------------------
136  real function surfvcord( varno, codtyp )
137
138    implicit none
139
140    ! Arguments:
141    integer, intent(in) :: varno
142    integer, intent(in) :: codtyp
143
144    ! Locals:
145    character(len=9)  :: family
146
147    family = codtypfam(codtyp)
148    surfvcord = 0.0
149
150    select case(family)
151      case ('synop')
152        select case(varno)
153          case (bufr_neds, bufr_nefs, bufr_neus, bufr_nevs, bufr_gust)
154            surfvcord = 10.0
155          case (bufr_nets, bufr_nees, bufr_ness, bufr_vis, bufr_logVis)
156            surfvcord = 1.5
157        end select
158      case ('ship')
159        select case(varno)
160          case (bufr_neds, bufr_nefs, bufr_neus, bufr_nevs, bufr_gust)
161            surfvcord = 20.0
162          case (bufr_nets, bufr_nees, bufr_ness, bufr_vis, bufr_logVis)
163            surfvcord = 11.5
164        end select
165      case ('upairland')
166        select case(varno)
167          case (bufr_neds, bufr_nefs, bufr_neus, bufr_nevs, bufr_gust)
168            surfvcord = 10.0
169          case (bufr_nets, bufr_ness, bufr_vis, bufr_logVis)
170            surfvcord = 1.5
171        end select
172      case ('upairship')
173        select case(varno)
174          case (bufr_neds, bufr_nefs, bufr_neus, bufr_nevs, bufr_gust)
175            surfvcord = 20.0
176          case (bufr_nets, bufr_ness, bufr_vis, bufr_logVis)
177            surfvcord = 1.5
178        end select
179      case ('scatwinds')
180        select case(varno)
181          case (bufr_neds, bufr_nefs, bufr_neus, bufr_nevs)
182            surfvcord = 10.0
183        end select
184    end select
185
186  end function  surfvcord
187
188  !--------------------------------------------------------------------------
189  ! codtypfam
190  !--------------------------------------------------------------------------
191  function codtypfam(codtyp) result(family)
192    implicit none
193
194    ! Arguments:
195    integer, intent(in) :: codtyp
196    ! Result:
197    character(len=9) :: family
198
199    if (       codtyp == codtyp_get_codtyp('synopnonauto')   .or. codtyp == codtyp_get_codtyp('synopmobil')      &
200       .or.    codtyp == codtyp_get_codtyp('asynopauto') ) then
201       family = 'synop'
202    else if (  codtyp == codtyp_get_codtyp('shipnonauto')    .or. codtyp == codtyp_get_codtyp('drifter')         &
203       .or.    codtyp == codtyp_get_codtyp('synoppatrol')    .or. codtyp == codtyp_get_codtyp('ashipauto') ) then
204       family = 'ship'
205    else if (  codtyp == codtyp_get_codtyp('temppilot')      .or. codtyp == codtyp_get_codtyp('tempsynop')       &
206       .or.    codtyp == codtyp_get_codtyp('pilotsynop')     .or. codtyp == codtyp_get_codtyp('temppilotsynop')  &
207       .or.    codtyp == codtyp_get_codtyp('pilot')          .or. codtyp == codtyp_get_codtyp('pilotmobil')      &
208       .or.    codtyp == codtyp_get_codtyp('temp')           .or. codtyp == codtyp_get_codtyp('tempdrop')        &
209       .or.    codtyp == codtyp_get_codtyp('tempmobil')      .or. codtyp == codtyp_get_codtyp('temppilotmobil')  &
210       .or.    codtyp == codtyp_get_codtyp('tempsynopmobil') .or. codtyp == codtyp_get_codtyp('pilotsynopmobil') &
211       .or.    codtyp == codtyp_get_codtyp('temppilotsynopmobil') ) then
212       family = 'upairland'
213    else if (  codtyp == codtyp_get_codtyp('temppilotship')  .or. codtyp ==codtyp_get_codtyp('tempshipship')     &
214       .or.    codtyp == codtyp_get_codtyp('tempsshipship')  .or. codtyp ==codtyp_get_codtyp('pilotshipship')    &
215       .or.    codtyp == codtyp_get_codtyp('pilotship')      .or. codtyp ==codtyp_get_codtyp('tempship') ) then
216       family = 'upairship'
217    else if (  codtyp == codtyp_get_codtyp('ascat') ) then
218       family = 'scatwinds'
219    else
220       family = 'other'
221    end if
222
223  end function codtypfam
224
225  !--------------------------------------------------------------------------
226  ! obsu_computeVertCoordSurfObs
227  !--------------------------------------------------------------------------
228  subroutine obsu_computeVertCoordSurfObs(obsdat, headerIndexStart, headerIndexEnd )
229    !
230    implicit none
231
232    ! Arguments:
233    type (struct_obs), intent(inout) :: obsdat
234    integer          , intent(in)    :: headerIndexStart
235    integer          , intent(in)    :: headerIndexEnd
236
237    ! Locals:
238    integer  :: bodyIndex, headerIndex, bodyIndexStart, bodyIndexEnd
239    integer  :: varno, codtyp
240    real(4)  :: sfc_vco, elev
241    real(pre_obsReal) :: ppp
242
243    HEADER: do headerIndex = headerIndexStart, headerIndexEnd
244        
245      bodyIndexStart = obs_headElem_i(obsdat, OBS_RLN, headerIndex )
246      bodyIndexEnd   = obs_headElem_i(obsdat, OBS_NLV, headerIndex ) + bodyIndexStart - 1
247      codtyp = obs_headElem_i(obsdat, OBS_ITY, headerIndex )
248      elev = obs_headElem_r(obsdat, OBS_ALT, headerIndex )
249
250      BODY: do bodyIndex = bodyIndexStart, bodyIndexEnd
251        varno = obs_bodyElem_i(obsdat, OBS_VNM, bodyIndex )
252
253        select case(varno)
254          case(bufr_neds, bufr_nefs, bufr_neus, bufr_nevs, bufr_nets, bufr_ness, bufr_nepn, bufr_neps, bufr_nehs, &
255               bufr_nezd, bufr_vis, bufr_logVis, bufr_gust )
256            sfc_vco = surfvcord(varno, codtyp )
257            if ( varno /= bufr_nepn) then
258              ppp = elev + sfc_vco
259              call obs_bodySet_r(obsdat, OBS_PPP, bodyIndex, ppp )
260              call obs_bodySet_i(obsdat, OBS_VCO, bodyIndex, 1 )
261            else
262              ppp = 0.
263              call obs_bodySet_r(obsdat,OBS_PPP, bodyIndex, ppp )
264              call obs_bodySet_i(obsdat,OBS_VCO, bodyIndex, 1 )
265            end if
266        end select
267
268      end do BODY
269
270    end do HEADER
271
272  end subroutine obsu_computeVertCoordSurfObs
273
274  !--------------------------------------------------------------------------
275  ! obsu_setGbgpsError
276  !--------------------------------------------------------------------------
277  subroutine obsu_setGbgpsError(obsdat, headerIndexStart, headerIndexEnd )
278    !
279    implicit none
280
281    ! Arguments:
282    type (struct_obs), intent(inout) :: obsdat
283    integer          , intent(in)    :: headerIndexStart
284    integer          , intent(in)    :: headerIndexEnd
285
286    ! Locals:
287    real(pre_obsReal)    :: obsv
288    integer  :: bodyIndex, headerIndex,bodyIndexStart, bodyIndexEnd
289    integer  :: varno
290
291    HEADER: do headerIndex = headerIndexStart, headerIndexEnd
292 
293      bodyIndexStart = obs_headElem_i(obsdat, OBS_RLN, headerIndex )
294      bodyIndexEnd   = obs_headElem_i(obsdat, OBS_NLV, headerIndex ) + bodyIndexStart - 1
295      obsv = real(MPC_missingValue_R8, pre_obsReal)
296      
297      BODY: do bodyIndex = bodyIndexStart, bodyIndexEnd 
298
299        varno = obs_bodyElem_i(obsdat,OBS_VNM,bodyIndex )
300
301        if ( varno == bufr_nefe ) then
302          obsv = obs_bodyElem_r(obsdat,OBS_VAR, bodyIndex )
303          call obs_bodySet_i(obsdat, OBS_VNM, bodyIndex, 999 )
304          exit BODY
305        end if
306
307      end do BODY
308
309      BODY2: do bodyIndex = bodyIndexStart, bodyIndexEnd
310
311        varno = obs_bodyElem_i(obsdat, OBS_VNM, bodyIndex )
312
313        if ( varno == bufr_nezd .and. obsv /= real(MPC_missingValue_R8, pre_obsReal)) then
314          call obs_bodySet_r(obsdat, OBS_OER, bodyIndex, obsv )
315          exit BODY2
316        end if
317
318      end do BODY2
319
320    end do HEADER
321
322  end subroutine obsu_setGbgpsError
323
324  !--------------------------------------------------------------------------
325  ! obsu_cvt_obs_instrum
326  !--------------------------------------------------------------------------
327  integer function obsu_cvt_obs_instrum(sensor)
328    !
329    !:Purpose: Map burp satellite sensor indicator (element #2048) to
330    !           burp satellite instrument (element #2019). This is a more
331    !           complete common element, allowing for future expansion.
332    !
333    !:Table of BURP satellite sensor indicator element #002048:
334    ! ==================  =============================== 
335    ! Satellite sensor    BURP satellite sensor indicator
336    ! ==================  =============================== 
337    !               HIRS                 0
338    !                MSU                 1
339    !                SSU                 2
340    !              AMSUA                 3
341    !              AMSUB                 4
342    !              AVHRR                 5
343    !               SSMI                 6
344    !              NSCAT                 7
345    !           SEAWINDS                 8
346    !           Reserved                9-14
347    !      Missing value                15
348    ! ==================  =============================== 
349    !
350    implicit none
351
352    ! Arguments:
353    integer, intent(in) :: sensor      ! BURP satellite sensor indicator (element #2048)
354
355    ! Locals:
356    integer :: instrument  ! BURP satellite instrument       (element #2019)
357
358    select case (sensor)
359      case (000);   instrument = 606  ! HIRS
360      case (001);   instrument = 623  ! MSU
361      case (002);   instrument = 627  ! SSU
362      case (003);   instrument = 570  ! AMSUA
363      case (004);   instrument = 574  ! AMSUB
364      case (005);   instrument = 591  ! AVHRR
365      case (006);   instrument = 905  ! SSMI
366      case (007);   instrument = 312  ! NSCAT
367      case (008);   instrument = 313  ! SEAWINDS
368      case (015);   instrument = 2047 ! Missing value
369      case default; instrument = 2047 ! Unrecognized value
370    end select
371
372    obsu_cvt_obs_instrum = instrument
373
374  end function obsu_cvt_obs_instrum
375
376end module obsUtil_mod