obssla_io.h90 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. !!----------------------------------------------------------------------
  2. !! NEMO/OPA 3.3 , NEMO Consortium (2010)
  3. !! $Id: obssla_io.h90 2287 2010-10-18 07:53:52Z smasson $
  4. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  5. !!----------------------------------------------------------------------
  6. SUBROUTINE read_avisofile( cdfilename, inpfile, kunit, ldwp, ldgrid )
  7. !!---------------------------------------------------------------------
  8. !!
  9. !! ** ROUTINE read_avisofile **
  10. !!
  11. !! ** Purpose : Read from file the AVISO SLA observations.
  12. !!
  13. !! ** Method : The data file is a NetCDF file.
  14. !!
  15. !! ** Action :
  16. !!
  17. !! References : http://www.aviso.oceanobs.com
  18. !!
  19. !! History :
  20. !! ! 09-01 (K. Mogensen) Original based on old versions
  21. !!----------------------------------------------------------------------
  22. !! * Arguments
  23. CHARACTER(LEN=*) :: cdfilename ! Input filename
  24. TYPE(obfbdata) :: inpfile ! Output obfbdata structure
  25. INTEGER :: kunit ! Unit for output
  26. LOGICAL :: ldwp ! Print info
  27. LOGICAL :: ldgrid ! Save grid info in data structure
  28. !! * Local declarations
  29. CHARACTER(LEN=14),PARAMETER :: cpname = 'read_avisofile'
  30. INTEGER :: i_file_id ! netcdf IDS
  31. INTEGER :: i_tracks_id
  32. INTEGER :: i_cycles_id
  33. INTEGER :: i_data_id
  34. INTEGER :: i_var_id
  35. INTEGER, PARAMETER :: imaxdim = 2 ! Assumed maximum for no. dims. in file
  36. INTEGER, DIMENSION(2) :: idims ! Dimensions in file
  37. INTEGER :: iilen ! Length of netCDF attributes
  38. INTEGER :: itype ! Typeof netCDF attributes
  39. REAL(fbdp) :: zsca ! Scale factor
  40. REAL(fbdp) :: zfill ! Fill value
  41. CHARACTER(len=3) :: cmission ! Mission global attribute
  42. INTEGER :: itracks ! Maximum number of passes in file
  43. INTEGER :: icycles ! Maximum number of cycles for each pass
  44. INTEGER :: idata ! Number of data per parameter in current file
  45. REAL(fbdp) :: zdeltat ! Time gap getween two measurements in seconds
  46. INTEGER, DIMENSION(:), POINTER :: &
  47. & iptracks, & ! List of passes contained in current file
  48. & ipnbpoints, & ! Number of points per pass
  49. & ipdataindexes ! Index of data in theoretical profile
  50. INTEGER, DIMENSION(:,:), POINTER :: &
  51. & ipcycles ! List of cycles per pass
  52. REAL(fbdp), DIMENSION(:), POINTER :: &
  53. & zphi, & ! Latitudes
  54. & zlam ! Longitudes
  55. REAL(fbdp), DIMENSION(:,:), POINTER :: &
  56. & zbegindates ! Date of point with index 0
  57. REAL(fbdp) :: zbeginmiss ! Missing data for dates
  58. REAL(fbsp), DIMENSION(:,:), POINTER :: &
  59. & zsla ! SLA data
  60. REAL(fbdp), DIMENSION(:), POINTER :: &
  61. & zjuld ! Julian date
  62. LOGICAL, DIMENSION(:), POINTER :: &
  63. & llskip ! Skip observation
  64. CHARACTER(len=14) :: cdjuldref ! Julian data reference
  65. INTEGER :: imission ! Mission number converted from Mission global
  66. ! netCDF atttribute.
  67. CHARACTER(len=255) :: ctmp
  68. INTEGER :: iobs
  69. INTEGER :: jl
  70. INTEGER :: jm
  71. INTEGER :: jj
  72. INTEGER :: ji
  73. INTEGER :: jk
  74. INTEGER :: jobs
  75. INTEGER :: jcycle
  76. ! Open the file
  77. CALL chkerr( nf90_open( TRIM( cdfilename ), nf90_nowrite, i_file_id ), &
  78. & cpname, __LINE__ )
  79. ! Get the netCDF dimensions
  80. CALL chkerr( nf90_inq_dimid( i_file_id, 'Tracks', i_tracks_id ), &
  81. & cpname, __LINE__ )
  82. CALL chkerr( nf90_inquire_dimension( i_file_id, i_tracks_id, &
  83. & len = itracks ), &
  84. & cpname, __LINE__ )
  85. CALL chkerr( nf90_inq_dimid( i_file_id, 'Cycles', i_cycles_id ), &
  86. & cpname, __LINE__ )
  87. CALL chkerr( nf90_inquire_dimension( i_file_id, i_cycles_id, &
  88. & len = icycles ), &
  89. & cpname, __LINE__ )
  90. CALL chkerr( nf90_inq_dimid( i_file_id, 'Data', i_data_id ), &
  91. & cpname, __LINE__ )
  92. CALL chkerr( nf90_inquire_dimension( i_file_id, i_data_id, &
  93. & len = idata ), &
  94. & cpname, __LINE__ )
  95. ! Allocate memory for input data
  96. ALLOCATE( &
  97. & iptracks ( itracks ), &
  98. & ipnbpoints ( itracks ), &
  99. & ipcycles ( icycles, itracks ), &
  100. & zphi ( idata ), &
  101. & zlam ( idata ), &
  102. & zbegindates ( icycles, itracks ), &
  103. & ipdataindexes( idata ), &
  104. & zsla ( icycles, idata ), &
  105. & zjuld ( idata*icycles ), &
  106. & llskip ( idata*icycles ) &
  107. & )
  108. ! Get time gap getween two measurements in seconds
  109. CALL chkerr( nf90_inq_varid( i_file_id, 'DeltaT', i_var_id ), &
  110. & cpname, __LINE__ )
  111. CALL chkdim( i_file_id, i_var_id, 0, idims, cpname, __LINE__ )
  112. CALL chkerr( nf90_get_var ( i_file_id, i_var_id, zdeltat), &
  113. & cpname, __LINE__ )
  114. zsca = 1.0
  115. IF (nf90_inquire_attribute( i_file_id, i_var_id, 'scale_factor') &
  116. & == nf90_noerr) THEN
  117. CALL chkerr( nf90_get_att( i_file_id, i_var_id, &
  118. & 'scale_factor',zsca), cpname, __LINE__)
  119. ENDIF
  120. zdeltat = zsca * zdeltat
  121. ! Get List of passes contained in current file
  122. CALL chkerr( nf90_inq_varid( i_file_id, 'Tracks', i_var_id ), &
  123. & cpname, __LINE__ )
  124. idims(1) = itracks
  125. CALL chkdim( i_file_id, i_var_id, 1, idims, cpname, __LINE__ )
  126. CALL chkerr( nf90_get_var ( i_file_id, i_var_id, iptracks), &
  127. & cpname, __LINE__ )
  128. ! Get Number of points per pass
  129. CALL chkerr( nf90_inq_varid( i_file_id, 'NbPoints', i_var_id ), &
  130. & cpname, __LINE__ )
  131. idims(1) = itracks
  132. CALL chkdim( i_file_id, i_var_id, 1, idims, cpname, __LINE__ )
  133. CALL chkerr( nf90_get_var ( i_file_id, i_var_id, ipnbpoints),&
  134. & cpname, __LINE__ )
  135. ! Get list of cycles per pass
  136. CALL chkerr( nf90_inq_varid( i_file_id, 'Cycles', i_var_id ), &
  137. & cpname, __LINE__ )
  138. idims(1) = icycles
  139. idims(2) = itracks
  140. CALL chkdim( i_file_id, i_var_id, 2, idims, cpname, __LINE__ )
  141. CALL chkerr( nf90_get_var ( i_file_id, i_var_id, ipcycles), &
  142. & cpname, __LINE__ )
  143. ! Get longitudes
  144. CALL chkerr( nf90_inq_varid( i_file_id, 'Longitudes', i_var_id ), &
  145. & cpname, __LINE__ )
  146. idims(1) = idata
  147. CALL chkdim( i_file_id, i_var_id, 1, idims, cpname, __LINE__ )
  148. CALL chkerr( nf90_get_var ( i_file_id, i_var_id, zlam), &
  149. & cpname, __LINE__ )
  150. zsca = 1.0
  151. IF (nf90_inquire_attribute( i_file_id, i_var_id, 'scale_factor') &
  152. & == nf90_noerr) THEN
  153. CALL chkerr( nf90_get_att( i_file_id, i_var_id, &
  154. & 'scale_factor',zsca), cpname, __LINE__)
  155. ENDIF
  156. zlam(:) = zsca * zlam(:)
  157. ! Get latitudes
  158. CALL chkerr( nf90_inq_varid( i_file_id, 'Latitudes', i_var_id ), &
  159. & cpname, __LINE__ )
  160. idims(1) = idata
  161. CALL chkdim( i_file_id, i_var_id, 1, idims, cpname, __LINE__ )
  162. CALL chkerr( nf90_get_var ( i_file_id, i_var_id, zphi), &
  163. & cpname, __LINE__ )
  164. zsca = 1.0
  165. IF (nf90_inquire_attribute( i_file_id, i_var_id, 'scale_factor') &
  166. & == nf90_noerr) THEN
  167. CALL chkerr( nf90_get_att( i_file_id, i_var_id, &
  168. & 'scale_factor',zsca), cpname, __LINE__)
  169. ENDIF
  170. zphi(:) = zsca * zphi(:)
  171. ! Get date of point with index 0
  172. CALL chkerr( nf90_inq_varid( i_file_id, 'BeginDates', i_var_id ), &
  173. & cpname, __LINE__ )
  174. idims(1) = icycles
  175. idims(2) = itracks
  176. CALL chkdim( i_file_id, i_var_id, 2, idims, cpname, __LINE__ )
  177. CALL chkerr( nf90_get_var ( i_file_id, i_var_id, zbegindates), &
  178. & cpname, __LINE__ )
  179. CALL chkerr( nf90_inquire_attribute( i_file_id, i_var_id, &
  180. & 'units', len = iilen, &
  181. & xtype = itype), cpname, __LINE__ )
  182. IF (( itype /= NF90_CHAR ) .OR. ( iilen > 255 )) THEN
  183. CALL fatal_error('Error decoding BeginDates unit', __LINE__ )
  184. ENDIF
  185. CALL chkerr( nf90_get_att( i_file_id, i_var_id, 'units', &
  186. & ctmp ), cpname, __LINE__ )
  187. jl=1
  188. DO jm = 1, LEN(TRIM(ctmp))
  189. IF ((ctmp(jm:jm)>='0').AND.(ctmp(jm:jm)<='9')) THEN
  190. cdjuldref(jl:jl) = ctmp(jm:jm)
  191. jl=jl+1
  192. ENDIF
  193. IF (jl>14) EXIT
  194. END DO
  195. CALL chkerr( nf90_inquire_attribute( i_file_id, i_var_id, '_FillValue', &
  196. & xtype = itype), cpname, __LINE__ )
  197. IF ( itype /= NF90_DOUBLE ) THEN
  198. CALL fatal_error('Error decoding BeginDates missing data', __LINE__ )
  199. ENDIF
  200. CALL chkerr( nf90_get_att( i_file_id, i_var_id, '_FillValue', &
  201. & zbeginmiss ), cpname, __LINE__ )
  202. ! Get indices of data in theoretical profile
  203. CALL chkerr( nf90_inq_varid( i_file_id, 'DataIndexes', i_var_id ), &
  204. & cpname, __LINE__ )
  205. idims(1) = idata
  206. CALL chkdim( i_file_id, i_var_id, 1, idims, cpname, __LINE__ )
  207. CALL chkerr( nf90_get_var ( i_file_id, i_var_id, ipdataindexes), &
  208. & cpname, __LINE__ )
  209. ! Get SLA data
  210. CALL chkerr( nf90_inq_varid( i_file_id, 'SLA', i_var_id ), &
  211. & cpname, __LINE__ )
  212. idims(1) = icycles
  213. idims(2) = idata
  214. CALL chkdim( i_file_id, i_var_id, 2, idims, cpname, __LINE__ )
  215. CALL chkerr( nf90_get_var ( i_file_id, i_var_id, zsla), &
  216. & cpname, __LINE__ )
  217. zsca = 1.0
  218. IF (nf90_inquire_attribute( i_file_id, i_var_id, 'scale_factor') &
  219. & == nf90_noerr) THEN
  220. CALL chkerr( nf90_get_att( i_file_id, i_var_id, &
  221. & 'scale_factor',zsca), cpname, __LINE__ )
  222. ENDIF
  223. zfill = 0.0
  224. IF (nf90_inquire_attribute( i_file_id, i_var_id, '_FillValue') &
  225. & == nf90_noerr) THEN
  226. CALL chkerr( nf90_get_att( i_file_id, i_var_id, &
  227. & '_FillValue',zfill), cpname, __LINE__ )
  228. ENDIF
  229. WHERE(zsla(:,:) /= zfill)
  230. zsla(:,:) = zsca * zsla(:,:)
  231. ELSEWHERE
  232. zsla(:,:) = fbrmdi
  233. END WHERE
  234. ! Get the global Mission netCDF attribute
  235. cmission=' '
  236. CALL chkerr( nf90_inquire_attribute( i_file_id, nf90_global, &
  237. & 'Mission', len = iilen, &
  238. & xtype = itype), cpname, __LINE__ )
  239. IF (( itype /= NF90_CHAR ) .OR. ( iilen > 3 )) THEN
  240. CALL fatal_error('Error decoding Mission global attribute', __LINE__ )
  241. ENDIF
  242. CALL chkerr( nf90_get_att( i_file_id, nf90_global, 'Mission', &
  243. & cmission ), cpname, __LINE__ )
  244. ! Convert it to an integer
  245. imission = 0
  246. DO jm = 1, imaxmissions
  247. IF (cmission==cmissions(jm)) THEN
  248. imission = jm
  249. EXIT
  250. ENDIF
  251. END DO
  252. ! Close the file
  253. CALL chkerr( nf90_close( i_file_id ), cpname, __LINE__ )
  254. ! Compute Julian dates for all observations
  255. jm = 0
  256. jl = 0
  257. DO jj = 1, itracks
  258. DO ji = 1, ipnbpoints(jj)
  259. jl = jl + 1
  260. DO jk = 1, icycles
  261. jm = jm + 1
  262. IF (zbegindates(jk,jj)==zbeginmiss) THEN
  263. llskip(jm) = .TRUE.
  264. zjuld(jm) = fbrmdi
  265. ELSE
  266. llskip(jm) = .FALSE.
  267. zjuld(jm) = zbegindates(jk,jj) + &
  268. & (ipdataindexes(jl) * zdeltat / 86400._wp )
  269. ENDIF
  270. END DO
  271. END DO
  272. END DO
  273. ! Get rid of missing data
  274. jm = 0
  275. DO jobs = 1, idata
  276. DO jcycle = 1, icycles
  277. jm = jm + 1
  278. IF (zsla(jcycle,jobs) == fbrmdi) llskip(jm) = .TRUE.
  279. END DO
  280. END DO
  281. ! Allocate obfbdata
  282. iobs = COUNT( .NOT.llskip(:) )
  283. CALL init_obfbdata( inpfile )
  284. CALL alloc_obfbdata( inpfile, 1, iobs, 1, 0, 0, ldgrid )
  285. inpfile%cname(1) = 'SLA'
  286. ! Fill the obfbdata structure from input data
  287. inpfile%cdjuldref = cdjuldref
  288. iobs = 0
  289. jm = 0
  290. DO jobs = 1, idata
  291. DO jcycle = 1, icycles
  292. jm = jm + 1
  293. IF (llskip(jm)) CYCLE
  294. iobs = iobs + 1
  295. ! Characters
  296. WRITE(inpfile%cdwmo(iobs),'(A3,A5)') cmissions(imission), ' '
  297. WRITE(inpfile%cdtyp(iobs),'(I4)') imission
  298. ! Real values
  299. inpfile%plam(iobs) = zlam(jobs)
  300. inpfile%pphi(iobs) = zphi(jobs)
  301. inpfile%pob(1,iobs,1) = zsla(jcycle,jobs)
  302. inpfile%ptim(iobs) = zjuld(jm)
  303. inpfile%pdep(1,iobs) = 0.0
  304. ! Integers
  305. inpfile%kindex(iobs) = iobs
  306. inpfile%ioqc(iobs) = 1
  307. inpfile%ivqc(iobs,1) = 1
  308. inpfile%ivlqc(1,iobs,1) = 1
  309. inpfile%ipqc(iobs) = 0
  310. inpfile%ipqcf(:,iobs) = 0
  311. inpfile%itqc(iobs) = 0
  312. inpfile%itqcf(:,iobs) = 0
  313. inpfile%ivqcf(:,iobs,1) = 0
  314. inpfile%ioqcf(:,iobs) = 0
  315. inpfile%idqc(1,iobs) = 0
  316. inpfile%idqcf(1,1,iobs) = 0
  317. inpfile%ivlqcf(:,1,iobs,1) = 0
  318. END DO
  319. END DO
  320. ! Deallocate memory for input data
  321. DEALLOCATE( &
  322. & iptracks, &
  323. & ipnbpoints, &
  324. & ipcycles, &
  325. & zphi, &
  326. & zlam, &
  327. & zbegindates, &
  328. & ipdataindexes, &
  329. & zsla, &
  330. & zjuld, &
  331. & llskip &
  332. & )
  333. END SUBROUTINE read_avisofile