MOmF_output.F90 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886
  1. ! First include the set of model-wide compiler flags
  2. #include "tm5.inc"
  3. ! Macro
  4. #define IF_ERROR_RETURN(action) if (status> 0) then; TRACEBACK; action; return; end if
  5. #define TRACEBACK write (gol,'("in ",a," (",a,i6,")")') rname, __FILE__, __LINE__ ; call goErr
  6. #define IF_NOTOK_RETURN(action) if (status/=0) then; TRACEBACK; action; return; end if
  7. #define IF_NOTOK_MDF(action) if (status/=0) then; TRACEBACK; action; call MDF_CLose(fid,status); status=1; return; end if
  8. ! integer, parameter :: sp = selected_real_kind(6, 37)
  9. ! integer, parameter :: dp = selected_real_kind(15, 307)
  10. !=====================================================================
  11. !
  12. ! Write OmF information to netcdf file, with one file per orbit
  13. !
  14. ! Henk Eskes, KNMI, Aug 2016
  15. !======================================================================
  16. module MOmF_output
  17. ! printing, error handling
  18. use GO, only : gol, goPr, goErr, goLabel
  19. ! Observational input (slant columns) is stored in this structure
  20. use MTObsTrack, only : TObsTrack
  21. ! Storage for retrieval results (vertical columns)
  22. use MTObsFcInfo, only : TObsFcInfo
  23. ! Storage superobservations
  24. use MOmFSuper, only : TObsInfoReduced
  25. ! output makes use of the MDF module
  26. use MDF
  27. implicit none
  28. private
  29. public :: OmF_Output
  30. !-------------------------------------------------------------
  31. character(len=*), parameter :: dataset_author = 'Henk Eskes'
  32. character(len=*), parameter :: institution = 'KNMI'
  33. ! character(len=*) :: dataset_version =
  34. character(len=*), parameter :: mname = 'MOmF_output'
  35. ! type for netcdf file access, storing id's of datasets
  36. type TPFile_OmF
  37. integer :: trec
  38. integer :: ncid
  39. ! dimension id
  40. integer :: dimid_nobs
  41. integer :: dimid_nobs_super_fc, dimid_nobs_super_an
  42. integer :: dimid_tm5_im, dimid_tm5_jm
  43. ! individual observations
  44. integer :: varid_lon, varid_lat, varid_icell, varid_jcell
  45. integer :: varid_vza, varid_sza, varid_aza
  46. integer :: varid_slc, varid_slcerr, varid_cf, varid_cp
  47. integer :: varid_slcfc, varid_slcan
  48. integer :: varid_fcerr, varid_tropfrac
  49. ! superobservations
  50. integer :: varid_sup_obsi_fc, varid_sup_obsj_fc
  51. integer :: varid_sup_obsi_an, varid_sup_obsj_an
  52. integer :: varid_sup_slcobs, varid_sup_slcfc, varid_sup_slcan
  53. ! TM5 2D fields
  54. integer :: varid_tm5_lon, varid_tm5_lat
  55. integer :: varid_tm5_no2col_fc, varid_tm5_no2col_an, varid_tm5_no2col_AmF
  56. ! gridded fields
  57. integer :: varid_grid_sup_o, varid_grid_sup_f
  58. integer :: varid_grid_sup_omf, varid_grid_sup_oma, varid_grid_sup_amf
  59. end type TPFile_OmF
  60. ! share varid and dimid between subroutines
  61. type(TPFile_OmF) :: omff
  62. ! parallel netcdf or not ...
  63. integer :: access_mode ! netcdf-4 access mode
  64. integer :: fid ! for NOTOK_MDF macro
  65. ! Undefined value
  66. real, parameter :: undef = -999.99
  67. contains
  68. subroutine OmF_Output( no2Tr, obsFcInfo, obsFcInfoReduced, NO2VCForecastError, im, jm, tm_lon, tm_lat, tm_no2col_fc, TM5_date, filedir, status, obsAnInfo, obsAnInfoReduced, tm_no2col_an )
  69. implicit none
  70. ! in/out
  71. ! Storage of track data: NO2 and cloud info
  72. type(TObsTrack), intent(inout) :: no2Tr
  73. ! observations and model forecast
  74. type(TObsFcInfo), intent(inout) :: obsFcInfo
  75. ! clustered superobservations
  76. type(TObsInfoReduced), intent(inout) :: obsFcInfoReduced
  77. ! the 2D model column forecast error distribution
  78. real, dimension(:,:), intent(in) :: NO2VCForecastError
  79. ! TM5 2D NO2 field
  80. integer, intent(in) :: im, jm
  81. real, dimension(im), intent(in) :: tm_lon
  82. real, dimension(jm), intent(in) :: tm_lat
  83. real, dimension(im,jm), intent(in) :: tm_no2col_fc
  84. ! other
  85. integer, dimension(6), intent(in) :: TM5_date
  86. character(len=*), intent(in) :: filedir
  87. integer, intent(out) :: status
  88. ! optional (analysis)
  89. type(TObsFcInfo), intent(inout), optional :: obsAnInfo
  90. type(TObsInfoReduced), intent(inout), optional :: obsAnInfoReduced
  91. real, dimension(im,jm), intent(in), optional :: tm_no2col_an
  92. ! local
  93. logical :: includeAnalysis
  94. character(len=*), parameter :: rname = trim(mname)//'/OmF_Output'
  95. ! begin code
  96. status = 0
  97. if ( present(obsAnInfo) .and. present(obsAnInfoReduced) .and. present(tm_no2col_an) ) then
  98. print *, 'OmF_Output: output for both forecast and analysis'
  99. includeAnalysis = .true.
  100. call OmF_Output_Init( no2Tr, im, jm, TM5_date, includeAnalysis, filedir, obsFcInfoReduced%count, obsAnInfoReduced%count, status )
  101. IF_NOTOK_RETURN(status=1)
  102. call OmF_Output_Write( no2Tr, obsFcInfo, obsFcInfoReduced, NO2VCForecastError, im, jm, tm_lon, tm_lat, tm_no2col_fc, includeAnalysis, status, obsAnInfo, obsAnInfoReduced, tm_no2col_an )
  103. IF_NOTOK_RETURN(status=1)
  104. else
  105. print *, 'OmF_Output: output for forecast only'
  106. includeAnalysis = .false.
  107. call OmF_Output_Init( no2Tr, im, jm, TM5_date, includeAnalysis, filedir, obsFcInfoReduced%count, 0, status )
  108. IF_NOTOK_RETURN(status=1)
  109. call OmF_Output_Write( no2Tr, obsFcInfo, obsFcInfoReduced, NO2VCForecastError, im, jm, tm_lon, tm_lat, tm_no2col_fc, includeAnalysis, status )
  110. IF_NOTOK_RETURN(status=1)
  111. end if
  112. call OmF_Output_Done( status )
  113. IF_NOTOK_RETURN(status=1)
  114. print *, 'OmF_Output: done'
  115. end subroutine OmF_Output
  116. subroutine OmF_Output_Init( no2Tr, im, jm, TM5_date, includeAnalysis, filedir, nobs_sup_fc, nobs_sup_an, status )
  117. !
  118. ! Open OmF netcdf output file, define arrays and attributes
  119. !
  120. use partools, only : MPI_INFO_NULL, localComm
  121. implicit none
  122. ! in/out
  123. type(TObsTrack), intent(inout) :: no2Tr
  124. integer, intent(in) :: im, jm
  125. integer, dimension(6), intent(in) :: TM5_date
  126. logical, intent(in) :: includeAnalysis
  127. character(len=*), intent(in) :: filedir
  128. integer, intent(in) :: nobs_sup_fc, nobs_sup_an
  129. integer, intent(out) :: status
  130. ! local
  131. character(len=*), parameter :: rname = trim(mname)//'/OmF_Output_Init'
  132. character(len=256) :: fname
  133. integer :: varid
  134. integer :: rtype
  135. ! --- begin -------------------------------------
  136. call goLabel(rname)
  137. ! o open file
  138. ! write filename
  139. write (fname,'(a,"/",a,"_o",i5.5,".nc")') &
  140. trim(filedir), 'omf', no2Tr%orbitNumber
  141. print *, 'OmF_Output: file = ',trim(fname)
  142. !#ifdef MPI
  143. ! ! overwrite existing files (clobber), provide MPI stuff:
  144. ! call MDF_Create( trim(fname), MDF_NETCDF4, MDF_REPLACE, omff%ncid, status, &
  145. ! mpi_comm=localComm, mpi_info=MPI_INFO_NULL )
  146. ! if (status/=0) then
  147. ! write (gol,'("from creating NetCDF4 file for writing in parallel;")'); call goErr
  148. ! write (gol,'("MDF module not compiled with netcdf4_par support ?")'); call goErr
  149. ! TRACEBACK; status=1; return
  150. ! end if
  151. !#else
  152. ! overwrite existing files (clobber)
  153. call MDF_Create( trim(fname), MDF_NETCDF4, MDF_REPLACE, omff%ncid, status )
  154. IF_NOTOK_RETURN(status=1)
  155. !#endif
  156. ! o global attributes
  157. call MDF_Put_Att( omff%ncid, MDF_GLOBAL, 'Title', 'Obsevation-minus-forecast output' , status)
  158. IF_NOTOK_MDF(fid=omff%ncid)
  159. call MDF_Put_Att( omff%ncid, MDF_GLOBAL, 'DatasetAuthor' , trim(dataset_author) , status)
  160. IF_NOTOK_MDF(fid=omff%ncid)
  161. call MDF_Put_Att( omff%ncid, MDF_GLOBAL, 'Institution' , trim(institution) , status)
  162. IF_NOTOK_MDF(fid=omff%ncid)
  163. call MDF_Put_Att( omff%ncid, MDF_GLOBAL, 'TM5_DateTime' , TM5_date , status)
  164. IF_NOTOK_MDF(fid=omff%ncid)
  165. call MDF_Put_Att( omff%ncid, MDF_GLOBAL, 'L2_OrbitFilename' , trim(no2Tr%orbitParts(1)%filename), status)
  166. IF_NOTOK_MDF(fid=omff%ncid)
  167. ! o define dimensions
  168. call MDF_Def_Dim( omff%ncid, 'nObs', no2Tr%count, omff%dimid_nobs, status )
  169. IF_NOTOK_MDF(fid=omff%ncid)
  170. call MDF_Def_Dim( omff%ncid, 'nObsSuper_fc', nObs_sup_fc, omff%dimid_nobs_super_fc, status )
  171. IF_NOTOK_MDF(fid=omff%ncid)
  172. if ( includeAnalysis ) then
  173. ! there may be less analysis than fc superobs (not more)
  174. call MDF_Def_Dim( omff%ncid, 'nObsSuper_an', nObs_sup_an, omff%dimid_nobs_super_an, status )
  175. IF_NOTOK_MDF(fid=omff%ncid)
  176. end if
  177. call MDF_Def_Dim( omff%ncid, 'lon', im, omff%dimid_tm5_im, status )
  178. IF_NOTOK_MDF(fid=omff%ncid)
  179. call MDF_Def_Dim( omff%ncid, 'lat', jm, omff%dimid_tm5_jm, status )
  180. IF_NOTOK_MDF(fid=omff%ncid)
  181. !#ifdef MPI
  182. !#ifdef with_netcdf4_par
  183. ! access_mode = MDF_COLLECTIVE
  184. !#else
  185. ! write(gol,'("Time Series output (PDUMP) requires netcdf4 with parallel access enabled")') ; call goErr
  186. ! TRACEBACK
  187. ! status=1; return
  188. !#endif
  189. !#else
  190. access_mode = MDF_INDEPENDENT
  191. !#endif
  192. ! o define variables
  193. call MDF_Def_Var( omff%ncid, 'obs_lon_fc', MDF_FLOAT, (/omff%dimid_nobs/), varid , status)
  194. IF_NOTOK_MDF(fid=omff%ncid)
  195. call MDF_Var_Par_Access( omff%ncid, varid, access_mode, status )
  196. IF_NOTOK_MDF(fid=omff%ncid)
  197. call MDF_Put_Att( omff%ncid, varid, 'standard_name', 'longitude' , status)
  198. IF_NOTOK_MDF(fid=omff%ncid)
  199. call MDF_Put_Att( omff%ncid, varid, 'long_name', 'longitude' , status)
  200. IF_NOTOK_MDF(fid=omff%ncid)
  201. call MDF_Put_Att( omff%ncid, varid, 'units', 'degrees_east' , status)
  202. IF_NOTOK_MDF(fid=omff%ncid)
  203. omff%varid_lon = varid
  204. call MDF_Def_Var( omff%ncid, 'obs_lat_fc', MDF_FLOAT, (/omff%dimid_nobs/), varid , status)
  205. IF_NOTOK_MDF(fid=omff%ncid)
  206. call MDF_Var_Par_Access( omff%ncid, varid, access_mode, status )
  207. IF_NOTOK_MDF(fid=omff%ncid)
  208. call MDF_Put_Att( omff%ncid, varid, 'standard_name', 'latitude' , status)
  209. IF_NOTOK_MDF(fid=omff%ncid)
  210. call MDF_Put_Att( omff%ncid, varid, 'long_name', 'latitude' , status)
  211. IF_NOTOK_MDF(fid=omff%ncid)
  212. call MDF_Put_Att( omff%ncid, varid, 'units', 'degrees_north' , status)
  213. IF_NOTOK_MDF(fid=omff%ncid)
  214. omff%varid_lat = varid
  215. call MDF_Def_Var( omff%ncid, 'icell_fc', MDF_INT, (/omff%dimid_nobs/), varid , status)
  216. IF_NOTOK_MDF(fid=omff%ncid)
  217. call MDF_Var_Par_Access( omff%ncid, varid, access_mode, status )
  218. IF_NOTOK_MDF(fid=omff%ncid)
  219. call MDF_Put_Att( omff%ncid, varid, 'standard_name', 'tm5_cell_index_lon' , status)
  220. IF_NOTOK_MDF(fid=omff%ncid)
  221. call MDF_Put_Att( omff%ncid, varid, 'long_name', 'East-West index of the TM5 cell' , status)
  222. IF_NOTOK_MDF(fid=omff%ncid)
  223. call MDF_Put_Att( omff%ncid, varid, 'units', '-' , status)
  224. IF_NOTOK_MDF(fid=omff%ncid)
  225. omff%varid_icell = varid
  226. call MDF_Def_Var( omff%ncid, 'jcell_fc', MDF_INT, (/omff%dimid_nobs/), varid , status)
  227. IF_NOTOK_MDF(fid=omff%ncid)
  228. call MDF_Var_Par_Access( omff%ncid, varid, access_mode, status )
  229. IF_NOTOK_MDF(fid=omff%ncid)
  230. call MDF_Put_Att( omff%ncid, varid, 'standard_name', 'tm5_cell_index_lat' , status)
  231. IF_NOTOK_MDF(fid=omff%ncid)
  232. call MDF_Put_Att( omff%ncid, varid, 'long_name', 'North-South index of the TM5 cell' , status)
  233. IF_NOTOK_MDF(fid=omff%ncid)
  234. call MDF_Put_Att( omff%ncid, varid, 'units', '-' , status)
  235. IF_NOTOK_MDF(fid=omff%ncid)
  236. omff%varid_jcell = varid
  237. call MDF_Def_Var( omff%ncid, 'vza_fc', MDF_FLOAT, (/omff%dimid_nobs/), varid , status)
  238. IF_NOTOK_MDF(fid=omff%ncid)
  239. call MDF_Var_Par_Access( omff%ncid, varid, access_mode, status )
  240. IF_NOTOK_MDF(fid=omff%ncid)
  241. call MDF_Put_Att( omff%ncid, varid, 'standard_name', 'viewing zenith angle' , status)
  242. IF_NOTOK_MDF(fid=omff%ncid)
  243. call MDF_Put_Att( omff%ncid, varid, 'long_name', 'viewing zenith angle at the surface' , status)
  244. IF_NOTOK_MDF(fid=omff%ncid)
  245. call MDF_Put_Att( omff%ncid, varid, 'units', 'degree' , status)
  246. IF_NOTOK_MDF(fid=omff%ncid)
  247. omff%varid_vza = varid
  248. call MDF_Def_Var( omff%ncid, 'sza_fc', MDF_FLOAT, (/omff%dimid_nobs/), varid , status)
  249. IF_NOTOK_MDF(fid=omff%ncid)
  250. call MDF_Var_Par_Access( omff%ncid, varid, access_mode, status )
  251. IF_NOTOK_MDF(fid=omff%ncid)
  252. call MDF_Put_Att( omff%ncid, varid, 'standard_name', 'solar zenith angle' , status)
  253. IF_NOTOK_MDF(fid=omff%ncid)
  254. call MDF_Put_Att( omff%ncid, varid, 'long_name', 'solar zenith angle at the surface' , status)
  255. IF_NOTOK_MDF(fid=omff%ncid)
  256. call MDF_Put_Att( omff%ncid, varid, 'units', 'degree' , status)
  257. IF_NOTOK_MDF(fid=omff%ncid)
  258. omff%varid_sza = varid
  259. !call MDF_Def_Var( omff%ncid, 'aza', MDF_FLOAT, (/omff%dimid_nobs/), varid , status)
  260. !IF_NOTOK_MDF(fid=omff%ncid)
  261. !call MDF_Var_Par_Access( omff%ncid, varid, access_mode, status )
  262. !IF_NOTOK_MDF(fid=omff%ncid)
  263. !call MDF_Put_Att( omff%ncid, varid, 'standard_name', 'relative azimuth angle' , status)
  264. !IF_NOTOK_MDF(fid=omff%ncid)
  265. !call MDF_Put_Att( omff%ncid, varid, 'long_name', 'relative azimuth angle' , status)
  266. !IF_NOTOK_MDF(fid=omff%ncid)
  267. !call MDF_Put_Att( omff%ncid, varid, 'units', 'degree' , status)
  268. !IF_NOTOK_MDF(fid=omff%ncid)
  269. !omff%varid_aza = varid
  270. call MDF_Def_Var( omff%ncid, 'slc_fc', MDF_FLOAT, (/omff%dimid_nobs/), varid , status)
  271. IF_NOTOK_MDF(fid=omff%ncid)
  272. call MDF_Var_Par_Access( omff%ncid, varid, access_mode, status )
  273. IF_NOTOK_MDF(fid=omff%ncid)
  274. call MDF_Put_Att( omff%ncid, varid, 'standard_name', 'slant column' , status)
  275. IF_NOTOK_MDF(fid=omff%ncid)
  276. call MDF_Put_Att( omff%ncid, varid, 'long_name', 'NO2 slant column divided by the geometrical AMF' , status)
  277. IF_NOTOK_MDF(fid=omff%ncid)
  278. call MDF_Put_Att( omff%ncid, varid, 'units', '10^15 molecules cm^-2' , status)
  279. IF_NOTOK_MDF(fid=omff%ncid)
  280. omff%varid_slc = varid
  281. call MDF_Def_Var( omff%ncid, 'slc_uncertainty_fc', MDF_FLOAT, (/omff%dimid_nobs/), varid , status)
  282. IF_NOTOK_MDF(fid=omff%ncid)
  283. call MDF_Var_Par_Access( omff%ncid, varid, access_mode, status )
  284. IF_NOTOK_MDF(fid=omff%ncid)
  285. call MDF_Put_Att( omff%ncid, varid, 'standard_name', 'slant column uncertainty' , status)
  286. IF_NOTOK_MDF(fid=omff%ncid)
  287. call MDF_Put_Att( omff%ncid, varid, 'long_name', 'Relative NO2 slant column uncertainty (%)' , status)
  288. IF_NOTOK_MDF(fid=omff%ncid)
  289. call MDF_Put_Att( omff%ncid, varid, 'units', '%' , status)
  290. IF_NOTOK_MDF(fid=omff%ncid)
  291. omff%varid_slcerr = varid
  292. call MDF_Def_Var( omff%ncid, 'cloudFraction_fc', MDF_FLOAT, (/omff%dimid_nobs/), varid , status)
  293. IF_NOTOK_MDF(fid=omff%ncid)
  294. call MDF_Var_Par_Access( omff%ncid, varid, access_mode, status )
  295. IF_NOTOK_MDF(fid=omff%ncid)
  296. call MDF_Put_Att( omff%ncid, varid, 'standard_name', 'cloud fraction' , status)
  297. IF_NOTOK_MDF(fid=omff%ncid)
  298. call MDF_Put_Att( omff%ncid, varid, 'long_name', 'fraction of satellite footprint covered with clouds' , status)
  299. IF_NOTOK_MDF(fid=omff%ncid)
  300. call MDF_Put_Att( omff%ncid, varid, 'units', '-' , status)
  301. IF_NOTOK_MDF(fid=omff%ncid)
  302. omff%varid_cf = varid
  303. call MDF_Def_Var( omff%ncid, 'cloudTopPressure', MDF_FLOAT, (/omff%dimid_nobs/), varid , status)
  304. IF_NOTOK_MDF(fid=omff%ncid)
  305. call MDF_Var_Par_Access( omff%ncid, varid, access_mode, status )
  306. IF_NOTOK_MDF(fid=omff%ncid)
  307. call MDF_Put_Att( omff%ncid, varid, 'standard_name', 'cloud pressure' , status)
  308. IF_NOTOK_MDF(fid=omff%ncid)
  309. call MDF_Put_Att( omff%ncid, varid, 'long_name', 'effective cloud top pressure' , status)
  310. IF_NOTOK_MDF(fid=omff%ncid)
  311. call MDF_Put_Att( omff%ncid, varid, 'units', 'hPa' , status)
  312. IF_NOTOK_MDF(fid=omff%ncid)
  313. omff%varid_cp = varid
  314. call MDF_Def_Var( omff%ncid, 'no2_slc_fc', MDF_FLOAT, (/omff%dimid_nobs/), varid , status)
  315. IF_NOTOK_MDF(fid=omff%ncid)
  316. call MDF_Var_Par_Access( omff%ncid, varid, access_mode, status )
  317. IF_NOTOK_MDF(fid=omff%ncid)
  318. call MDF_Put_Att( omff%ncid, varid, 'standard_name', 'model forecast slant column' , status)
  319. IF_NOTOK_MDF(fid=omff%ncid)
  320. call MDF_Put_Att( omff%ncid, varid, 'long_name', 'model NO2 forecast slant column divided by the geometrical AMF' , status)
  321. IF_NOTOK_MDF(fid=omff%ncid)
  322. call MDF_Put_Att( omff%ncid, varid, 'units', '10^15 molecules cm^-2' , status)
  323. IF_NOTOK_MDF(fid=omff%ncid)
  324. omff%varid_slcfc = varid
  325. if ( includeAnalysis ) then
  326. call MDF_Def_Var( omff%ncid, 'no2_slc_an', MDF_FLOAT, (/omff%dimid_nobs/), varid , status)
  327. IF_NOTOK_MDF(fid=omff%ncid)
  328. call MDF_Var_Par_Access( omff%ncid, varid, access_mode, status )
  329. IF_NOTOK_MDF(fid=omff%ncid)
  330. call MDF_Put_Att( omff%ncid, varid, 'standard_name', 'model analysis slant column' , status)
  331. IF_NOTOK_MDF(fid=omff%ncid)
  332. call MDF_Put_Att( omff%ncid, varid, 'long_name', 'model NO2 analysis slant column divided by the geometrical AMF' , status )
  333. IF_NOTOK_MDF(fid=omff%ncid)
  334. call MDF_Put_Att( omff%ncid, varid, 'units', '10^15 molecules cm^-2' , status)
  335. IF_NOTOK_MDF(fid=omff%ncid)
  336. omff%varid_slcan = varid
  337. end if
  338. call MDF_Def_Var( omff%ncid, 'forecastError_fc', MDF_FLOAT, (/omff%dimid_nobs/), varid , status)
  339. IF_NOTOK_MDF(fid=omff%ncid)
  340. call MDF_Var_Par_Access( omff%ncid, varid, access_mode, status )
  341. IF_NOTOK_MDF(fid=omff%ncid)
  342. call MDF_Put_Att( omff%ncid, varid, 'standard_name', 'model forecast uncertainty, total column' , status)
  343. IF_NOTOK_MDF(fid=omff%ncid)
  344. call MDF_Put_Att( omff%ncid, varid, 'long_name', 'model NO2 vertical column uncertainty' , status)
  345. IF_NOTOK_MDF(fid=omff%ncid)
  346. call MDF_Put_Att( omff%ncid, varid, 'units', '10^15 molecules cm^-2' , status)
  347. IF_NOTOK_MDF(fid=omff%ncid)
  348. omff%varid_fcerr = varid
  349. call MDF_Def_Var( omff%ncid, 'tropFraction_fc', MDF_FLOAT, (/omff%dimid_nobs/), varid , status)
  350. IF_NOTOK_MDF(fid=omff%ncid)
  351. call MDF_Var_Par_Access( omff%ncid, varid, access_mode, status )
  352. IF_NOTOK_MDF(fid=omff%ncid)
  353. call MDF_Put_Att( omff%ncid, varid, 'standard_name', 'model tropospheric column fraction' , status)
  354. IF_NOTOK_MDF(fid=omff%ncid)
  355. call MDF_Put_Att( omff%ncid, varid, 'long_name', 'forecast NO2 tropospheric column divided by forecast total column' , status)
  356. IF_NOTOK_MDF(fid=omff%ncid)
  357. call MDF_Put_Att( omff%ncid, varid, 'units', '-' , status)
  358. IF_NOTOK_MDF(fid=omff%ncid)
  359. omff%varid_tropfrac = varid
  360. ! o superobservations
  361. call MDF_Def_Var( omff%ncid, 'sup_obsi_fc', MDF_INT, (/omff%dimid_nobs_super_fc/), varid , status)
  362. IF_NOTOK_MDF(fid=omff%ncid)
  363. call MDF_Var_Par_Access( omff%ncid, varid, access_mode, status )
  364. IF_NOTOK_MDF(fid=omff%ncid)
  365. call MDF_Put_Att( omff%ncid, varid, 'standard_name', 'superobs tm5_cell_index_lon' , status)
  366. IF_NOTOK_MDF(fid=omff%ncid)
  367. call MDF_Put_Att( omff%ncid, varid, 'long_name', 'East-West index of the TM5 cell of the superobservation' , status)
  368. IF_NOTOK_MDF(fid=omff%ncid)
  369. call MDF_Put_Att( omff%ncid, varid, 'units', '-' , status)
  370. IF_NOTOK_MDF(fid=omff%ncid)
  371. omff%varid_sup_obsi_fc = varid
  372. call MDF_Def_Var( omff%ncid, 'sup_obsj_fc', MDF_INT, (/omff%dimid_nobs_super_fc/), varid , status)
  373. IF_NOTOK_MDF(fid=omff%ncid)
  374. call MDF_Var_Par_Access( omff%ncid, varid, access_mode, status )
  375. IF_NOTOK_MDF(fid=omff%ncid)
  376. call MDF_Put_Att( omff%ncid, varid, 'standard_name', 'superobs tm5_cell_index_lat' , status)
  377. IF_NOTOK_MDF(fid=omff%ncid)
  378. call MDF_Put_Att( omff%ncid, varid, 'long_name', 'North-South index of the TM5 cell of the superobservation' , status)
  379. IF_NOTOK_MDF(fid=omff%ncid)
  380. call MDF_Put_Att( omff%ncid, varid, 'units', '-' , status)
  381. IF_NOTOK_MDF(fid=omff%ncid)
  382. omff%varid_sup_obsj_fc = varid
  383. call MDF_Def_Var( omff%ncid, 'sup_no2_slc_obs_fc', MDF_FLOAT, (/omff%dimid_nobs_super_fc/), varid, status)
  384. IF_NOTOK_MDF(fid=omff%ncid)
  385. call MDF_Var_Par_Access( omff%ncid, varid, access_mode, status )
  386. IF_NOTOK_MDF(fid=omff%ncid)
  387. call MDF_Put_Att( omff%ncid, varid, 'standard_name', 'superobservation slant column' , status)
  388. IF_NOTOK_MDF(fid=omff%ncid)
  389. call MDF_Put_Att( omff%ncid, varid, 'long_name', 'measured NO2 slant column divided by the geometrical AMF for the superobservation' , status)
  390. IF_NOTOK_MDF(fid=omff%ncid)
  391. call MDF_Put_Att( omff%ncid, varid, 'units', '10^15 molecules cm^-2' , status)
  392. IF_NOTOK_MDF(fid=omff%ncid)
  393. omff%varid_sup_slcobs = varid
  394. call MDF_Def_Var( omff%ncid, 'sup_no2_slc_fc', MDF_FLOAT, (/omff%dimid_nobs_super_fc/), varid, status)
  395. IF_NOTOK_MDF(fid=omff%ncid)
  396. call MDF_Var_Par_Access( omff%ncid, varid, access_mode, status )
  397. IF_NOTOK_MDF(fid=omff%ncid)
  398. call MDF_Put_Att( omff%ncid, varid, 'standard_name', 'superobs model forecast slant column' , status)
  399. IF_NOTOK_MDF(fid=omff%ncid)
  400. call MDF_Put_Att( omff%ncid, varid, 'long_name', 'model NO2 forecast slant column divided by the geometrical AMF for the superobservation' , status)
  401. IF_NOTOK_MDF(fid=omff%ncid)
  402. call MDF_Put_Att( omff%ncid, varid, 'units', '10^15 molecules cm^-2' , status)
  403. IF_NOTOK_MDF(fid=omff%ncid)
  404. omff%varid_sup_slcfc = varid
  405. if ( includeAnalysis ) then
  406. call MDF_Def_Var( omff%ncid, 'sup_no2_slc_an', MDF_FLOAT, (/omff%dimid_nobs_super_an/), varid, status)
  407. IF_NOTOK_MDF(fid=omff%ncid)
  408. call MDF_Var_Par_Access( omff%ncid, varid, access_mode, status )
  409. IF_NOTOK_MDF(fid=omff%ncid)
  410. call MDF_Put_Att( omff%ncid, varid, 'standard_name', 'superobs model analysis slant column' , status)
  411. IF_NOTOK_MDF(fid=omff%ncid)
  412. call MDF_Put_Att( omff%ncid, varid, 'long_name', 'model NO2 analysis slant column divided by the geometrical AMF for the superobservation' , status)
  413. IF_NOTOK_MDF(fid=omff%ncid)
  414. call MDF_Put_Att( omff%ncid, varid, 'units', '10^15 molecules cm^-2' , status)
  415. IF_NOTOK_MDF(fid=omff%ncid)
  416. omff%varid_sup_slcan = varid
  417. end if
  418. ! o TM5 NO2 field
  419. call MDF_Def_Var( omff%ncid, 'lon', MDF_FLOAT, (/omff%dimid_tm5_im/), varid, status)
  420. IF_NOTOK_MDF(fid=omff%ncid)
  421. call MDF_Var_Par_Access( omff%ncid, varid, access_mode, status )
  422. IF_NOTOK_MDF(fid=omff%ncid)
  423. call MDF_Put_Att( omff%ncid, varid, 'standard_name', 'longitude' , status)
  424. IF_NOTOK_MDF(fid=omff%ncid)
  425. call MDF_Put_Att( omff%ncid, varid, 'long_name', 'longitude' , status)
  426. IF_NOTOK_MDF(fid=omff%ncid)
  427. call MDF_Put_Att( omff%ncid, varid, 'units', 'degrees_east' , status)
  428. IF_NOTOK_MDF(fid=omff%ncid)
  429. omff%varid_tm5_lon = varid
  430. call MDF_Def_Var( omff%ncid, 'lat', MDF_FLOAT, (/omff%dimid_tm5_jm/), varid, status)
  431. IF_NOTOK_MDF(fid=omff%ncid)
  432. call MDF_Var_Par_Access( omff%ncid, varid, access_mode, status )
  433. IF_NOTOK_MDF(fid=omff%ncid)
  434. call MDF_Put_Att( omff%ncid, varid, 'standard_name', 'latitude' , status)
  435. IF_NOTOK_MDF(fid=omff%ncid)
  436. call MDF_Put_Att( omff%ncid, varid, 'long_name', 'latitude' , status)
  437. IF_NOTOK_MDF(fid=omff%ncid)
  438. call MDF_Put_Att( omff%ncid, varid, 'units', 'degrees_north' , status)
  439. IF_NOTOK_MDF(fid=omff%ncid)
  440. omff%varid_tm5_lat = varid
  441. call MDF_Def_Var( omff%ncid, 'tm5_no2col_fc', MDF_FLOAT, (/omff%dimid_tm5_im,omff%dimid_tm5_jm/), varid, status)
  442. IF_NOTOK_MDF(fid=omff%ncid)
  443. call MDF_Var_Par_Access( omff%ncid, varid, access_mode, status )
  444. IF_NOTOK_MDF(fid=omff%ncid)
  445. call MDF_Put_Att( omff%ncid, varid, 'standard_name', 'TM5 forecast NO2 column' , status)
  446. IF_NOTOK_MDF(fid=omff%ncid)
  447. call MDF_Put_Att( omff%ncid, varid, 'long_name', 'TM5 forecast NO2 column' , status)
  448. IF_NOTOK_MDF(fid=omff%ncid)
  449. call MDF_Put_Att( omff%ncid, varid, 'units', '10^15 molecules cm^-2' , status)
  450. IF_NOTOK_MDF(fid=omff%ncid)
  451. omff%varid_tm5_no2col_fc = varid
  452. if ( includeAnalysis ) then
  453. call MDF_Def_Var( omff%ncid, 'tm5_no2col_an', MDF_FLOAT, (/omff%dimid_tm5_im,omff%dimid_tm5_jm/), varid, status)
  454. IF_NOTOK_MDF(fid=omff%ncid)
  455. call MDF_Var_Par_Access( omff%ncid, varid, access_mode, status )
  456. IF_NOTOK_MDF(fid=omff%ncid)
  457. call MDF_Put_Att( omff%ncid, varid, 'standard_name', 'TM5 analysis NO2 column' , status)
  458. IF_NOTOK_MDF(fid=omff%ncid)
  459. call MDF_Put_Att( omff%ncid, varid, 'long_name', 'TM5 analysis NO2 column' , status)
  460. IF_NOTOK_MDF(fid=omff%ncid)
  461. call MDF_Put_Att( omff%ncid, varid, 'units', '10^15 molecules cm^-2' , status)
  462. IF_NOTOK_MDF(fid=omff%ncid)
  463. omff%varid_tm5_no2col_an = varid
  464. call MDF_Def_Var( omff%ncid, 'tm5_no2col_AmF', MDF_FLOAT, (/omff%dimid_tm5_im,omff%dimid_tm5_jm/), varid, status)
  465. IF_NOTOK_MDF(fid=omff%ncid)
  466. call MDF_Var_Par_Access( omff%ncid, varid, access_mode, status )
  467. IF_NOTOK_MDF(fid=omff%ncid)
  468. call MDF_Put_Att( omff%ncid, varid, 'standard_name', 'TM5 AmF NO2 column' , status)
  469. IF_NOTOK_MDF(fid=omff%ncid)
  470. call MDF_Put_Att( omff%ncid, varid, 'long_name', 'TM5 analysis-minus-forecast NO2 column' , status)
  471. IF_NOTOK_MDF(fid=omff%ncid)
  472. call MDF_Put_Att( omff%ncid, varid, 'units', '10^15 molecules cm^-2' , status)
  473. IF_NOTOK_MDF(fid=omff%ncid)
  474. omff%varid_tm5_no2col_AmF = varid
  475. end if
  476. ! o gridded fields
  477. call MDF_Def_Var( omff%ncid, 'grid_sup_o', MDF_FLOAT, (/omff%dimid_tm5_im,omff%dimid_tm5_jm/), varid, status)
  478. IF_NOTOK_MDF(fid=omff%ncid)
  479. call MDF_Var_Par_Access( omff%ncid, varid, access_mode, status )
  480. IF_NOTOK_MDF(fid=omff%ncid)
  481. call MDF_Put_Att( omff%ncid, varid, 'standard_name', 'gridded NO2 superobs', status)
  482. IF_NOTOK_MDF(fid=omff%ncid)
  483. call MDF_Put_Att( omff%ncid, varid, 'long_name', 'NO2 superobservations on the TM5 grid', status)
  484. IF_NOTOK_MDF(fid=omff%ncid)
  485. call MDF_Put_Att( omff%ncid, varid, 'units', '10^15 molecules cm^-2', status)
  486. IF_NOTOK_MDF(fid=omff%ncid)
  487. omff%varid_grid_sup_o = varid
  488. call MDF_Def_Var( omff%ncid, 'grid_sup_f', MDF_FLOAT, (/omff%dimid_tm5_im,omff%dimid_tm5_jm/), varid, status)
  489. IF_NOTOK_MDF(fid=omff%ncid)
  490. call MDF_Var_Par_Access( omff%ncid, varid, access_mode, status )
  491. IF_NOTOK_MDF(fid=omff%ncid)
  492. call MDF_Put_Att( omff%ncid, varid, 'standard_name', 'gridded NO2 forecast for superobs', status)
  493. IF_NOTOK_MDF(fid=omff%ncid)
  494. call MDF_Put_Att( omff%ncid, varid, 'long_name', 'NO2 forecast for the superobservations on the TM5 grid', status)
  495. IF_NOTOK_MDF(fid=omff%ncid)
  496. call MDF_Put_Att( omff%ncid, varid, 'units', '10^15 molecules cm^-2', status)
  497. IF_NOTOK_MDF(fid=omff%ncid)
  498. omff%varid_grid_sup_f = varid
  499. call MDF_Def_Var( omff%ncid, 'grid_sup_omf', MDF_FLOAT, (/omff%dimid_tm5_im,omff%dimid_tm5_jm/), varid, status)
  500. IF_NOTOK_MDF(fid=omff%ncid)
  501. call MDF_Var_Par_Access( omff%ncid, varid, access_mode, status )
  502. IF_NOTOK_MDF(fid=omff%ncid)
  503. call MDF_Put_Att( omff%ncid, varid, 'standard_name', 'gridded OmF for superobs', status)
  504. IF_NOTOK_MDF(fid=omff%ncid)
  505. call MDF_Put_Att( omff%ncid, varid, 'long_name', 'Observation-minus-forecast for the superobservations on the TM5 grid', status)
  506. IF_NOTOK_MDF(fid=omff%ncid)
  507. call MDF_Put_Att( omff%ncid, varid, 'units', '10^15 molecules cm^-2', status)
  508. IF_NOTOK_MDF(fid=omff%ncid)
  509. omff%varid_grid_sup_omf = varid
  510. if ( includeAnalysis ) then
  511. call MDF_Def_Var( omff%ncid, 'grid_sup_oma', MDF_FLOAT, (/omff%dimid_tm5_im,omff%dimid_tm5_jm/), varid, status)
  512. IF_NOTOK_MDF(fid=omff%ncid)
  513. call MDF_Var_Par_Access( omff%ncid, varid, access_mode, status )
  514. IF_NOTOK_MDF(fid=omff%ncid)
  515. call MDF_Put_Att( omff%ncid, varid, 'standard_name', 'gridded OmA for superobs', status)
  516. IF_NOTOK_MDF(fid=omff%ncid)
  517. call MDF_Put_Att( omff%ncid, varid, 'long_name', 'Observation-minus-analysis for the superobservations on the TM5 grid', status)
  518. IF_NOTOK_MDF(fid=omff%ncid)
  519. call MDF_Put_Att( omff%ncid, varid, 'units', '10^15 molecules cm^-2', status)
  520. IF_NOTOK_MDF(fid=omff%ncid)
  521. omff%varid_grid_sup_oma = varid
  522. call MDF_Def_Var( omff%ncid, 'grid_sup_amf', MDF_FLOAT, (/omff%dimid_tm5_im,omff%dimid_tm5_jm/), varid, status)
  523. IF_NOTOK_MDF(fid=omff%ncid)
  524. call MDF_Var_Par_Access( omff%ncid, varid, access_mode, status )
  525. IF_NOTOK_MDF(fid=omff%ncid)
  526. call MDF_Put_Att( omff%ncid, varid, 'standard_name', 'gridded AmF for superobs', status)
  527. IF_NOTOK_MDF(fid=omff%ncid)
  528. call MDF_Put_Att( omff%ncid, varid, 'long_name', 'Analysis-minus-forecast for the superobservations on the TM5 grid', status)
  529. IF_NOTOK_MDF(fid=omff%ncid)
  530. call MDF_Put_Att( omff%ncid, varid, 'units', '10^15 molecules cm^-2', status)
  531. IF_NOTOK_MDF(fid=omff%ncid)
  532. omff%varid_grid_sup_amf = varid
  533. end if
  534. ! o end defintion mode
  535. call MDF_EndDef( omff%ncid , status)
  536. IF_NOTOK_MDF(fid=omff%ncid)
  537. ! no records written yet
  538. omff%trec = 0
  539. call goLabel() ; status = 0
  540. end subroutine OmF_Output_Init
  541. subroutine OmF_Output_Write( no2Tr, obsFcInfo, obsFcInfoReduced, NO2VCForecastError, im, jm, tm_lon, tm_lat, tm_no2col_fc, includeAnalysis, status, obsAnInfo, obsAnInfoReduced, tm_no2col_an )
  542. implicit none
  543. !
  544. ! in/out
  545. ! Storage of track data: NO2 and cloud info
  546. type(TObsTrack), intent(inout) :: no2Tr
  547. ! observations and model forecast
  548. type(TObsFcInfo), intent(inout) :: obsFcInfo
  549. ! clustered superobservations
  550. type(TObsInfoReduced), intent(inout) :: obsFcInfoReduced
  551. ! the 2D model column forecast error distribution
  552. real, dimension(:,:), intent(in) :: NO2VCForecastError
  553. ! TM5 2D NO2 field
  554. integer, intent(in) :: im, jm
  555. real, dimension(im), intent(in) :: tm_lon
  556. real, dimension(jm), intent(in) :: tm_lat
  557. real, dimension(im,jm), intent(in) :: tm_no2col_fc
  558. logical, intent(in) :: includeAnalysis
  559. integer, intent(out) :: status
  560. ! optional (analysis structures)
  561. type(TObsFcInfo), intent(inout), optional :: obsAnInfo
  562. type(TObsInfoReduced), intent(inout), optional :: obsAnInfoReduced
  563. real, dimension(im,jm), intent(in), optional :: tm_no2col_an
  564. ! local
  565. character(len=*), parameter :: rname = trim(mname)//'/OmF_Output_Write'
  566. integer :: i, isup, isupfc, nObsSup
  567. real, dimension(:), allocatable :: fcerr, tropfrac
  568. real, dimension(:,:), allocatable :: tmfield
  569. real, dimension(:), allocatable :: s_slcfc
  570. ! --- begin -------------------------------------
  571. call goLabel(rname)
  572. call MDF_Put_Var( omff%ncid, omff%varid_lon, no2Tr%longitude, status)
  573. IF_NOTOK_MDF(fid=omff%ncid)
  574. call MDF_Put_Var( omff%ncid, omff%varid_lat, no2Tr%latitude, status)
  575. IF_NOTOK_MDF(fid=omff%ncid)
  576. call MDF_Put_Var( omff%ncid, omff%varid_icell, obsFcInfo%icell, status)
  577. IF_NOTOK_MDF(fid=omff%ncid)
  578. call MDF_Put_Var( omff%ncid, omff%varid_jcell, obsFcInfo%jcell, status)
  579. IF_NOTOK_MDF(fid=omff%ncid)
  580. call MDF_Put_Var( omff%ncid, omff%varid_vza, no2Tr%viewingZenithAngle, status)
  581. IF_NOTOK_MDF(fid=omff%ncid)
  582. call MDF_Put_Var( omff%ncid, omff%varid_sza, no2Tr%solarZenithAngle, status)
  583. IF_NOTOK_MDF(fid=omff%ncid)
  584. !call MDF_Put_Var( omff%ncid, omff%varid_aza, no2Tr%viewingAzimuthAngle, status)
  585. !IF_NOTOK_MDF(fid=omff%ncid)
  586. call MDF_Put_Var( omff%ncid, omff%varid_slc, no2Tr%no2slc/obsFcInfo%amfgeo, status)
  587. IF_NOTOK_MDF(fid=omff%ncid)
  588. call MDF_Put_Var( omff%ncid, omff%varid_slcerr, no2Tr%no2slcError, status)
  589. IF_NOTOK_MDF(fid=omff%ncid)
  590. call MDF_Put_Var( omff%ncid, omff%varid_cf, no2Tr%cloudFraction, status)
  591. IF_NOTOK_MDF(fid=omff%ncid)
  592. call MDF_Put_Var( omff%ncid, omff%varid_cp, no2Tr%cloudTopPressure, status)
  593. IF_NOTOK_MDF(fid=omff%ncid)
  594. call MDF_Put_Var( omff%ncid, omff%varid_slcfc, obsFcInfo%no2slcfc/obsFcInfo%amfgeo, status)
  595. IF_NOTOK_MDF(fid=omff%ncid)
  596. if ( includeAnalysis ) then
  597. call MDF_Put_Var( omff%ncid, omff%varid_slcan, obsAnInfo%no2slcfc/obsAnInfo%amfgeo, status)
  598. IF_NOTOK_MDF(fid=omff%ncid)
  599. end if
  600. allocate ( fcerr(obsFcInfo%count) )
  601. allocate ( tropfrac(obsFcInfo%count) )
  602. fcerr(:) = undef
  603. tropfrac(:) = undef
  604. do i = 1, obsFcInfo%count
  605. if ( iand(ObsFcInfo%flag(i), 255) == 0 ) then
  606. fcerr(i) = NO2VCForecastError(obsFcInfo%icell(i),obsFcInfo%jcell(i))
  607. tropfrac(i) = obsFcInfo%no2vcdfctrop(i)/obsFcInfo%no2vcdfc(i)
  608. end if
  609. end do
  610. call MDF_Put_Var( omff%ncid, omff%varid_fcerr, fcerr, status)
  611. IF_NOTOK_MDF(fid=omff%ncid)
  612. call MDF_Put_Var( omff%ncid, omff%varid_tropfrac, tropfrac, status)
  613. IF_NOTOK_MDF(fid=omff%ncid)
  614. deallocate ( fcerr )
  615. deallocate ( tropfrac )
  616. ! superobs
  617. call MDF_Put_Var( omff%ncid, omff%varid_sup_obsi_fc, obsFcInfoReduced%obsi, status)
  618. IF_NOTOK_MDF(fid=omff%ncid)
  619. call MDF_Put_Var( omff%ncid, omff%varid_sup_obsj_fc, obsFcInfoReduced%obsj, status)
  620. IF_NOTOK_MDF(fid=omff%ncid)
  621. call MDF_Put_Var( omff%ncid, omff%varid_sup_slcobs, obsFcInfoReduced%slcobs, status)
  622. IF_NOTOK_MDF(fid=omff%ncid)
  623. call MDF_Put_Var( omff%ncid, omff%varid_sup_slcfc, obsFcInfoReduced%slcfc, status)
  624. IF_NOTOK_MDF(fid=omff%ncid)
  625. if ( includeAnalysis ) then
  626. call MDF_Put_Var( omff%ncid, omff%varid_sup_slcan, obsAnInfoReduced%slcfc, status)
  627. IF_NOTOK_MDF(fid=omff%ncid)
  628. end if
  629. ! TM5 NO2 field
  630. call MDF_Put_Var( omff%ncid, omff%varid_tm5_lon, tm_lon, status )
  631. IF_NOTOK_MDF(fid=omff%ncid)
  632. call MDF_Put_Var( omff%ncid, omff%varid_tm5_lat, tm_lat, status )
  633. IF_NOTOK_MDF(fid=omff%ncid)
  634. call MDF_Put_Var( omff%ncid, omff%varid_tm5_no2col_fc, tm_no2col_fc, status )
  635. IF_NOTOK_MDF(fid=omff%ncid)
  636. if ( includeAnalysis ) then
  637. call MDF_Put_Var( omff%ncid, omff%varid_tm5_no2col_an, tm_no2col_an, status )
  638. IF_NOTOK_MDF(fid=omff%ncid)
  639. call MDF_Put_Var( omff%ncid, omff%varid_tm5_no2col_AmF, tm_no2col_an-tm_no2col_fc, status )
  640. IF_NOTOK_MDF(fid=omff%ncid)
  641. end if
  642. ! gridded results
  643. allocate ( tmfield(im,jm) )
  644. ! O for superobs on grid
  645. tmfield(:,:) = 0.0
  646. do isup = 1, obsFcInfoReduced%count
  647. tmfield(obsFcInfoReduced%obsi(isup),obsFcInfoReduced%obsj(isup)) = obsFcInfoReduced%slcobs(isup)
  648. end do
  649. call MDF_Put_Var( omff%ncid, omff%varid_grid_sup_o, tmfield, status )
  650. IF_NOTOK_MDF(fid=omff%ncid)
  651. ! F for superobs on grid
  652. tmfield(:,:) = 0.0
  653. do isup = 1, obsFcInfoReduced%count
  654. tmfield(obsFcInfoReduced%obsi(isup),obsFcInfoReduced%obsj(isup)) = obsFcInfoReduced%slcfc(isup)
  655. end do
  656. call MDF_Put_Var( omff%ncid, omff%varid_grid_sup_f, tmfield, status )
  657. IF_NOTOK_MDF(fid=omff%ncid)
  658. ! OmF for superobs on grid
  659. tmfield(:,:) = 0.0
  660. do isup = 1, obsFcInfoReduced%count
  661. tmfield(obsFcInfoReduced%obsi(isup),obsFcInfoReduced%obsj(isup)) = obsFcInfoReduced%slcobs(isup) - obsFcInfoReduced%slcfc(isup)
  662. end do
  663. call MDF_Put_Var( omff%ncid, omff%varid_grid_sup_omf, tmfield, status )
  664. IF_NOTOK_MDF(fid=omff%ncid)
  665. if ( includeAnalysis ) then
  666. ! OmA for superobs
  667. tmfield(:,:) = 0.0
  668. do isup = 1, obsAnInfoReduced%count
  669. tmfield(obsAnInfoReduced%obsi(isup),obsAnInfoReduced%obsj(isup)) = obsAnInfoReduced%slcobs(isup) - obsAnInfoReduced%slcfc(isup)
  670. end do
  671. call MDF_Put_Var( omff%ncid, omff%varid_grid_sup_oma, tmfield, status )
  672. IF_NOTOK_MDF(fid=omff%ncid)
  673. ! AmF for superobs
  674. tmfield(:,:) = 0.0
  675. if ( obsFcInfoReduced%count > obsAnInfoReduced%count ) then
  676. ! Reduce and match the number of FC superobs in case there are less analysis points
  677. isup = 0
  678. do isupfc = 1, obsFcInfoReduced%count
  679. if ( ( obsFcInfoReduced%obsi(isupfc) == obsAnInfoReduced%obsi(isup+1) ) .and. &
  680. ( obsFcInfoReduced%obsj(isupfc) == obsAnInfoReduced%obsj(isup+1) ) ) then
  681. isup = isup + 1
  682. tmfield(obsAnInfoReduced%obsi(isup),obsAnInfoReduced%obsj(isup)) = obsAnInfoReduced%slcfc(isup) - obsFcInfoReduced%slcfc(isupfc)
  683. end if
  684. end do
  685. if ( isup /= obsAnInfoReduced%count ) then
  686. print *, 'ERROR in OmF_output (2nd): isup inconsistent'
  687. stop -1
  688. end if
  689. else
  690. if ( obsFcInfoReduced%count == obsAnInfoReduced%count ) then
  691. do isup = 1, obsFcInfoReduced%count
  692. tmfield(obsFcInfoReduced%obsi(isup),obsFcInfoReduced%obsj(isup)) = obsAnInfoReduced%slcfc(isup) - obsFcInfoReduced%slcfc(isup)
  693. end do
  694. call MDF_Put_Var( omff%ncid, omff%varid_grid_sup_amf, tmfield, status )
  695. IF_NOTOK_MDF(fid=omff%ncid)
  696. end if
  697. end if
  698. end if
  699. deallocate ( tmfield )
  700. ! wrap up
  701. call goLabel()
  702. status = 0
  703. end subroutine OmF_Output_Write
  704. subroutine OmF_Output_Done( status )
  705. implicit none
  706. ! in/out
  707. integer, intent(out) :: status
  708. ! local
  709. character(len=*), parameter :: rname = trim(mname)//'/omff_GridDef_Done'
  710. ! --- begin -------------------------------------
  711. call goLabel(rname)
  712. call MDF_Close( omff%ncid, status)
  713. IF_NOTOK_RETURN(status=1)
  714. call goLabel()
  715. status = 0
  716. end subroutine OmF_Output_Done
  717. end module MOmF_output