p_prep_obs_ORCA1.f90 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. # 0 "<stdin>"
  2. # 0 "<built-in>"
  3. # 0 "<command-line>"
  4. # 1 "/usr/include/stdc-predef.h" 1 3 4
  5. # 17 "/usr/include/stdc-predef.h" 3 4
  6. # 2 "<command-line>" 2
  7. # 1 "<stdin>"
  8. # 9 "<stdin>"
  9. program prep_obs
  10. ! This takes a model restart file, extracts the desired variable
  11. ! and brings into a format that the EnKF V2 can read & treat ('observations.uf').
  12. !
  13. ! !!! AGAIN: THIS USES EnKF VERSION 2 !!!
  14. !
  15. ! Two command line arguments are expected:
  16. ! 1. Path to the nc file of which the data is to be extracted.
  17. ! 2. Variable name that can be found in there.
  18. !
  19. ! Output is written to 'observations.uf'. If lots of files are to be treated,
  20. ! use a shell script to call me and rename output.
  21. !
  22. ! Warning: Currently only the data from the first time step are being read.
  23. ! (No problem with restart files, normally)
  24. !
  25. !
  26. ! TO DO: Add possibility of treating several obs types.
  27. !
  28. !
  29. ! (c) September 2008, Christof König Beatty, Christof.KonigBeatty@uclouvain.be
  30. ! (c) May 2009, generalized by same.
  31. ! (c) Jun 2011, simplified by F. Massonnet
  32. ! (c) April 2016, cleaned by F. Massonnet
  33. use mod_measurement
  34. use netcdf
  35. implicit none
  36. ! NetCDF vars
  37. character(len=99) :: filename, cvarerror, cvarerroru, cvarerrorv
  38. integer :: ncid, ierr, nvar, narg
  39. logical :: ex
  40. character(len=16) :: varname, varnameu, varnamev ! Type of measurement ('a_i_htcX', 'u_ice', 'v_ice', maybe 'v_i_htcX', 'siconc' if model forced by itself)
  41. !!!!!TAG-DEV-AD : change mask-ORCA1.nc into mask-eORCA1.nc
  42. ! character(len=80), parameter :: maskfile = 'mask-ORCA1.nc' !hc!
  43. character(len=80), parameter :: maskfile = 'mask-eORCA1.nc' !hc!
  44. ! Data vars
  45. !!!!!TAG-DEV-AD : adapted coordinate for eORCA1, mlon mlat mx my for model dim
  46. integer, parameter :: mx=360, my=331 ! Unfortunately, still hard coded.
  47. real, dimension(mx,my) :: mlons, mlats
  48. !!!!!TAG-DEV-AD : add OSI-SAF dim = obs dim = ox,oy
  49. integer, parameter :: ox=432, oy=432 ! Unfortunately, still hard coded.
  50. real, dimension(ox,oy,1) :: errorfld, obsfld, obsfldu, obsfldv, errorfldu, errorfldv
  51. real, dimension(ox,oy) :: olons, olats
  52. REAL :: obsmin, obsmax, errmin, errmax
  53. REAL :: latmin_NH = 40.0 !76.0 Assim only circle more or less with Svlbard latitudes
  54. REAL :: latmax_NH = 90.0 !82.0
  55. REAL :: latmin_SH = 40.0 ! Same for SH (sign will be added)
  56. REAL :: latmax_SH = 90.0
  57. integer, dimension(mx,my) :: mask
  58. integer :: obscnt, obscnt2, cpt, cptemin, cptemax, cptomin, cptomax ! Counts nr of obs's.
  59. ! Other vars
  60. character(len=99) dummy ! To read cmd line args
  61. ! for loops (haha)
  62. integer :: i, j, varID, varID_lon, varID_lat, varID_err, varID_var, icomp
  63. ! Ice thickness category stuff
  64. integer, parameter :: nhtc=5 !hc! nr of ice thickn. cat's
  65. real(KIND=8) :: rdate
  66. ! Obs stuff
  67. type (measurement), allocatable :: obs(:)
  68. ! Need to fill:
  69. ! d (val), var (error var), id (iiceconc etc.), lon, lat, depths,
  70. ! ipic, jpic (i/j-pivot point in grid), ns (support, 0: point meas.),
  71. ! a1-4 (bilin. coeff), status (not used)
  72. narg= iargc()
  73. PRINT *, narg
  74. if (narg<=1) then
  75. ! Write info
  76. write(*,*)
  77. write(*,*) " (prep_obs) takes a real obs, extracts the desired variable and outputs"
  78. write(*,*) " it in a format that the EnKF can read & treat ('observations.uf')."
  79. write(*,*)
  80. write(*,*) " A file named mask.nc containing the variables tmaskutil, nav_lon and nav_lat"
  81. write(*,*) " is expected to be in the current directory (ORCA-file)"
  82. write(*,*)
  83. write(*,*) " Three command line arguments are expected:"
  84. write(*,*) " 1. Path to the nc file of which the data is to be extracted."
  85. write(*,*) " 2. Variable name that can be found in there, 'h_i_htc1' or"
  86. write(*,*) " 'sic'. or dxdy_ice"
  87. write(*,*) " 3. A tag with the date, e.g. 19790520"
  88. write(*,*)
  89. write(*,*) " Hope to see you again soon."
  90. write(*,*)
  91. stop "(prep_obs): Stopped."
  92. end if
  93. ! Command line arguments
  94. nvar=narg-1
  95. ! Get them
  96. call getarg(1, dummy)
  97. read(dummy,'(A)') filename
  98. ! Some parameter checking
  99. inquire(file=trim(filename), exist=ex)
  100. if (.not.ex) then
  101. print *, '(p_prep_obs): file does not exist: '// trim(filename)
  102. stop
  103. end if
  104. ! Get mask, lons & lats
  105. ! open the maskfile
  106. ierr = nf90_open(trim(maskfile),nf90_NoWrite,ncid); if (ierr.ne.nf90_noerr) call handle_err(ierr, "opening mask file")
  107. ! Find VarID of tmask & get values
  108. ierr = nf90_inq_varid(ncid, 'tmask', varID) ; if (ierr.ne.nf90_noerr) call handle_err(ierr, "inquiring varID tmask")
  109. WRITE(*,*)'tmask varID:',varID
  110. ierr = nf90_get_var(ncid, varID, mask) ; if (ierr.ne.nf90_noerr) call handle_err(ierr, "getting variable tmaks")
  111. ! Find VarID of longitude & get vals
  112. ierr = nf90_inq_varid(ncid, 'nav_lon', varID) ; if (ierr.ne.nf90_noerr) call handle_err(ierr, "inquiring varID nav_lon")
  113. WRITE(*,*)'nav_lon varID:',varID
  114. ierr = nf90_get_var(ncid, varID, mlons) ; if (ierr.ne.nf90_noerr) call handle_err(ierr, "getting variable nav_lon")
  115. ! Find VarID of latitude & get vals
  116. ierr = nf90_inq_varid(ncid, 'nav_lat', varID) ; if (ierr.ne.nf90_noerr) call handle_err(ierr, "inquiring varID nav_lat")
  117. ierr = nf90_get_var(ncid, varID, mlats) ; if (ierr.ne.nf90_noerr) call handle_err(ierr, "getting variable nav_lat")
  118. ! Close maskfile
  119. ierr = nf90_close(ncid)
  120. if (ierr.ne.nf90_noerr) call handle_err(ierr, "closing")
  121. allocate( obs(nvar*sum(mask)), STAT=ierr )
  122. if (ierr.ne.0) call handle_err(ierr, "allocating obs") !no netcdf-error! ohwell.
  123. obscnt = 0 ! Keeps track of nr of added obs's.
  124. call getarg(2, dummy)
  125. read(dummy,'(A)') varname
  126. call getarg(3, dummy)
  127. read(dummy,*) rdate
  128. IF ( TRIM(varname) .eq. 'rfb' ) THEN
  129. WRITE(*,*) "Handling ", TRIM(varname)
  130. ! Min and max values for error used to screen the data (any data with
  131. ! standard deviation in between those values will be selected
  132. obsmin = 0.01
  133. obsmax = 10.0
  134. errmin = 0.01
  135. errmax = 1.0
  136. ELSEIF ( TRIM(varname) .eq. 'vt_i') THEN
  137. WRITE(*,*) "Handling ", TRIM(varname)
  138. obsmin = 0.01
  139. obsmax = 50.0
  140. errmin = 0.01
  141. errmax = 1.0
  142. ELSEIF ( TRIM(varname) .eq. 'at_i') THEN
  143. WRITE(*,*) "Handling ", TRIM(varname)
  144. obsmin = 0.001
  145. obsmax = 1.0
  146. errmin = 0.001
  147. errmax = 0.5
  148. ELSEIF ( TRIM(varname) .eq. 'siconc') THEN
  149. WRITE(*,*) "Handling ", TRIM(varname)
  150. obsmin = 0.001
  151. obsmax = 1.0
  152. errmin = 0.001
  153. errmax = 0.5
  154. ELSEIF ( TRIM(varname) .eq. 'ice_conc') THEN ! OSI-SAF-450
  155. WRITE(*,*) "Handling ", TRIM(varname)
  156. obsmin = 0.0
  157. obsmax = 100.0
  158. errmin = 0.001
  159. errmax = 40.0
  160. ELSE
  161. WRITE(*,*) " (prep_obs) Currently only the variables rfb (sea ice freeboard),"
  162. WRITE(*,*) " vt_i (total sea ice volume)"
  163. WRITE(*,*) " at_i (total sea ice concentration)"
  164. WRITE(*,*) " can be processed "
  165. STOP "(prep_obs) Aborted"
  166. ENDIF
  167. ! User info
  168. WRITE(*,*) "(prep_obs) Extracting "//TRIM(varname)//" from "//TRIM(filename)
  169. ! Some preparations
  170. obsfld=0.
  171. errorfld=0.
  172. ! open the netCDF file
  173. ierr = nf90_open(trim(filename),nf90_NoWrite,ncid) ; if (ierr.ne.nf90_noerr) call handle_err(ierr, "opening")
  174. ! Read observation data
  175. ! Find VarID of longitude & get vals from obs
  176. ierr = nf90_inq_varid(ncid, 'lon', varID_lon) ; if (ierr.ne.nf90_noerr) call handle_err(ierr, "inq varID lon obs")
  177. WRITE(*,*)'lon obs varID:',varID_lon
  178. ierr = nf90_get_var(ncid, varID_lon, olons) ; if (ierr.ne.nf90_noerr) call handle_err(ierr, "getting var lon obs")
  179. ! Find VarID of latitude & get vals
  180. ierr = nf90_inq_varid(ncid, 'lat', varID_lat) ; if (ierr.ne.nf90_noerr) call handle_err(ierr, "inq varID lat obs")
  181. ierr = nf90_get_var(ncid, varID_lat, olats) ; if (ierr.ne.nf90_noerr) call handle_err(ierr, "getting var lat obs")
  182. ! Find VarID of varname (variable to assim)
  183. WRITE(*,*) "varname="//trim(varname)
  184. ierr = nf90_inq_varid(ncid, trim(varname), varID_var) ; if (ierr.ne.nf90_noerr) call handle_err(ierr, "inq varID obs")
  185. ! get values
  186. ierr = nf90_get_var(ncid, varID_var, obsfld) ; if (ierr.ne.nf90_noerr) call handle_err(ierr, "getting var obs")
  187. obsfld=obsfld/100.
  188. WRITE(*,*) "OK var"//trim(varname)
  189. ! Find VarID of varname (error)
  190. cvarerror=TRIM(varname)//'_sd'
  191. WRITE(*,*) "cvarerror="//trim(varname)//"_sd"
  192. ierr = nf90_inq_varid(ncid, cvarerror, varID_err) ; if (ierr.ne.nf90_noerr) call handle_err(ierr, "inq varID obs")
  193. !! get values
  194. ierr = nf90_get_var(ncid, varID_err, errorfld) ; if (ierr.ne.nf90_noerr) call handle_err(ierr, "getting error var obs")
  195. errorfld=errorfld/100.
  196. ! Close file
  197. ierr = nf90_close(ncid) ; if (ierr.ne.nf90_noerr) call handle_err(ierr, "closing")
  198. ! User info - ADAPT ACCORDINGLY
  199. WRITE (*,*) " (prep_obs) Using data >40N and <45S"
  200. obscnt2=0
  201. WRITE(*,*) 'obs min:',obsmin,'obs max:',obsmax,'err min:',errmin,'err max:',errmax
  202. ! Loop over space
  203. DO i = 1, SIZE(olats, 1)
  204. DO j = 1, SIZE(olats, 2)
  205. ! Pick out ocean points where data is existent
  206. IF ( obsfld(i,j,1) .LT. obsmax &
  207. .AND. obsfld(i,j,1) .GT. obsmin &
  208. .AND. ( (errorfld(i,j,1)) ** 2 ) .GT. ( errmin ** 2 ) &
  209. .AND. ( (errorfld(i,j,1)) ** 2 ) .LT. ( errmax ** 2 ) &
  210. ) THEN
  211. obscnt2 = obscnt2 + 1
  212. ! Limit 'obs' spatially
  213. IF ( ( olats(i,j) .GE. latmin_NH &
  214. .AND. olats(i,j) .LE. latmax_NH ) &
  215. .OR.( olats(i,j) .LE. (-latmin_SH) &
  216. .AND. olats(i,j) .GE. (-latmax_SH) ) &
  217. ) THEN
  218. obscnt = obscnt + 1
  219. obs(obscnt)%d = obsfld(i,j,1)
  220. obs(obscnt)%lon = olons(i,j)
  221. obs(obscnt)%lat = olats(i,j)
  222. obs(obscnt)%ipiv = i ! the i-point of the grid of the model
  223. obs(obscnt)%jpiv = j ! the j-point of the grid of the model
  224. ! Put other data into obs type array
  225. obs(obscnt)%var = (errorfld(i,j,1))**2 ! The variance
  226. obs(obscnt)%id = TRIM(varname)
  227. obs(obscnt)%depths = 0
  228. obs(obscnt)%ns = 0
  229. obs(obscnt)%a1 = 1
  230. obs(obscnt)%a2 = 0
  231. obs(obscnt)%a3 = 0
  232. obs(obscnt)%a4 = 0
  233. obs(obscnt)%status = .TRUE.
  234. obs(obscnt)%i_orig_grid = -1
  235. obs(obscnt)%j_orig_grid = -1
  236. obs(obscnt)%h = -1.0
  237. obs(obscnt)%date = rdate
  238. obs(obscnt)%orig_id = 0
  239. END IF ! Spatial selection
  240. END IF ! if valid point
  241. END DO ! j
  242. END DO ! i
  243. WRITE(*,*) 'Nb obscnt: ', obscnt
  244. WRITE(*,*) 'Nb obscnt2: ', obscnt2
  245. !Write data:
  246. INQUIRE(iolength=i)obs(1)
  247. OPEN (11, file='observations.uf', status='replace',form='unformatted', access='direct', recl=i)
  248. DO j = 1, obscnt
  249. WRITE(11, rec=j)obs(j)
  250. ENDDO
  251. CLOSE(11)
  252. ! Write data to textfile, for visual checking
  253. OPEN(12, file = 'observations.txt')
  254. DO j = 1, obscnt
  255. WRITE(12, FMT = 53) obs(j)
  256. 53 FORMAT(f8.4,X,f9.4,X,a8,X,2(f10.5,X),f4.2,X,2(I3,X),I1,X,4(f5.2,X),L,X,2(I3,X),f5.2,X,I8,X,I1)
  257. ENDDO
  258. CLOSE(12)
  259. ! Tell user how many obs there were
  260. WRITE(*,*) " (prep_obs) Wrote out this many obs: ", obscnt
  261. WRITE(*,*) " (prep_obs) Number of ocean points : ", sum(mask)
  262. ! Cleanup
  263. IF (allocated(obs)) deallocate(obs,STAT=ierr)
  264. WRITE(*,*) ' (prep_obs) End successfully reached'; WRITE(*,*)
  265. contains
  266. subroutine handle_err(status, infomsg)
  267. integer, intent ( in) :: status
  268. character(len = *), intent ( in), optional :: infomsg
  269. if(status /= nf90_noerr) then
  270. if (present(infomsg)) then
  271. print *, '(prep_obs) Error while '//infomsg//' - '//trim(nf90_strerror(status))
  272. else
  273. print *, trim(nf90_strerror(status))
  274. endif ! opt arg
  275. print *,'(prep_obs)'
  276. stop
  277. end if ! check error status
  278. end subroutine handle_err
  279. end program prep_obs