m_read_CLS_TSLA.F90 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. module m_read_CLS_TSLA
  2. integer, parameter, private :: STRLEN = 512
  3. real(8), parameter, private :: RE_MULTIPLE = 0.7d0
  4. character(*), parameter, private :: RE_FNAME = "re_sla.nc"
  5. contains
  6. subroutine read_CLS_TSLA(filename, gr, data)
  7. use mod_measurement
  8. use mod_grid
  9. use nfw_mod
  10. implicit none
  11. character(*), intent(in) :: filename
  12. type(grid), intent(inout) :: gr ! CLS measurement grid
  13. type(measurement), intent(inout) :: data(:)
  14. integer :: data_ID, track_ID, cycl_ID
  15. integer :: vNbpoint_ID, vLongitude_ID, vLatitude_ID, vBegindate_ID, vSLA_ID
  16. ! array dimensions
  17. integer :: nb, ntracks, ncycles
  18. ! data arrays
  19. real(8), allocatable :: vsla(:,:), vlon(:), vlat(:), vbegindate(:,:)
  20. integer, allocatable :: vnbpoint(:)
  21. logical, allocatable :: isgood(:,:)
  22. integer :: ncid
  23. real(8), dimension(1) :: undef_sla, undef_lat, undef_lon, undef_begindate
  24. real(8) :: varsat
  25. integer, dimension(1) :: undef_nbpoint
  26. integer :: i, j, k, nobs, obsid, sid, age
  27. real(8), parameter :: EPS = 0.01 ! test for undefined values
  28. character(STRLEN) :: ftemplate
  29. character(STRLEN) :: fname
  30. character(STRLEN) :: fpath
  31. logical :: ex
  32. print *, 'read_CLS_TSLA():'
  33. fpath='./'
  34. read(filename,'(i7)') age
  35. nobs = 0
  36. do sid = 1, 7 ! loop over satellite ID
  37. select case(sid)
  38. case(1)
  39. ftemplate = trim(fpath)//'sla_'//trim(filename)//'_en*.nc'
  40. varsat = 0.0009 ! 3 cm for ENVISAT
  41. print *, ' ENVISSAT:'
  42. case(2)
  43. ftemplate = trim(fpath)//'sla_'//trim(filename)//'_j1*.nc'
  44. varsat = 0.0009 ! 3 cm for ENVISAT Jason1
  45. print *, ' Jason1:'
  46. case(3)
  47. ftemplate = trim(fpath)//'sla_'//trim(filename)//'_j2*.nc'
  48. varsat = 0.0009 ! 3 cm for ENVISAT Jason2
  49. print *, ' Jason2:'
  50. case(4)
  51. ftemplate = trim(fpath)//'sla_'//trim(filename)//'_e1*.nc'
  52. varsat = 0.0075 ! 8.5 cm for e1
  53. print *, ' ERS1:'
  54. case(5)
  55. ftemplate = trim(fpath)//'sla_'//trim(filename)//'_e2*.nc'
  56. varsat = 0.0075 ! 8.5 cm for e2
  57. print *, ' ERS2:'
  58. case(6)
  59. ftemplate = trim(fpath)//'sla_'//trim(filename)//'_tp*.nc'
  60. varsat = 0.0030 ! 5.5 cm for TOPEX
  61. print *, ' TOPEX:'
  62. case(7)
  63. ftemplate = trim(fpath)//'sla_'//trim(filename)//'_g2*.nc'
  64. varsat = 0.0030 ! GEOSAT
  65. print *, ' GEOSAT2:'
  66. end select
  67. call fname_fromtemplate(ftemplate, fname)
  68. inquire(file = trim(fname), exist = ex)
  69. if (.not. ex) then
  70. cycle
  71. end if
  72. ! Reading the observation file of satellite
  73. call nfw_open(fname, nf_nowrite, ncid)
  74. call nfw_inq_dimid(fname, ncid, 'Data', data_ID)
  75. call nfw_inq_dimid(fname, ncid, 'Tracks', track_ID)
  76. call nfw_inq_dimid(fname, ncid, 'Cycles', cycl_ID)
  77. call nfw_inq_dimlen(fname, ncid, data_ID, nb)
  78. call nfw_inq_dimlen(fname, ncid, track_ID, ntracks)
  79. call nfw_inq_dimlen(fname, ncid, cycl_ID, ncycles)
  80. print '(1x, a, 3i8)', ' dimensions (# obs, # tracks, # cycles):', nb, ntracks, ncycles
  81. allocate(vlon(nb), vlat(nb), vsla(ncycles, nb))
  82. allocate(vnbpoint(ntracks), vbegindate(ncycles, ntracks))
  83. allocate(isgood(ncycles, ntracks))
  84. ! Variable ids in netcdf file
  85. call nfw_inq_varid(fname, ncid, 'Latitudes', vLatitude_ID)
  86. call nfw_inq_varid(fname, ncid,'Longitudes', vLongitude_ID)
  87. call nfw_inq_varid(fname, ncid,'BeginDates', vBegindate_ID)
  88. call nfw_inq_varid(fname, ncid,'NbPoints', vNbpoint_ID)
  89. call nfw_inq_varid(fname, ncid,'SLA', vSLA_ID)
  90. ! Variable _FillValue attributes
  91. call nfw_get_att_double(fname, ncid, vLatitude_ID , '_FillValue', undef_lat(1))
  92. call nfw_get_att_double(fname, ncid, vLongitude_ID , '_FillValue', undef_lon(1))
  93. call nfw_get_att_double(fname, ncid, vSLA_ID, '_FillValue', undef_sla(1))
  94. call nfw_get_att_int(fname, ncid, vNbpoint_ID, '_FillValue', undef_nbpoint(1))
  95. call nfw_get_att_double(fname, ncid,vBegindate_ID, '_FillValue', undef_begindate(1))
  96. gr % undef = undef_sla(1)
  97. call nfw_get_var_double(fname, ncid, vLongitude_ID, vlon)
  98. call nfw_get_var_double(fname, ncid, vLatitude_ID, vlat)
  99. call nfw_get_var_double(fname, ncid, vSLA_ID, vsla)
  100. !lon = ang180(lon)
  101. vlon = vlon * 1.e-06
  102. vlat = vlat * 1.e-06
  103. print '(1x, a, 2f10.2)', ' range Lon = ', minval(vlon), maxval(vlon)
  104. print '(1x, a, 2f10.2)', ' range Lat = ', minval(vlat), maxval(vlat)
  105. print '(1x, a, 2f10.2)', ' range SLA = ', minval(vsla), maxval(vsla)
  106. call nfw_get_var_int(fname, ncid, vNbpoint_ID, vnbpoint)
  107. call nfw_get_var_double(fname, ncid, vBegindate_ID, vbegindate)
  108. print '(1x, a, 2i8)', ' range nbpoints = ', minval(vnbpoint), maxval(vnbpoint)
  109. print *, ' age = ', age
  110. isgood = .false.
  111. where (vbegindate /= undef_begindate(1))
  112. vbegindate = age - floor(vbegindate) - 1
  113. isgood = .true.
  114. end where
  115. print '(3x,a,2G10.3)',' range begin_date (days from assim) = ', &
  116. minval(pack(vbegindate, isgood)), maxval(pack(vbegindate, isgood))
  117. call nfw_close(fname, ncid)
  118. ! Here we set the reference the date with respect to the assimilation
  119. ! date (0=today, 6=is 6 day old).
  120. ! Fanf: We assume that the data from the same pass have the same
  121. ! date=begindate(passnb).
  122. ! We also assume that envisat, J1 and J2 have similar accuracy, and
  123. ! thus use data%var to store the age of the data. Only data that are
  124. ! younger than 6 days are retained such that we do not assimilate the
  125. ! same obs twice.
  126. do k = 1, ncycles
  127. obsid = 0
  128. do i = 1, ntracks
  129. do j = 1, vnbpoint(i)
  130. obsid = obsid + 1
  131. ! only consider data above -30 of lat
  132. if (vlat(obsid) <= -30.0 .or.&
  133. vbegindate(k, i) >= 7 .or. vbegindate(k, i) <= -1 .or.&
  134. vlon(obsid) == undef_lon(1) .or.&
  135. vlat(obsid) == undef_lat(1) .or.&
  136. vsla(k, obsid) == undef_sla(1)) then
  137. cycle
  138. end if
  139. nobs = nobs + 1
  140. data(nobs) % id = 'TSLA'
  141. data(nobs) % d = vsla(k, obsid) * 0.001 ! conversion to meters
  142. data(nobs) % ipiv = -1 ! to be filled
  143. data(nobs) % jpiv = -1
  144. data(nobs) % lat = vlat(obsid)
  145. data(nobs) % lon = ang180(vlon(obsid))
  146. data(nobs) % a1 = -1.0e10 ! to be filled
  147. data(nobs) % a2 = -1.0e10
  148. data(nobs) % a3 = -1.0e10
  149. data(nobs) % a4 = -1.0e10
  150. data(nobs) % ns = 0
  151. data(nobs) % var = varsat
  152. data(nobs) % date = int(vbegindate(k, i))
  153. data(nobs) % depth = 0.0
  154. data(nobs) % status = .true.
  155. enddo ! Vnbpoint
  156. enddo ! track
  157. enddo ! cycle
  158. print*, ' # of obs read so far = ', nobs
  159. deallocate(vlat, vlon, vsla, vnbpoint, vbegindate, isgood)
  160. end do ! satellite id
  161. gr % nx = nobs
  162. end subroutine read_CLS_TSLA
  163. subroutine read_MYO_TSLA(julday,dayinweek, gr, data)
  164. use mod_measurement
  165. use mod_grid
  166. use nfw_mod
  167. implicit none
  168. !Fanf: this routine assume that you have one seperate file for each day.
  169. !Call prepobs 7 times (for each cycle days with the date and the corrsponding
  170. !day in the cycle
  171. ! character(*), intent(in) :: filename
  172. character(*), intent(in) :: julday, dayinweek
  173. type(grid), intent(inout) :: gr ! MYO measurement grid
  174. type(measurement), intent(inout) :: data(:)
  175. integer :: time_ID !data_ID, track_ID, cycl_ID
  176. integer :: vNbpoint_ID, vLongitude_ID, vLatitude_ID, vBegindate_ID, vSLA_ID, vtime_ID
  177. ! array dimensions
  178. integer :: nb !, ntracks, ncycles
  179. ! data arrays
  180. real(8), allocatable :: vsla(:), vlon(:), vlat(:), vtime(:)!, vbegindate(:,:)
  181. logical, allocatable :: isgood(:)
  182. integer :: ncid
  183. real(8), dimension(1) :: undef_sla, undef_lat, undef_lon, undef_begindate, undef_time
  184. real(8) :: varsat
  185. integer, dimension(1) :: undef_nbpoint
  186. integer :: i, j, k, nobs, obsid, sid, age, idayinweek
  187. real(8), parameter :: EPS = 0.01 ! test for undefined values
  188. character(STRLEN) :: ftemplate
  189. character(STRLEN) :: fname
  190. character(STRLEN) :: fpath
  191. logical :: ex
  192. print *, 'read_MYO_TSLA():'
  193. fpath='./'
  194. read(julday,'(i7)') age
  195. read(dayinweek,'(i2)') idayinweek
  196. nobs = 0
  197. do sid = 1, 9 ! loop over satellite ID
  198. select case(sid)
  199. case(1)
  200. ftemplate = trim(fpath)//'sla_'//trim(julday)//'_en*.nc'
  201. varsat = 0.0009 ! 3 cm for ENVISAT
  202. print *, ' ENVISSAT:'
  203. case(2)
  204. ftemplate = trim(fpath)//'sla_'//trim(julday)//'_j1*.nc'
  205. varsat = 0.0009 ! 3 cm for ENVISAT Jason1
  206. print *, ' Jason1:'
  207. case(3)
  208. ftemplate = trim(fpath)//'sla_'//trim(julday)//'_j2*.nc'
  209. varsat = 0.0009 ! 3 cm for ENVISAT Jason2
  210. print *, ' Jason2:'
  211. case(4)
  212. ftemplate = trim(fpath)//'sla_'//trim(julday)//'_e1*.nc'
  213. varsat = 0.0075 ! 8.5 cm for e1
  214. print *, ' ERS1:'
  215. case(5)
  216. ftemplate = trim(fpath)//'sla_'//trim(julday)//'_e2*.nc'
  217. varsat = 0.0075 ! 8.5 cm for e2
  218. print *, ' ERS2:'
  219. case(6)
  220. ftemplate = trim(fpath)//'sla_'//trim(julday)//'_tp*.nc'
  221. varsat = 0.0030 ! 5.5 cm for TOPEX
  222. print *, ' TOPEX:'
  223. case(7)
  224. ftemplate = trim(fpath)//'sla_'//trim(julday)//'_g2*.nc'
  225. varsat = 0.0030 ! GEOSAT
  226. print *, ' GEOSAT2:'
  227. case(8)
  228. ftemplate = trim(fpath)//'sla_'//trim(julday)//'_c2*.nc'
  229. varsat = 0.0030 ! CRYOSAT-2
  230. print *, ' CRYOSAT2:'
  231. case(9)
  232. ftemplate = trim(fpath)//'sla_'//trim(julday)//'_al*.nc'
  233. varsat = 0.0009 ! ALTIKA
  234. print *, ' ALTIKA:'
  235. end select
  236. call fname_fromtemplate(ftemplate, fname)
  237. inquire(file = trim(fname), exist = ex)
  238. if (.not. ex) then
  239. cycle
  240. end if
  241. ! Reading the observation file of satellite
  242. call nfw_open(fname, nf_nowrite, ncid)
  243. call nfw_inq_dimid(fname, ncid, 'time', time_ID)
  244. call nfw_inq_dimlen(fname, ncid, time_ID, nb)
  245. print '(1x, a, i8)', ' dimensions (# obs):', nb !, ntracks, ncycles
  246. allocate(vlon(nb), vlat(nb), vsla(nb), vtime(nb))
  247. allocate(isgood(nb))
  248. ! Variable ids in netcdf file
  249. call nfw_inq_varid(fname, ncid, 'latitude', vLatitude_ID)
  250. call nfw_inq_varid(fname, ncid,'longitude', vLongitude_ID)
  251. call nfw_inq_varid(fname, ncid, 'time', vtime_ID)
  252. call nfw_inq_varid(fname, ncid,'SLA', vSLA_ID)
  253. ! Variable _FillValue attributes
  254. call nfw_get_att_double(fname, ncid, vSLA_ID, '_FillValue', undef_sla(1))
  255. gr % undef = undef_sla(1)
  256. call nfw_get_var_double(fname, ncid, vLongitude_ID, vlon)
  257. call nfw_get_var_double(fname, ncid, vLatitude_ID, vlat)
  258. call nfw_get_var_double(fname, ncid, vSLA_ID, vsla)
  259. call nfw_get_var_double(fname, ncid, vtime_ID, vtime)
  260. !lon = ang180(lon)
  261. vlon = vlon * 1.e-06
  262. vlat = vlat * 1.e-06
  263. print '(1x, a, 2f10.2)', ' range Lon = ', minval(vlon), maxval(vlon)
  264. print '(1x, a, 2f10.2)', ' range Lat = ', minval(vlat), maxval(vlat)
  265. print '(1x, a, 2f10.2)', ' range SLA = ', minval(vsla), maxval(vsla)
  266. print *, ' age = ', age
  267. print '(3x,a,G10.3)',' Days before assim = ', idayinweek
  268. call nfw_close(fname, ncid)
  269. ! Here we set the reference the date with respect to the assimilation
  270. ! date (0=today, 6=is 6 day old).
  271. ! Fanf: We assume that the data from the same pass have the same
  272. ! date=begindate(passnb).
  273. ! We also assume that envisat, J1 and J2 have similar accuracy, and
  274. ! thus use data%var to store the age of the data. Only data that are
  275. ! younger than 6 days are retained such that we do not assimilate the
  276. ! same obs twice.
  277. obsid = 0
  278. do k = 1, nb
  279. obsid = obsid + 1
  280. ! only consider data above -30 of lat
  281. if (vlat(obsid) <= -30.0 .or.&
  282. vsla(obsid) == undef_sla(1)) then
  283. cycle
  284. end if
  285. nobs = nobs + 1
  286. data(nobs) % id = 'TSLA'
  287. data(nobs) % d = vsla(obsid) * 0.001 ! conversion to meters
  288. data(nobs) % ipiv = -1 ! to be filled
  289. data(nobs) % jpiv = -1
  290. data(nobs) % lat = vlat(obsid)
  291. data(nobs) % lon = ang180(vlon(obsid))
  292. data(nobs) % a1 = -1.0e10 ! to be filled
  293. data(nobs) % a2 = -1.0e10
  294. data(nobs) % a3 = -1.0e10
  295. data(nobs) % a4 = -1.0e10
  296. data(nobs) % ns = 0
  297. data(nobs) % var = varsat
  298. data(nobs) % date = idayinweek
  299. data(nobs) % depth = 0.0
  300. data(nobs) % status = .true.
  301. enddo ! cycle
  302. print*, ' # of obs read so far = ', nobs, obsid
  303. deallocate(vlat, vlon, vsla, vtime, isgood)
  304. end do ! satellite id
  305. gr % nx = nobs
  306. end subroutine read_MYO_TSLA
  307. subroutine set_re_TSLA(nrobs, obs, nx, ny, modlon, modlat)
  308. use mod_measurement
  309. use nfw_mod
  310. integer, intent(in) :: nrobs
  311. type(measurement), dimension(nrobs), intent(inout) :: obs
  312. integer, intent(in) :: nx, ny
  313. real, dimension(nx, ny), intent(in) :: modlon, modlat
  314. integer :: ncid, reid
  315. real, dimension(nx, ny) :: re
  316. real :: reo
  317. integer :: o
  318. print *, ' reading representation error from "', trim(RE_FNAME), '"'
  319. call nfw_open(RE_FNAME, nf_nowrite, ncid)
  320. call nfw_inq_varid(RE_FNAME, ncid, 're_sla', reid)
  321. call nfw_get_var_double(RE_FNAME, ncid, reid, re)
  322. call nfw_close(RE_FNAME, ncid)
  323. do o = 1, nrobs
  324. reo = re(obs(o) % ipiv, obs(o) % jpiv)
  325. if (reo < 0 .or. reo > 1.0d5) then
  326. cycle
  327. end if
  328. ! PS 1.4.2010 Increased the multiple for representation error from
  329. ! 0.3 to 0.5 - it seems that with 0.3 it wants to do more in the Gulf
  330. ! Stream region than the model can sustain.
  331. ! PS June 2010 - further increased the multiple to 0.7.
  332. obs(o) % var = obs(o) % var + RE_MULTIPLE * reo
  333. end do
  334. end subroutine set_re_TSLA
  335. subroutine fname_fromtemplate(ftemplate, fname)
  336. character(*), intent(in) :: ftemplate
  337. character(*), intent(inout) :: fname
  338. character(STRLEN) :: command ! (there may be a limit of 80 on some systems)
  339. integer :: ios
  340. command = 'ls '//trim(ftemplate)//' 2> /dev/null > tsla_files.txt'
  341. call system(trim(command));
  342. open(10, file = 'tsla_files.txt')
  343. read(10, fmt = '(a)', iostat = ios) fname
  344. close(10)
  345. if (ios /= 0) then
  346. fname = ""
  347. end if
  348. end subroutine fname_fromtemplate
  349. end module m_read_CLS_TSLA