m_read_CERSAT_data.F90 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. module m_read_CERSAT_data
  2. contains
  3. subroutine read_CERSAT_data(driftfile, gr, data, numdata, var)
  4. use nfw_mod
  5. use mod_measurement
  6. use mod_grid
  7. use m_spherdist
  8. implicit none
  9. character(*), intent(in) :: driftfile
  10. integer, intent(in) :: numdata
  11. type(measurement), dimension(numdata) :: data
  12. type(grid), intent(in) :: gr
  13. real, intent(in) :: var
  14. integer :: dimids(2)
  15. integer , dimension(2) :: dimsizes
  16. integer :: lon_id, lat_id, zon_id, mer_id, qua_id
  17. real, dimension(:,:), allocatable :: drlon, drlat, drmer, drzon
  18. integer, dimension(:,:), allocatable :: qflag
  19. integer :: ncid, varid
  20. real, dimension(1) :: scalefac, fillval, addoffset
  21. integer :: i,j,k,icomp
  22. integer :: drnx, drny
  23. logical :: valid
  24. integer :: tmpint, bit(0:8)
  25. ! Get dimensions of drift file
  26. call nfw_open(driftfile, nf_nowrite, ncid)
  27. call nfw_inq_varid(driftfile, ncid, 'zonal_motion', varid)
  28. call nfw_inq_vardimid(driftfile, ncid, varid, dimids)
  29. do i = 1, 2
  30. call nfw_inq_dimlen(driftfile, ncid, dimids(i), dimsizes(i))
  31. end do
  32. if (gr % reg) then
  33. print *,'NB: CERSAT data should be specified as irregular !'
  34. print *,' Currently it is set as regular..'
  35. print *,'(read_CERSAT_data)'
  36. call exit(1)
  37. end if
  38. ! Which should match numdata dimension
  39. ! NB !!! Mult by 2 for two vector components
  40. if (2 * dimsizes(1) * dimsizes(2) /= numdata .or. &
  41. gr % nx /= dimsizes(1) * dimsizes(2) * 2) then
  42. print *,'Different dimensions - data file and specified'
  43. print *,'dimsizes(1)=',dimsizes(1)
  44. print *,'dimsizes(2)=',dimsizes(2)
  45. print *,'nx =',gr%nx
  46. print *,'(read_CERSAT_data)'
  47. call exit(1)
  48. end if
  49. ! Read data from drift file
  50. drnx=dimsizes(1)
  51. drny=dimsizes(2)
  52. allocate(drlon(drnx,drny))
  53. allocate(drlat(drnx,drny))
  54. allocate(drmer(drnx,drny))
  55. allocate(drzon(drnx,drny))
  56. allocate(qflag(drnx,drny))
  57. call nfw_inq_varid(driftfile, ncid, 'longitude', lon_id)
  58. !call nfw_get_var_double(driftfile, ncid, lon_id, drlon)
  59. call cersat_readfield(driftfile, ncid, lon_id, drlon, drnx * drny)
  60. call nfw_inq_varid(driftfile, ncid, 'latitude', lat_id)
  61. !call nfw_get_var_double(driftfile, ncid, lat_id, drlat)
  62. call cersat_readfield(driftfile, ncid, lat_id, drlat, drnx * drny)
  63. call nfw_inq_varid(driftfile, ncid, 'zonal_motion', zon_id)
  64. !call nfw_get_var_double(driftfile, ncid, zon_id, drzon)
  65. call cersat_readfield(driftfile, ncid, zon_id, drzon, drnx * drny)
  66. call nfw_inq_varid(driftfile, ncid, 'meridional_motion', mer_id)
  67. !call nfw_get_var_double(driftfile, ncid, mer_id, drmer)
  68. call cersat_readfield(driftfile, ncid, mer_id, drmer, drnx * drny)
  69. call nfw_get_att_double(driftfile, ncid, zon_id, '_FillValue', fillval)
  70. call nfw_get_att_double(driftfile, ncid, zon_id, 'scale_factor', scalefac)
  71. call nfw_get_att_double(driftfile, ncid, zon_id, 'add_offset', addoffset)
  72. where (abs(drzon - (fillval(1) * scalefac(1) + addoffset(1))) <&
  73. 1e-4 * fillval(1) * scalefac(1) + addoffset(1))
  74. drzon = gr % undef
  75. end where
  76. call nfw_get_att_double(driftfile, ncid, mer_id, '_FillValue', fillval)
  77. call nfw_get_att_double(driftfile, ncid, mer_id, 'scale_factor', scalefac)
  78. call nfw_get_att_double(driftfile, ncid, mer_id, 'add_offset', addoffset)
  79. ! Flag zonal motion for fill values
  80. where (abs(drmer - (fillval(1) * scalefac(1) + addoffset(1))) <&
  81. 1e-4 * fillval(1) * scalefac(1) + addoffset(1))
  82. drmer = gr % undef
  83. end where
  84. call nfw_inq_varid(driftfile, ncid, 'quality_flag', qua_id)
  85. call nfw_get_var_int(driftfile, ncid, qua_id, qflag)
  86. call nfw_close(driftfile, ncid)
  87. k = 0
  88. do icomp = 1, 2
  89. do j = 1, drny ! gr%ny
  90. do i = 1, drnx ! gr%nx
  91. k = k + 1
  92. ! Qualit flag bits - may be signed
  93. tmpint = qflag(i,j)
  94. bit(7) = tmpint/128; tmpint = tmpint - bit(7)*128 ! Not used
  95. bit(6) = tmpint/ 64; tmpint = tmpint - bit(6)* 64 ! Validated using all available info
  96. bit(5) = tmpint/ 32; tmpint = tmpint - bit(5)* 32 ! Validated using local consistency
  97. bit(4) = tmpint/ 16; tmpint = tmpint - bit(4)* 16 ! Cost function used
  98. bit(3) = tmpint/ 8; tmpint = tmpint - bit(3)* 8 ! Two identical drift vectors
  99. bit(2) = tmpint/ 4; tmpint = tmpint - bit(2)* 4 ! SSMI V selected
  100. bit(1) = tmpint/ 2; tmpint = tmpint - bit(1)* 2 ! SSMI H used
  101. bit(0) = tmpint/ 1; tmpint = tmpint - bit(0)* 1 ! Quickscat used
  102. valid = qflag(i,j) < 127 ! Intermediate solution until I figure out the byte stuff
  103. if (icomp==1) then
  104. data(k)%id = 'VICE'
  105. data(k)%d = drmer(i,j)*.001 ! Convert to km
  106. valid = valid .and. abs( (drmer(i,j)-gr%undef) / gr%undef) > 1e-4
  107. else
  108. data(k)%id = 'UICE'
  109. data(k)%d = drzon(i,j)*.001 ! Convert to km
  110. valid = valid .and. abs( (drzon(i,j)-gr%undef) / gr%undef) > 1e-4
  111. end if
  112. if (.not.valid) then
  113. data(k)%d = gr%undef
  114. end if
  115. data(k)%ipiv = i ! Not really used for ice drift
  116. data(k)%jpiv = j ! Not really used for ice drift
  117. data(k)%i_orig_grid = i ! Used for ice drift
  118. data(k)%j_orig_grid = j ! Used for ice drift
  119. data(k)%lat=drlat(i,j)
  120. data(k)%lon=ang180(drlon(i,j))
  121. !LB: Data support is assumed = a square grid cell
  122. !support diameter in meters stored in %a1 (tricky, isn't it ?)
  123. ! KAL -- hardcoded from data
  124. data(k)%a1 = 1.4 * 16000.0
  125. data(k)%ns = 1
  126. ! To be decided - obs units are meters O(1e4)
  127. ! CERSAT grid cells are of ~30 km - We assume the errors are
  128. ! roughly ~15 km
  129. !KAL data(k)%var = (15)**2
  130. data(k)%var = var ! fom idrft.hdr specification
  131. data(k)%depth = 0.0
  132. data(k)%status = valid
  133. enddo
  134. enddo
  135. enddo
  136. print*, 'Number of data read:', k, gridpoints(gr)
  137. print *,'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'
  138. print *,'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'
  139. print *,'!!!!!!!!! Adjust obs errors !!!!!!!!!!!!!!!!!!!'
  140. print *,'!!!!!!!Use qflag in valid as well!!!!!!!!!!!!!!!'
  141. print *,'!!!!!!!!!!CHECK use of qflag !!!!!!!!!!!!!!!!!!!'
  142. print *,'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'
  143. print *,'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'
  144. end subroutine read_CERSAT_data
  145. subroutine cersat_readfield(fname, ncid, varid, v, vlen)
  146. use nfw_mod
  147. implicit none
  148. character*(*), intent(in) :: fname
  149. integer, intent(in) :: ncid
  150. integer, intent(in) :: varid
  151. integer :: vlen
  152. real(8), intent(out) :: v(vlen)
  153. real(8) :: scale_factor(1)
  154. real(8) :: offset(1)
  155. call nfw_get_att_double(fname, ncid, varid, 'scale_factor', scale_factor)
  156. call nfw_get_att_double(fname, ncid, varid, 'add_offset', offset)
  157. call nfw_get_var_double(fname, ncid, varid, v)
  158. v = v * scale_factor(1) + offset(1)
  159. end subroutine cersat_readfield
  160. end module m_read_CERSAT_data