p_obsstats.F90 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. program p_obsstats
  2. ! Computes the EnKF analysis
  3. ! For parallelization
  4. #if defined (QMPI)
  5. use qmpi
  6. use distribute
  7. #else
  8. use qmpi_fake
  9. #endif
  10. use mod_measurement
  11. use mod_sphere_tools
  12. use m_get_mod_grid
  13. use m_get_mod_nrens
  14. use m_uobs
  15. use m_obs
  16. use m_prep_4_EnKF
  17. use m_set_random_seed2
  18. use m_parse_blkdat
  19. use netcdf
  20. implicit none
  21. integer nrens ! Size of ensemble
  22. real, dimension(:,:), allocatable :: modlon,modlat,depths
  23. !Generated variables for EnKF analysis
  24. !Global Analysis
  25. real, allocatable, dimension(:,:) :: S
  26. real, allocatable, dimension(:,:) :: E
  27. real, allocatable, dimension(:) :: d, meanD, meanS, RMSD, RMSE, RMSS, &
  28. mask_obs
  29. !Local Analysis
  30. real radius
  31. integer n_obs_local
  32. character(len=12) clocal
  33. !Local variables in main program
  34. integer iargc
  35. integer i,j
  36. !Parallab: Given random seed
  37. integer seedsze
  38. integer, allocatable :: putseed(:)
  39. !KAL real, allocatable, dimension(:,:,:,:) :: subS, X3
  40. real(8) rtc, old, time0, time1
  41. !KAL -- just for testing parse_blkdat
  42. real :: rdummy
  43. integer :: idm, jdm, kdm
  44. real :: mindx,meandx
  45. #if defined(MATLAB)
  46. !#include </export/fimm/local/Matlab-R14sp3/extern/include/fintrf.h> fimm
  47. #include </usr/local/Matlab-6.5/extern/include//fintrf.h>
  48. MWPOINTER :: mxCreateNumericMatrix, mxGetPr, mxClassIDFromClassName, matopen, &
  49. mxCreateDoubleMatrix, matPutVariableAsGlobal, mp, pa1
  50. integer matputvariable, matclose
  51. real*8, dimension(:,:), allocatable :: matio
  52. integer :: status
  53. #endif
  54. ! Netcdf output
  55. integer :: obsdim, var_id,ncid,ierr2
  56. character(len=80) :: ncfile
  57. logical :: ex
  58. character(len=20) :: regname
  59. integer,parameter :: maxcorners=10
  60. real, dimension(maxcorners) :: crnlon, crnlat
  61. integer :: numcorners,nrobsbox
  62. integer, dimension(:), allocatable :: pointinbox
  63. integer :: iuobs
  64. integer :: ios
  65. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  66. ! Read the characteristics of the assimilation to be carried out.
  67. if (iargc()/=0) then
  68. stop 'usage: obstats [ no argument ] '
  69. endif
  70. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  71. !Set a variable random seed
  72. !//lab call set_random_seed2
  73. ! Remove any randomness in the results for Parallab
  74. call random_seed(size=seedsze)
  75. allocate(putseed(seedsze))
  76. putseed(:)=13
  77. call random_seed(put=putseed)
  78. deallocate(putseed)
  79. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  80. !Get model dimensions - first step on the path to a model-independent EnKF
  81. call parse_blkdat('idm ','integer',rdummy,idm)
  82. call parse_blkdat('jdm ','integer',rdummy,jdm)
  83. call parse_blkdat('kdm ','integer',rdummy,kdm)
  84. ! Allocate model grid
  85. allocate(modlon(idm,jdm))
  86. allocate(modlat(idm,jdm))
  87. allocate(depths(idm,jdm))
  88. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  89. ! Read measurements and store in d
  90. if (master) then
  91. print*,' '
  92. print*,'Start reading files, calling obs_readobs()'
  93. end if
  94. call obs_readobs
  95. if (master) then
  96. print '(2a,i6)', obs(1)%id,' Number of obs =',nobs
  97. print '(2a,2f6.2)', obs(1)%id,'first obs and var= ',obs(1)%d, obs(1)%var
  98. print '(2a,2f6.2)', obs(nobs)%id,'last obs and var= ',obs(nobs)%d, obs(nobs)%var
  99. end if
  100. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  101. !Get model grid
  102. if (master) then
  103. print*,' '
  104. print*,'EnKF: Start reading files, get_mod_grid'
  105. end if
  106. call get_mod_grid(modlon,modlat,depths,mindx,meandx,idm,jdm)
  107. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  108. ! Read ensemble and store in A
  109. nrens=get_mod_nrens(idm,jdm)
  110. if (master) print *,'NR ENS (available) = ',nrens,' !!!!'
  111. !call stop_mpi()
  112. if (master) then
  113. print*,'EnKF: Start calculations of input to the analysis'
  114. end if
  115. allocate(S(nobs, nrens), d(nobs))
  116. allocate(meanD(nobs), meanS(nobs))
  117. time0 = rtc()
  118. ! KAL -- move ssh stuff in here, as well as reading "observed" variable
  119. call uobs_get(obs%id, nobs, .true.)
  120. call obs_prepareobs
  121. print*, 'Unique obs ', unique_obs(:)
  122. call prep_4_EnKF(nrens,d,S,depths,meandx*0.001,idm,jdm,kdm)
  123. print *,'prep_4_EnKF ferdig'
  124. ! mean innovations
  125. ! old code (allegedly wrong - PS)
  126. !
  127. !meanD(:)=0.
  128. !do j=1,nrens
  129. ! do i=1,nobs
  130. ! meanD(i)=meanD(i)+D(i,j)
  131. ! enddo
  132. !enddo
  133. !meanD(:)=meanD(:)/real(nrens)
  134. meanD(1 : nobs) = obs(1 : nobs) % d - meanS(1 : nobs)
  135. ! Innovation RMS without obs. perturbations
  136. allocate(RMSD(nobs))
  137. RMSD(:)=0.
  138. do i=1,nobs
  139. RMSD(i)=RMSD(i)+meanD(i)**2
  140. enddo
  141. RMSD(:)=sqrt(RMSD(:))
  142. ! observation std. deviation
  143. allocate(RMSE(nobs))
  144. RMSE(:)=0.
  145. do j=1,nrens
  146. do i=1,nobs
  147. RMSE(i)=RMSE(i)+E(i,j)**2
  148. enddo
  149. enddo
  150. RMSE(:)=sqrt(RMSE(:)/real(nrens-1))
  151. ! model std. deviation
  152. allocate(RMSS(nobs))
  153. RMSS(:)=0.
  154. do j=1,nrens
  155. do i=1,nobs
  156. RMSS(i)=RMSS(i)+S(i,j)**2
  157. enddo
  158. enddo
  159. RMSS(:)=sqrt(RMSS(:)/real(nrens-1))
  160. print *,'obs stats ferdig'
  161. ! In case there are more than 1 obs -- order them in this mask
  162. allocate(mask_obs(nobs))
  163. ! nuobs=1
  164. ! unique_obs(nuobs)=obs(1)%id
  165. ! do i=1,nobs
  166. ! if (all(unique_obs(1:nuobs)/=obs(i)%id)) then
  167. ! nuobs=nuobs+1
  168. !
  169. ! if (nuobs>maxnuobs) then
  170. ! print *, '(obsstats: too many unique obs ids)'
  171. ! call exit(1)
  172. ! end if
  173. !
  174. ! unique_obs(nuobs)=obs(i)%id
  175. ! end if
  176. ! end do
  177. do iuobs=1,nuobs
  178. where ( obs%id == unique_obs(iuobs) ) mask_obs=iuobs
  179. end do
  180. print *,'obs mask done'
  181. ! Produce tec fields - should be split into several files/zones if observations
  182. ! are of different types
  183. open(10,file='innovationstats.tec',status='replace')
  184. write(10,*)'TITLE = "innovation statistics"'
  185. write(10,*)'VARIABLES = "i-index" "j-index" "lon" "lat" "meaninnov"' // &
  186. '"RMSinnov" "stdobs" "stdmodel" "maskobs" '
  187. write(10,'(a,i7)')' ZONE F=BLOCK, I=',nobs
  188. write(10,900)(obs(i)%ipiv + obs(i)%a1 + obs(i)%a4,i=1,nobs)
  189. write(10,900)(obs(i)%jpiv + obs(i)%a2 + obs(i)%a3,i=1,nobs)
  190. write(10,900)(obs(i)%lon ,i=1,nobs)
  191. write(10,900)(obs(i)%lat ,i=1,nobs)
  192. write(10,900)(meanD(i) ,i=1,nobs)
  193. write(10,900)(RMSD (i) ,i=1,nobs)
  194. write(10,900)(RMSE (i) ,i=1,nobs)
  195. write(10,900)(RMSS (i) ,i=1,nobs)
  196. write(10,900)(mask_obs(i) ,i=1,nobs)
  197. close(10)
  198. 900 format(10(1x,e12.5))
  199. #if defined (MATLAB)
  200. ! Do the same for matlab -- only partly finished
  201. print *,'matlab'
  202. allocate(matio (nobs,1))
  203. mp=matopen('innovationstats.mat','w')
  204. matio(:,1)=obs(:)%lon
  205. pa1=mxCreateNumericMatrix(nobs,1,mxClassIDFromClassName('double'),0)
  206. call mxCopyReal8ToPtr(matio,mxGetPr(pa1),nobs)
  207. status = matPutVariable(mp, 'lon', pa1)
  208. matio(:,1)=obs(:)%lat
  209. pa1=mxCreateNumericMatrix(nobs,1,mxClassIDFromClassName('double'),0)
  210. call mxCopyReal8ToPtr(matio,mxGetPr(pa1),nobs)
  211. status = matPutVariable(mp, 'lat', pa1)
  212. matio(:,1)=meanD
  213. pa1=mxCreateNumericMatrix(nobs,1,mxClassIDFromClassName('double'),0)
  214. call mxCopyReal8ToPtr(matio,mxGetPr(pa1),nobs)
  215. status = matPutVariable(mp, 'mean_innov', pa1)
  216. #endif
  217. ! Netcdf - safest bet
  218. ncfile='innovationstats.nc'
  219. if (NF90_CREATE(trim(ncfile),NF90_CLOBBER,ncid) /= NF90_NOERR) then
  220. print *,'An error occured when opening the netcdf file'
  221. stop '(obsstats)'
  222. end if
  223. ierr2=NF90_DEF_DIM(ncid,'nobs',nobs,obsdim)
  224. ierr2=NF90_DEF_VAR(ncid,'lon',NF90_Float,obsdim,var_id)
  225. ierr2=NF90_ENDDEF(ncid)
  226. ierr2=NF90_PUT_VAR(ncid,var_id,obs(:)%lon)
  227. ierr2=NF90_REDEF(ncid)
  228. ierr2=NF90_DEF_VAR(ncid,'lat',NF90_Float,obsdim,var_id)
  229. ierr2=NF90_ENDDEF(ncid)
  230. ierr2=NF90_PUT_VAR(ncid,var_id,obs(:)%lat)
  231. ierr2=NF90_REDEF(ncid)
  232. ierr2=NF90_DEF_VAR(ncid,'meaninnov',NF90_Float,obsdim,var_id)
  233. ierr2=NF90_ENDDEF(ncid)
  234. ierr2=NF90_PUT_VAR(ncid,var_id,meanD)
  235. ierr2=NF90_REDEF(ncid)
  236. ierr2=NF90_DEF_VAR(ncid,'RMSinnov',NF90_Float,obsdim,var_id)
  237. ierr2=NF90_ENDDEF(ncid)
  238. ierr2=NF90_PUT_VAR(ncid,var_id,RMSD)
  239. ierr2=NF90_REDEF(ncid)
  240. ierr2=NF90_DEF_VAR(ncid,'varobs',NF90_Float,obsdim,var_id)
  241. ierr2=NF90_ENDDEF(ncid)
  242. ierr2=NF90_PUT_VAR(ncid,var_id,RMSE)
  243. ierr2=NF90_REDEF(ncid)
  244. ierr2=NF90_DEF_VAR(ncid,'varmodel',NF90_Float,obsdim,var_id)
  245. ierr2=NF90_ENDDEF(ncid)
  246. ierr2=NF90_PUT_VAR(ncid,var_id,RMSS)
  247. ierr2=NF90_REDEF(ncid)
  248. ierr2=NF90_DEF_VAR(ncid,'maskobs',NF90_Float,obsdim,var_id)
  249. ierr2=NF90_ENDDEF(ncid)
  250. ierr2=NF90_PUT_VAR(ncid,var_id,mask_obs)
  251. ierr2=NF90_CLOSE(ncid)
  252. ! Global stats
  253. print *,'Global mean innovation : ',sum(meanD(1 : nobs))/nobs
  254. print *,'Global mean innovation RMS : ',sum(RMSD(1 : nobs))/nobs
  255. print *,'Global mean obs variance : ',sum(RMSE(1 : nobs))/nobs
  256. print *,'Global mean model variance : ',sum(RMSS(1 : nobs))/nobs
  257. ! Regional stats - only if the file below exists
  258. inquire(exist=ex,file='EnKF_regstats.in',iostat=ios)
  259. if (ios.ne.0) stop 'obsstat: error opening EnKF_regstats.in'
  260. if (ex) then
  261. allocate(pointinbox(nobs))
  262. print *,'Found EnKF_regstats.in - producing regional statistics'
  263. open(10,file='EnKF_regstats.in',status='old')
  264. do while (ios==0)
  265. read(10,'(a)',iostat=ios) regname
  266. if (ios/=0) cycle
  267. read(10,*,iostat=ios) numcorners
  268. print *, 'Region is ', regname, ' and has ', numcorners, ' corners'
  269. if (numcorners>maxcorners) then
  270. print *,'obsstats can only handle ',maxcorners,' corners'
  271. call exit(1)
  272. end if
  273. read(10,*,iostat=ios) crnlon(1:numcorners)
  274. read(10,*,iostat=ios) crnlat(1:numcorners)
  275. ! Find points in box
  276. pointinbox=0
  277. do i=1,nobs
  278. if ( inbox(crnlon,crnlat,numcorners,obs(i)%lon,obs(i)%lat)) &
  279. pointinbox(i)=1
  280. end do
  281. print *,'Total nobs :',nobs
  282. print *,'Total in testbox:',sum(pointinbox)
  283. nrobsbox=sum(pointinbox)
  284. if (nrobsbox==0) cycle
  285. print *,trim(regname)//' mean innovation : ',sum(meanD(1:nobs)*pointinbox(1:nobs))/nrobsbox
  286. print *,trim(regname)//' mean innovation RMS : ',sum(RMSD*pointinbox )/nrobsbox
  287. print *,trim(regname)//' mean obs variance : ',sum(RMSE*pointinbox )/nrobsbox
  288. print *,trim(regname)//' mean model variance : ',sum(RMSS*pointinbox )/nrobsbox
  289. end do
  290. close (10)
  291. else
  292. print *,'EnKF_regstats.in not found - skipping regional statistics'
  293. end if
  294. print*,'obsstats: Finished'
  295. end program