TM5IF_module.F90 57 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758
  1. ! First include the set of model-wide compiler flags
  2. #include "tm5.inc"
  3. ! -----------------------------------------------------------------------------
  4. !
  5. ! TROPOMI NL L2 Data Processors
  6. !
  7. ! Copyright 2013-2015 KNMI
  8. ! This software is the proprietary information of KNMI
  9. ! All rights Reserved
  10. !
  11. ! -----------------------------------------------------------------------------
  12. module TM5IF_module
  13. use MTObsTrack
  14. use MTObsFcInfo
  15. use netcdf
  16. use pqf_module, only : PQF_E_GENERIC_EXCEPTION
  17. implicit none
  18. private
  19. public :: TM5IF_select, TM5IF_obstrack_read, TM5IF_obsfcinfo_write
  20. public :: TM5IF_time_init, TM5IF_time_to_string
  21. public :: TM5IF_log_info, TM5IF_log_error, TM5IF_log_debug
  22. public :: TM5IF_date, FILENAME_LEN
  23. integer, parameter :: FILENAME_LEN = 256
  24. integer, parameter :: STR_LEN = 256
  25. integer :: ncfileid
  26. integer :: ncgroupid
  27. character*(FILENAME_LEN) :: ncfilename
  28. ! In case of QA4ECV, the unit of the columns is 10^15 molecules per cm^2
  29. logical :: use_scd_qa4ecv_units
  30. ! undefined
  31. ! real, parameter :: nf_fill_float = 9.9692099683868690e+36
  32. real(4), parameter :: nf_fill_float = 9.96921e+36
  33. type TM5IF_date
  34. integer :: year, month, day, hour, minute, second
  35. end type TM5IF_date
  36. interface TM5IF_put_var
  37. module procedure TM5IF_put_var_f2, TM5IF_put_var_f3, TM5IF_put_var_f4, TM5IF_put_var_i3
  38. end interface
  39. interface TM5IF_get_var
  40. module procedure TM5IF_get_var_f2, TM5IF_get_var_f3, TM5IF_get_var_f4, TM5IF_get_var_i1, TM5IF_get_var_i2, TM5IF_get_var_i3
  41. end interface
  42. interface TM5IF_put_att
  43. module procedure TM5IF_put_att_str
  44. end interface
  45. interface TM5IF_get_att
  46. module procedure TM5IF_get_att_i, TM5IF_get_att_str
  47. end interface
  48. contains
  49. ! -----------------------------------------------------------------------------
  50. subroutine TM5IF_select ( filename, timeStart, timeStop, obstrack, before_or_after )
  51. ! Select L2 NO2 products.
  52. ! Check if product coverage time range falls in processing time range.
  53. ! If so, read number of scanlines used for allocation of memory for
  54. ! reading during pass 2.
  55. !
  56. ! before_or_after = -1 : the orbit time is before the time interval
  57. ! 0 : the orbit time is inside the time interval
  58. ! 1 : the orbit time is after the time interval
  59. implicit none
  60. character*(*),intent(in) :: filename
  61. type(TM5IF_date),intent(in) :: timeStart
  62. type(TM5IF_date),intent(in) :: timeStop
  63. type(TObsTrack),intent(inout) :: obstrack
  64. integer, intent(out) :: before_or_after
  65. character*(STR_LEN) :: str
  66. integer :: i, j, n, status
  67. integer :: nValidPixels
  68. integer :: dimScanline
  69. integer :: dimGroundPixel
  70. integer :: firstimage
  71. integer :: secCoverageStart
  72. integer :: secCoverageEnd
  73. integer :: secCoverageMid
  74. type(TM5IF_date) :: timeCoverageStart
  75. type(TM5IF_date) :: timeCoverageEnd
  76. integer, allocatable :: processingQualityFlags(:,:,:)
  77. integer, allocatable :: processingErrorFlag(:,:,:)
  78. status = TM5IF_open ( filename, nf90_nowrite )
  79. if (status /= 0) goto 999
  80. status = TM5IF_get_att("time_coverage_start", str)
  81. if (status /= 0) goto 998
  82. status = TM5IF_convert_date(str, timeCoverageStart);
  83. if (status /= 0) goto 998
  84. status = TM5IF_get_att("time_coverage_end", str)
  85. if (status /= 0) goto 998
  86. status = TM5IF_convert_date(str, timeCoverageEnd);
  87. if (status /= 0) goto 998
  88. secCoverageStart = TM5IF_time_get_seconds(timeCoverageStart)
  89. secCoverageEnd = TM5IF_time_get_seconds(timeCoverageEnd)
  90. secCoverageMid = (secCoverageStart + secCoverageEnd) / 2
  91. if (secCoverageMid < TM5IF_time_get_seconds(timeStart)) then
  92. ! orbit before time interval
  93. before_or_after = -1
  94. goto 998
  95. endif
  96. if (secCoverageMid > TM5IF_time_get_seconds(timeStop)) then
  97. ! orbit after time interval
  98. before_or_after = 1
  99. goto 998
  100. endif
  101. ! orbit inside time interval
  102. before_or_after = 0
  103. status = TM5IF_set_group("/PRODUCT")
  104. if (status /= 0) goto 998
  105. status = TM5IF_get_dimension("scanline", dimScanline)
  106. if (status /= 0) goto 998
  107. status = TM5IF_get_dimension("ground_pixel", dimGroundPixel)
  108. if (status /= 0) goto 998
  109. status = TM5IF_set_group("/PRODUCT/SUPPORT_DATA/DETAILED_RESULTS")
  110. if (status /= 0) goto 998
  111. status = TM5IF_get_var("processing_quality_flags", processingQualityFlags)
  112. if (status /= 0) goto 998
  113. status = TM5IF_set_group("/PRODUCT")
  114. if (status /= 0) goto 998
  115. nValidPixels = 0
  116. do i = 1, dimScanline
  117. do j = 1, dimGroundPixel
  118. if (iand(processingQualityFlags(j, i, 1), 255) == 0) nValidPixels = nValidPixels + 1
  119. end do
  120. end do
  121. deallocate ( processingQualityFlags )
  122. print '(a,i6,a,i6)', ' TM5IF_select: nValidPixels = ', nValidPixels,' total = ',dimGroundPixel*dimScanline
  123. n = obstrack%norbitparts + 1
  124. obstrack%orbitparts(n)%filename = filename
  125. obstrack%orbitparts(n)%nValidPixels = nValidPixels
  126. obstrack%orbitparts(n)%dimScanline = dimScanline
  127. obstrack%orbitparts(n)%starttime(1) = timeCoverageStart%year
  128. obstrack%orbitparts(n)%starttime(2) = timeCoverageStart%month
  129. obstrack%orbitparts(n)%starttime(3) = timeCoverageStart%day
  130. obstrack%orbitparts(n)%starttime(4) = timeCoverageStart%hour
  131. obstrack%orbitparts(n)%starttime(5) = timeCoverageStart%minute
  132. obstrack%orbitparts(n)%starttime(6) = timeCoverageStart%second
  133. obstrack%orbitparts(n)%endtime(1) = timeCoverageEnd%year
  134. obstrack%orbitparts(n)%endtime(2) = timeCoverageEnd%month
  135. obstrack%orbitparts(n)%endtime(3) = timeCoverageEnd%day
  136. obstrack%orbitparts(n)%endtime(4) = timeCoverageEnd%hour
  137. obstrack%orbitparts(n)%endtime(5) = timeCoverageEnd%minute
  138. obstrack%orbitparts(n)%endtime(6) = timeCoverageEnd%second
  139. !obstrack%orbitparts(n)%meantime = TBD
  140. obstrack%norbitparts = n
  141. 998 continue
  142. status = TM5IF_close()
  143. if (status /= 0) goto 999
  144. 999 continue
  145. end subroutine TM5IF_select
  146. ! -----------------------------------------------------------------------------
  147. subroutine TM5IF_obstrack_read(obstrack)
  148. ! Read L2 NO2 product
  149. implicit none
  150. type(TObsTrack) :: obstrack
  151. character(STR_LEN) :: str
  152. character(STR_LEN) :: scd_unit_string
  153. integer :: dim_scanline
  154. integer :: dim_ground_pixel
  155. integer :: dim_corner
  156. integer :: dim_time
  157. integer :: dim_polynomial_exponents
  158. integer :: dim_pressure_levels
  159. integer :: dim_profile_layers
  160. integer :: i, j, k, n
  161. integer :: iorbit
  162. integer :: status
  163. ! must be real(4) because of reading from netcdf
  164. real(4), allocatable :: latitude(:,:,:)
  165. real(4), allocatable :: longitude(:,:,:)
  166. real(4), allocatable :: latitude_bounds(:,:,:,:)
  167. real(4), allocatable :: longitude_bounds(:,:,:,:)
  168. real(4), allocatable :: solar_zenith_angle(:,:,:)
  169. real(4), allocatable :: solar_azimuth_angle(:,:,:)
  170. real(4), allocatable :: viewing_zenith_angle(:,:,:)
  171. real(4), allocatable :: viewing_azimuth_angle(:,:,:)
  172. real(4), allocatable :: surface_altitude(:,:,:)
  173. real(4), allocatable :: surface_pressure(:,:,:)
  174. real(4), allocatable :: surface_albedo_no2(:,:,:)
  175. real(4), allocatable :: scd_no2(:,:,:)
  176. real(4), allocatable :: scd_no2_precision(:,:,:)
  177. real(4), allocatable :: chi_squared(:,:,:)
  178. real(4), allocatable :: cloud_fraction_no2(:,:,:)
  179. real(4), allocatable :: cloud_pressure(:,:,:)
  180. real(4), allocatable :: cloud_albedo(:,:,:)
  181. real(4), allocatable :: cloud_radiance_fraction_no2(:,:,:)
  182. real(4), allocatable :: scene_albedo(:,:,:)
  183. real(4), allocatable :: scene_pressure(:,:,:)
  184. integer, allocatable :: snow_ice_flag(:,:,:)
  185. integer, allocatable :: pixel_type(:,:,:)
  186. integer, allocatable :: time(:)
  187. integer, allocatable :: delta_time(:,:)
  188. integer, allocatable :: processing_quality_flags(:,:,:)
  189. obstrack%count = 0
  190. call TM5IF_log_info("TM5IF_obstrack_read: now reading the track (orbit parts)")
  191. n = 0
  192. do i = 1, obstrack%norbitparts
  193. n = n + obstrack%orbitparts(i)%nValidPixels
  194. end do
  195. call ObsTrackAllocate(obstrack, n)
  196. do i = 1, obstrack%norbitparts
  197. call TM5IF_log_info(" Reading data from " // trim(obstrack%orbitparts(i)%filename))
  198. status = TM5IF_open ( trim(obstrack%orbitparts(i)%filename), nf90_nowrite)
  199. if (status /= 0) goto 998
  200. status = TM5IF_get_att("orbit", iorbit)
  201. if (status /= 0) goto 998
  202. status = TM5IF_set_group("/PRODUCT")
  203. if (status /= 0) goto 996
  204. status = TM5IF_get_dimension("time", dim_time)
  205. if (status /= 0) goto 996
  206. status = TM5IF_get_dimension("scanline", dim_scanline)
  207. if (status /= 0) goto 996
  208. status = TM5IF_get_dimension("ground_pixel", dim_ground_pixel)
  209. if (status /= 0) goto 996
  210. if (dim_time /= 1) then
  211. call TM5IF_log_error(" Invalid value for dimension 'time'")
  212. goto 996
  213. end if
  214. status = TM5IF_get_var( "time", time )
  215. if (status /= 0) goto 996
  216. status = TM5IF_get_var( "delta_time", delta_time )
  217. if (status /= 0) goto 996
  218. status = TM5IF_get_var( "latitude", latitude )
  219. if (status /= 0) goto 996
  220. status = TM5IF_get_var( "longitude", longitude )
  221. if (status /= 0) goto 996
  222. status = TM5IF_set_group("/PRODUCT/SUPPORT_DATA/GEOLOCATIONS")
  223. if (status /= 0) goto 996
  224. status = TM5IF_get_var( "pixel_type", pixel_type )
  225. if (status /= 0) goto 996
  226. status = TM5IF_get_var( "latitude_bounds", latitude_bounds )
  227. if (status /= 0) goto 996
  228. status = TM5IF_get_var( "longitude_bounds", longitude_bounds )
  229. if (status /= 0) goto 996
  230. status = TM5IF_get_var( "solar_zenith_angle", solar_zenith_angle )
  231. if ( status /= 0 ) goto 996
  232. status = TM5IF_get_var( "viewing_zenith_angle", viewing_zenith_angle )
  233. if ( status /= 0 ) goto 996
  234. status = TM5IF_get_var( "solar_azimuth_angle", solar_azimuth_angle, printErrorMessage = .false. )
  235. if ( status /= 0 ) then
  236. ! try QA4ECV convention
  237. status = TM5IF_get_var( "relative_azimuth_angle", solar_azimuth_angle )
  238. if ( status /= 0 ) goto 996
  239. call TM5IF_log_info(" Note: using -relative_azimuth_angle- instead of -solar_azimuth_angle- ")
  240. end if
  241. status = TM5IF_get_var( "viewing_azimuth_angle", viewing_azimuth_angle, printErrorMessage = .false. )
  242. if ( status /= 0 ) then
  243. ! try QA4ECV convention
  244. ! set vaa = raa, so that the computation in "MObservationOperator" yields a correct value
  245. status = TM5IF_get_var( "relative_azimuth_angle", viewing_azimuth_angle )
  246. if ( status /= 0 ) goto 996
  247. ! re-set saa to 180, so that the computation in "MObservationOperator" yields a correct value
  248. solar_azimuth_angle(:,:,:) = 180.0
  249. call TM5IF_log_info(" Note: using -relative_azimuth_angle_surf- instead of -viewing_azimuth_angle- ")
  250. end if
  251. status = TM5IF_set_group("/PRODUCT/SUPPORT_DATA/DETAILED_RESULTS")
  252. if (status /= 0) goto 996
  253. status = TM5IF_get_var("processing_quality_flags", processing_quality_flags)
  254. if (status /= 0) goto 996
  255. status = TM5IF_get_var("scd_no2", scd_no2)
  256. if (status /= 0) goto 996
  257. status = TM5IF_get_var_att_str("scd_no2", "units", scd_unit_string)
  258. if (status /= 0) goto 996
  259. use_scd_qa4ecv_units = .false.
  260. if ( trim(scd_unit_string) == "molecules cm-2" ) use_scd_qa4ecv_units = .true.
  261. print *, ' scd_no2: use qa4ecv units = ',use_scd_qa4ecv_units
  262. print *, ' scd_no2: units = ',trim(scd_unit_string)
  263. status = TM5IF_get_var("scd_no2_precision", scd_no2_precision)
  264. if (status /= 0) goto 996
  265. status = TM5IF_get_var( "chi_squared", chi_squared, printErrorMessage = .false. )
  266. if ( status /= 0 ) then
  267. ! QA4ECV does not provide chi_2
  268. ! set to fill value
  269. allocate ( chi_squared(dim_ground_pixel,dim_scanline,1) )
  270. chi_squared(:,:,:) = nf_fill_float
  271. call TM5IF_log_info(" Note: -chi_squared- set to fill value ")
  272. end if
  273. status = TM5IF_get_var( "cloud_radiance_fraction_no2", cloud_radiance_fraction_no2, printErrorMessage = .false. )
  274. if ( status /= 0 ) then
  275. ! QA4ECV does not provide cloud radiance fraction: set to fill value in this case
  276. allocate ( cloud_radiance_fraction_no2(dim_ground_pixel,dim_scanline,1) )
  277. cloud_radiance_fraction_no2(:,:,:) = nf_fill_float
  278. call TM5IF_log_info(" Warning: -cloud_radiance_fraction_no2- set to fill value ")
  279. end if
  280. status = TM5IF_get_var( "cloud_fraction_no2", cloud_fraction_no2, printErrorMessage = .false. )
  281. if ( status /= 0 ) then
  282. ! QA4ECV does not provide "cloud_fraction_no2", use cloud fraction instead
  283. status = TM5IF_set_group("/PRODUCT/SUPPORT_DATA/INPUT_DATA")
  284. if ( status /= 0 ) goto 996
  285. status = TM5IF_get_var( "cloud_fraction", cloud_fraction_no2 )
  286. if ( status /= 0 ) goto 996
  287. call TM5IF_log_info(" Note: using -cloud_fraction- instead of -cloud_fraction_no2- ")
  288. end if
  289. status = TM5IF_set_group("/PRODUCT/SUPPORT_DATA/INPUT_DATA")
  290. if (status /= 0) goto 996
  291. status = TM5IF_get_var("surface_altitude", surface_altitude)
  292. if (status /= 0) goto 996
  293. status = TM5IF_get_var("surface_pressure", surface_pressure)
  294. if (status /= 0) goto 996
  295. status = TM5IF_get_var("surface_albedo_no2", surface_albedo_no2)
  296. if (status /= 0) goto 996
  297. status = TM5IF_get_var("cloud_pressure", cloud_pressure)
  298. if (status /= 0) goto 996
  299. status = TM5IF_get_var("cloud_albedo", cloud_albedo, printErrorMessage = .false.)
  300. if ( status /= 0 ) then
  301. ! QA4ECV does not provide cloud albedo
  302. ! set to fill value
  303. allocate ( cloud_albedo(dim_ground_pixel,dim_scanline,1) )
  304. cloud_albedo(:,:,:) = 0.8
  305. call TM5IF_log_info(" Note: -cloud_albedo- set to 0.8 ")
  306. end if
  307. status = TM5IF_get_var("snow_ice_flag", snow_ice_flag)
  308. if (status /= 0) goto 996
  309. status = TM5IF_get_var("scene_pressure", scene_pressure)
  310. if (status /= 0) goto 996
  311. status = TM5IF_get_var("scene_albedo", scene_albedo)
  312. if (status /= 0) goto 996
  313. ! note: surface_altitude_precision is a field in the file, but is not defined
  314. ! note: surface_classification is a field in the file, but is also not defined
  315. ! note: for OMI, "omi_xtrack_flags" row anomaly flags are provided.
  316. ! However, these errors are included in the "processing_quality_flags"
  317. ! note: the "snow_ice_flag" needs to be read, because this info is not yet included
  318. ! in the processing_quality_flags. In the "MObservationoperator" module
  319. ! the action needs to be defined for snow/ice (use scene albedo/pressure),
  320. ! and the processing_quality_flags should be updated accordingly.
  321. n = obstrack%count
  322. print *, ' dims scanline groundpix = ', dim_scanline, dim_ground_pixel
  323. obstrack%dimGroundPixel = dim_ground_pixel
  324. ! print *, 'processing_quality_flags(:, j=500, 1)',processing_quality_flags(:, 800, 1)
  325. obstrack%orbitNumber = iorbit
  326. do j = 1, dim_scanline
  327. do k = 1, dim_ground_pixel
  328. if ( iand(processing_quality_flags(k, j, 1), 255) == 0 ) then
  329. n = n + 1
  330. obstrack%orbitPartIndex(n) = i
  331. obstrack%pixelIndex(n) = k
  332. obstrack%scanlineIndex(n) = j
  333. obstrack%subPixelNumber(n) = 1
  334. obstrack%pixelFlag(n) = processing_quality_flags(k, j, 1)
  335. obsTrack%subPixelNumber(n) = pixel_type(k, j, 1)
  336. obstrack%latitude(n) = latitude(k, j, 1)
  337. obstrack%longitude(n) = longitude(k, j, 1)
  338. obstrack%cornerLatitude(:,n) = latitude_bounds(:, k, j, 1)
  339. obstrack%cornerLongitude(:,n) = longitude_bounds(:, k, j, 1)
  340. if ( use_scd_qa4ecv_units ) then
  341. ! QA4ECV definition
  342. ! units = molecules cm-2, store as (10^15 molecules cm-2)
  343. obstrack%no2SLC(n) = scd_no2(k, j, 1) / 1.0e+15
  344. ! units = molecules cm-2, store as %
  345. obstrack%no2SLCError(n) = scd_no2_precision(k, j, 1) * 100.0 / scd_no2(k, j, 1)
  346. else
  347. ! TROPOMI definition
  348. ! units = mol m-2, store as (10^15 molecules cm-2)
  349. obstrack%no2SLC(n) = scd_no2(k, j, 1) * 6.02214e+19 / 1.0e+15
  350. ! units = mol m2, store as %
  351. obstrack%no2SLCError(n) = scd_no2_precision(k, j, 1) * 100.0 / scd_no2(k, j, 1)
  352. end if
  353. obstrack%chiSquareFit(n) = chi_squared(k, j, 1)
  354. obstrack%solarZenithAngle(n) = solar_zenith_angle(k, j, 1)
  355. obstrack%solarAzimuthAngle(n) = solar_azimuth_angle(k, j, 1)
  356. obstrack%viewingZenithAngle(n) = viewing_zenith_angle(k, j, 1)
  357. obstrack%ViewingAzimuthAngle(n) = viewing_azimuth_angle(k, j, 1)
  358. obstrack%cloudFraction(n) = cloud_fraction_no2(k, j, 1)
  359. obstrack%cloudTopPressure(n) = cloud_pressure(k, j, 1)
  360. obstrack%cloudAlbedo(n) = cloud_albedo(k, j, 1)
  361. obstrack%snowIceFlag(n) = snow_ice_flag(k, j, 1)
  362. obstrack%sceneAlbedo(n) = scene_albedo(k, j, 1)
  363. obstrack%scenePressure(n) = scene_pressure(k, j, 1)
  364. obstrack%cloudRadianceFraction(n) = cloud_radiance_fraction_no2(k, j, 1)
  365. obstrack%surfaceAlbedo(n) = surface_albedo_no2(k, j, 1)
  366. obstrack%terrainHeight(n) = surface_altitude(k, j, 1)
  367. obstrack%terrainPressure(n) = surface_pressure(k, j, 1)
  368. end if
  369. end do
  370. end do
  371. obstrack%count = n
  372. 996 continue
  373. deallocate ( latitude, stat=status )
  374. deallocate ( longitude, stat=status )
  375. deallocate ( latitude_bounds, stat=status )
  376. deallocate ( longitude_bounds, stat=status )
  377. deallocate ( solar_zenith_angle, stat=status )
  378. deallocate ( solar_azimuth_angle, stat=status )
  379. deallocate ( viewing_zenith_angle, stat=status )
  380. deallocate ( viewing_azimuth_angle, stat=status )
  381. deallocate ( surface_altitude, stat=status )
  382. deallocate ( surface_pressure, stat=status )
  383. deallocate ( surface_albedo_no2, stat=status )
  384. deallocate ( scd_no2, stat=status )
  385. deallocate ( scd_no2_precision, stat=status )
  386. deallocate ( chi_squared, stat=status )
  387. deallocate ( cloud_fraction_no2, stat=status )
  388. deallocate ( cloud_pressure, stat=status )
  389. deallocate ( cloud_albedo, stat=status )
  390. deallocate ( cloud_radiance_fraction_no2, stat=status )
  391. deallocate ( scene_albedo )
  392. deallocate ( scene_pressure )
  393. deallocate ( snow_ice_flag )
  394. deallocate ( pixel_type, stat=status )
  395. deallocate ( time, stat=status )
  396. deallocate ( delta_time, stat=status )
  397. deallocate ( processing_quality_flags, stat=status )
  398. 997 continue
  399. status = TM5IF_close ( )
  400. if ( status /= 0 ) goto 998
  401. 998 continue
  402. end do
  403. write(str, *) obstrack%count
  404. call TM5IF_log_info(" TM5IF_obstrack_read, loaded " // trim(adjustl(str)) // " observations")
  405. 999 continue
  406. end subroutine TM5IF_obstrack_read
  407. ! -----------------------------------------------------------------------------
  408. subroutine TM5IF_obsfcinfo_write ( obstrack, obsfcinfo, TM5Data )
  409. ! Update L2 NO2 product
  410. use MTM5Data, only : TTM5Data
  411. implicit none
  412. ! in/out
  413. type(TObsTrack), intent(inout) :: obstrack
  414. type(TObsFcInfo), intent(inout) :: obsfcinfo
  415. type(TTM5Data), intent(inout) :: TM5Data
  416. ! local
  417. integer :: i, j, k, l, n, intf
  418. integer :: status
  419. real :: f
  420. logical :: no_error
  421. ! main product
  422. integer, dimension(:,:,:), allocatable :: processing_error_flag
  423. real(4), dimension(:,:,:), allocatable :: amf_total
  424. real(4), dimension(:,:,:), allocatable :: amf_trop
  425. real(4), dimension(:,:,:,:), allocatable :: averaging_kernel
  426. real(4), dimension(:,:,:), allocatable :: tm5_surface_pressure
  427. real(4), dimension(:,:,:), allocatable :: tm5_tropopause_layer_index
  428. real(4), dimension(:,:,:), allocatable :: tropospheric_no2_vertical_column
  429. real(4), dimension(:,:,:), allocatable :: tropospheric_no2_vertical_column_precision
  430. real(4), dimension(:,:), allocatable :: tm5_pressure_level_a
  431. real(4), dimension(:,:), allocatable :: tm5_pressure_level_b
  432. ! detailed results
  433. real(4), dimension(:,:,:), allocatable :: amf_clear
  434. real(4), dimension(:,:,:), allocatable :: amf_strat
  435. real(4), dimension(:,:,:), allocatable :: ghost_column_no2
  436. integer, dimension(:,:,:), allocatable :: processing_quality_flags
  437. real(4), dimension(:,:,:), allocatable :: stratospheric_no2_vertical_column
  438. real(4), dimension(:,:,:), allocatable :: stratospheric_no2_vertical_column_precision
  439. real(4), dimension(:,:,:), allocatable :: summed_no2_total_vertical_column
  440. real(4), dimension(:,:,:), allocatable :: summed_no2_total_vertical_column_precision
  441. real(4), dimension(:,:,:), allocatable :: total_no2_vertical_column
  442. real(4), dimension(:,:,:), allocatable :: total_no2_vertical_column_precision
  443. real(4), dimension(:,:,:), allocatable :: cloud_radiance_fraction
  444. ! start code
  445. do i = 1, obstrack%norbitparts
  446. call TM5IF_log_info("TM5IF_obsfcinfo_write: Writing VCD NO2 data to file: ")
  447. call TM5IF_log_info(" " // trim(obstrack%orbitparts(i)%filename))
  448. status = TM5IF_open(trim(obstrack%orbitparts(i)%filename), nf90_write)
  449. if ( status /= 0 ) goto 998
  450. status = TM5IF_put_att("processing_status", "Retrieval/assimilation step complete, vertical columns and kernels added")
  451. if ( status /= 0 ) goto 996
  452. ! === Main product ===
  453. status = TM5IF_set_group("/PRODUCT" )
  454. if ( status /= 0 ) goto 996
  455. status = TM5IF_get_var( "processing_error_flag", processing_error_flag )
  456. if ( status /= 0 ) goto 996
  457. status = TM5IF_get_var( "amf_total", amf_total )
  458. if ( status /= 0 ) goto 996
  459. status = TM5IF_get_var( "amf_trop", amf_trop )
  460. if ( status /= 0 ) goto 996
  461. status = TM5IF_get_var( "averaging_kernel", averaging_kernel )
  462. if ( status /= 0 ) goto 996
  463. status = TM5IF_get_var( "tm5_pressure_level_a", tm5_pressure_level_a )
  464. if ( status /= 0 ) goto 996
  465. status = TM5IF_get_var( "tm5_pressure_level_b", tm5_pressure_level_b )
  466. if ( status /= 0 ) goto 996
  467. status = TM5IF_get_var( "tm5_surface_pressure", tm5_surface_pressure )
  468. if ( status /= 0 ) goto 996
  469. status = TM5IF_get_var( "tm5_tropopause_layer_index", tm5_tropopause_layer_index )
  470. if ( status /= 0 ) goto 996
  471. status = TM5IF_get_var( "tropospheric_no2_vertical_column", tropospheric_no2_vertical_column )
  472. if ( status /= 0 ) goto 996
  473. status = TM5IF_get_var( "tropospheric_no2_vertical_column_precision", tropospheric_no2_vertical_column_precision )
  474. if ( status /= 0 ) goto 996
  475. ! === Detailed Results ===
  476. status = TM5IF_set_group("/PRODUCT/SUPPORT_DATA/DETAILED_RESULTS")
  477. if ( status /= 0 ) goto 996
  478. status = TM5IF_get_var( "amf_clear", amf_clear )
  479. if ( status /= 0 ) goto 996
  480. status = TM5IF_get_var( "amf_strat", amf_strat )
  481. if ( status /= 0 ) goto 996
  482. status = TM5IF_get_var( "ghost_column_no2", ghost_column_no2 )
  483. if ( status /= 0 ) goto 996
  484. status = TM5IF_get_var( "processing_quality_flags", processing_quality_flags )
  485. if ( status /= 0 ) goto 996
  486. status = TM5IF_get_var( "stratospheric_no2_vertical_column", stratospheric_no2_vertical_column )
  487. if ( status /= 0 ) goto 996
  488. status = TM5IF_get_var( "stratospheric_no2_vertical_column_precision", stratospheric_no2_vertical_column_precision )
  489. if ( status /= 0 ) goto 996
  490. status = TM5IF_get_var( "summed_no2_total_vertical_column", summed_no2_total_vertical_column )
  491. if ( status /= 0 ) goto 996
  492. status = TM5IF_get_var( "summed_no2_total_vertical_column_precision", summed_no2_total_vertical_column_precision )
  493. if ( status /= 0 ) goto 996
  494. status = TM5IF_get_var( "total_no2_vertical_column", total_no2_vertical_column )
  495. if ( status /= 0 ) goto 996
  496. status = TM5IF_get_var( "total_no2_vertical_column_precision", total_no2_vertical_column_precision )
  497. if ( status /= 0 ) goto 996
  498. if ( ObsFcInfo%cloudRadFraction_computed ) then
  499. status = TM5IF_get_var( "cloud_radiance_fraction_no2", cloud_radiance_fraction )
  500. if ( status /= 0 ) goto 996
  501. end if
  502. ! QA4ECV units or TROPOMI units (NO2 columns)
  503. if ( use_scd_qa4ecv_units ) then
  504. ! QA4ECV definition
  505. ! units = molecules cm-2, store as (10^15 molecules cm-2)
  506. f = 1.0e+15
  507. else
  508. f = 1.0e+15 / 6.02214e+19
  509. end if
  510. do n = 1, obstrack%count
  511. if ( obstrack%orbitPartIndex(n) == i ) then
  512. j = obstrack%scanlineIndex(n)
  513. k = obstrack%pixelIndex(n)
  514. ! errors/warnings
  515. processing_quality_flags(k, j, 1) = obsfcinfo%flag(n)
  516. ! check if first 8 bits are all = 0
  517. no_error = (iand(obsfcinfo%flag(n), 255) == 0)
  518. if ( no_error ) then
  519. processing_error_flag(k, j, 1) = 0 ! success
  520. else
  521. processing_error_flag(k, j, 1) = 1 ! failure
  522. end if
  523. ! replace fill values only in case there was no error detected
  524. if ( no_error ) then
  525. ! main product
  526. amf_total(k, j, 1) = obsfcinfo%amf(n)
  527. amf_trop(k, j, 1) = obsfcinfo%amftrop(n)
  528. averaging_kernel(:, k, j, 1) = obsfcinfo%avkernel(:, n)
  529. tm5_surface_pressure(k, j, 1) = obsfcinfo%psurf(n)
  530. tm5_tropopause_layer_index(k, j, 1) = obsfcinfo%levtropopause(n)
  531. tropospheric_no2_vertical_column(k, j, 1) = obsfcinfo%no2vcdtrop(n) * f
  532. tropospheric_no2_vertical_column_precision(k, j, 1) = obsfcinfo%no2vcdtropsig(n) * f
  533. ! detailed results
  534. amf_clear(k, j, 1) = obsfcinfo%amfclear(n)
  535. amf_strat(k, j, 1) = obsfcinfo%amfstrat(n)
  536. ghost_column_no2(k, j, 1) = obsfcinfo%ghostcol(n) * f
  537. stratospheric_no2_vertical_column(k, j, 1) = obsfcinfo%no2vcdstrat(n) * f
  538. stratospheric_no2_vertical_column_precision(k, j, 1) = obsfcinfo%no2vcdstratsig(n) * f
  539. summed_no2_total_vertical_column(k, j, 1) = obsfcinfo%no2vcdsum(n) * f
  540. summed_no2_total_vertical_column_precision(k, j, 1) = obsfcinfo%no2vcdsumsig(n) * f
  541. total_no2_vertical_column(k, j, 1) = obsfcinfo%no2vcd(n) * f
  542. total_no2_vertical_column_precision(k, j, 1) = obsfcinfo%no2vcdsig(n) * f
  543. if ( ObsFcInfo%cloudRadFraction_computed ) then
  544. cloud_radiance_fraction(k, j, 1) = obsfcinfo%cloudradfraction(n)
  545. end if
  546. end if
  547. end if
  548. end do
  549. status = TM5IF_set_group("/PRODUCT")
  550. if ( status /= 0 ) goto 996
  551. do l = 1, TM5Data%lm
  552. do intf = 1, 2
  553. tm5_pressure_level_a(intf,l) = TM5Data%hyai(l+intf-1)
  554. tm5_pressure_level_b(intf,l) = TM5Data%hybi(l+intf-1)
  555. end do
  556. end do
  557. status = TM5IF_put_var("processing_error_flag", processing_error_flag)
  558. if ( status /= 0 ) goto 996
  559. status = TM5IF_put_var("amf_total", amf_total)
  560. if ( status /= 0 ) goto 996
  561. status = TM5IF_put_var("amf_trop", amf_trop)
  562. if ( status /= 0 ) goto 996
  563. status = TM5IF_put_var("averaging_kernel", averaging_kernel)
  564. if ( status /= 0 ) goto 996
  565. status = TM5IF_put_var("tm5_pressure_level_a", tm5_pressure_level_a)
  566. if ( status /= 0 ) goto 996
  567. status = TM5IF_put_var("tm5_pressure_level_b", tm5_pressure_level_b)
  568. if ( status /= 0 ) goto 996
  569. status = TM5IF_put_var("tm5_surface_pressure", tm5_surface_pressure)
  570. if ( status /= 0 ) goto 996
  571. status = TM5IF_put_var("tm5_tropopause_layer_index", tm5_tropopause_layer_index)
  572. if ( status /= 0 ) goto 996
  573. status = TM5IF_put_var("tropospheric_no2_vertical_column", tropospheric_no2_vertical_column)
  574. if ( status /= 0 ) goto 996
  575. status = TM5IF_put_var("tropospheric_no2_vertical_column_precision", tropospheric_no2_vertical_column_precision)
  576. if ( status /= 0 ) goto 996
  577. status = TM5IF_set_group("/PRODUCT/SUPPORT_DATA/DETAILED_RESULTS")
  578. if ( status /= 0 ) goto 996
  579. status = TM5IF_put_var("amf_clear", amf_clear)
  580. if ( status /= 0 ) goto 996
  581. status = TM5IF_put_var("amf_strat", amf_strat)
  582. if ( status /= 0 ) goto 996
  583. status = TM5IF_put_var("ghost_column_no2", ghost_column_no2)
  584. if ( status /= 0 ) goto 996
  585. status = TM5IF_put_var("processing_quality_flags", processing_quality_flags)
  586. if ( status /= 0 ) goto 996
  587. status = TM5IF_put_var("stratospheric_no2_vertical_column", stratospheric_no2_vertical_column)
  588. if ( status /= 0 ) goto 996
  589. status = TM5IF_put_var("stratospheric_no2_vertical_column_precision", stratospheric_no2_vertical_column_precision)
  590. if ( status /= 0 ) goto 996
  591. status = TM5IF_put_var("summed_no2_total_vertical_column", summed_no2_total_vertical_column)
  592. if ( status /= 0 ) goto 996
  593. status = TM5IF_put_var("summed_no2_total_vertical_column_precision", summed_no2_total_vertical_column_precision)
  594. if ( status /= 0 ) goto 996
  595. status = TM5IF_put_var("total_no2_vertical_column", total_no2_vertical_column)
  596. if ( status /= 0 ) goto 996
  597. status = TM5IF_put_var("total_no2_vertical_column_precision", total_no2_vertical_column_precision)
  598. if ( status /= 0 ) goto 996
  599. if ( ObsFcInfo%cloudRadFraction_computed ) then
  600. status = TM5IF_put_var( "cloud_radiance_fraction_no2", cloud_radiance_fraction )
  601. if ( status /= 0 ) goto 996
  602. end if
  603. 996 continue
  604. deallocate( processing_error_flag, stat=status )
  605. deallocate( amf_total, stat=status )
  606. deallocate( amf_trop, stat=status )
  607. deallocate( averaging_kernel, stat=status )
  608. deallocate( tm5_pressure_level_a, stat=status )
  609. deallocate( tm5_pressure_level_b, stat=status )
  610. deallocate( tm5_surface_pressure, stat=status )
  611. deallocate( tm5_tropopause_layer_index, stat=status )
  612. deallocate( tropospheric_no2_vertical_column, stat=status )
  613. deallocate( tropospheric_no2_vertical_column_precision, stat=status )
  614. deallocate( amf_clear, stat=status )
  615. deallocate( amf_strat, stat=status )
  616. deallocate( ghost_column_no2, stat=status )
  617. deallocate( processing_quality_flags, stat=status )
  618. deallocate( stratospheric_no2_vertical_column, stat=status )
  619. deallocate( stratospheric_no2_vertical_column_precision, stat=status )
  620. deallocate( summed_no2_total_vertical_column, stat=status )
  621. deallocate( summed_no2_total_vertical_column_precision, stat=status )
  622. deallocate( total_no2_vertical_column, stat=status )
  623. deallocate( total_no2_vertical_column_precision, stat=status )
  624. 997 continue
  625. status = TM5IF_close()
  626. if ( status /= 0 ) goto 998
  627. 998 continue
  628. end do
  629. 999 continue
  630. end subroutine TM5IF_obsfcinfo_write
  631. ! -----------------------------------------------------------------------------
  632. integer function TM5IF_open ( filename, mode )
  633. implicit none
  634. character(len=*), intent(in) :: filename
  635. integer, intent(in) :: mode
  636. integer :: status
  637. ncfilename = filename
  638. call TM5IF_log_debug("Opening '" // trim(ncfilename) // "'")
  639. status = nf90_open(trim(ncfilename), mode, ncfileid)
  640. if (status /= 0) then
  641. call TM5IF_log_error("Failed to open file '" // trim(ncfilename) // "'")
  642. TM5IF_open = 1
  643. return
  644. end if
  645. ncgroupid = ncfileid
  646. TM5IF_open = 0
  647. end function TM5IF_open
  648. ! -----------------------------------------------------------------------------
  649. function TM5IF_close()
  650. integer TM5IF_close
  651. integer status
  652. call TM5IF_log_debug("Closing '" // trim(ncfilename) // "'")
  653. status = nf90_close(ncfileid)
  654. if (status /= 0) then
  655. call TM5IF_log_error("Failed to close file '" // trim(ncfilename) // "'")
  656. TM5IF_close = 1
  657. return
  658. end if
  659. TM5IF_close = 0
  660. end function TM5IF_close
  661. ! -----------------------------------------------------------------------------
  662. function TM5IF_set_group(name)
  663. integer TM5IF_set_group
  664. character*(*) name
  665. integer status
  666. integer ncnewgroupid
  667. integer i, j, n
  668. i = 1
  669. j = 1
  670. n = len(trim(name))
  671. do j = 1, n
  672. if (j == n) then
  673. status = nf90_inq_grp_ncid(ncgroupid, name(i:j), ncnewgroupid)
  674. if (status /= 0) then
  675. call TM5IF_log_error("Failed to inquire id for group '" // trim(name(i:j)) // "'")
  676. TM5IF_set_group = 1
  677. return
  678. end if
  679. ncgroupid = ncnewgroupid
  680. else if (name(j:j) == "/") then
  681. if (i == j) then
  682. ncgroupid = ncfileid
  683. else
  684. status = nf90_inq_grp_ncid(ncgroupid, name(i:j-1), ncnewgroupid)
  685. if (status /= 0) then
  686. call TM5IF_log_error("Failed to inquire id for group '" // trim(name(i:j-1)) // "'")
  687. TM5IF_set_group = 1
  688. return
  689. end if
  690. ncgroupid = ncnewgroupid
  691. end if
  692. i = j + 1
  693. end if
  694. end do
  695. TM5IF_set_group = 0
  696. end function TM5IF_set_group
  697. ! -----------------------------------------------------------------------------
  698. function TM5IF_get_dimension(name, value)
  699. integer TM5IF_get_dimension
  700. character*(*) name
  701. integer value
  702. integer status
  703. integer ncdimid
  704. status = nf90_inq_dimid(ncgroupid, name, ncdimid)
  705. if (status /= 0) then
  706. call TM5IF_log_error("Failed to inquire id for dimension '" // name // "'")
  707. TM5IF_get_dimension = 1
  708. return
  709. end if
  710. status = nf90_inquire_dimension(ncgroupid, ncdimid, len=value)
  711. if (status /= 0) then
  712. call TM5IF_log_error("Failed to inquire dimension '" // name // "'")
  713. TM5IF_get_dimension = 1
  714. return
  715. end if
  716. TM5IF_get_dimension = 0
  717. end function TM5IF_get_dimension
  718. ! -----------------------------------------------------------------------------
  719. function TM5IF_get_att_i(name, value)
  720. integer :: TM5IF_get_att_i
  721. character*(*) :: name
  722. integer :: value
  723. integer :: status
  724. status = nf90_get_att(ncgroupid, NF90_GLOBAL, name, value)
  725. if (status /= 0) then
  726. call TM5IF_log_error("Failed to get attribute '" // name // "'")
  727. TM5IF_get_att_i = 1
  728. return
  729. end if
  730. TM5IF_get_att_i = 0
  731. end function TM5IF_get_att_i
  732. ! -----------------------------------------------------------------------------
  733. function TM5IF_get_att_str(name, value)
  734. integer TM5IF_get_att_str
  735. character*(*) :: name
  736. character*(*) :: value
  737. integer status
  738. status = nf90_get_att(ncgroupid, NF90_GLOBAL, name, value)
  739. if (status /= 0) then
  740. call TM5IF_log_error("Failed to get attribute '" // name // "'")
  741. TM5IF_get_att_str = 1
  742. return
  743. end if
  744. TM5IF_get_att_str = 0
  745. end function TM5IF_get_att_str
  746. ! -----------------------------------------------------------------------------
  747. integer function TM5IF_put_att_str ( name, value )
  748. implicit none
  749. character(len=*), intent(in) :: name
  750. character(len=*), intent(in) :: value
  751. integer :: status
  752. status = nf90_put_att(ncgroupid, NF90_GLOBAL, name, value)
  753. if (status /= 0) then
  754. call TM5IF_log_error("Failed to put attribute '" // name // "'")
  755. TM5IF_put_att_str = 1
  756. return
  757. end if
  758. TM5IF_put_att_str = 0
  759. end function TM5IF_put_att_str
  760. ! -----------------------------------------------------------------------------
  761. function TM5IF_get_var_att_str(varname, name, value)
  762. integer :: TM5IF_get_var_att_str
  763. character*(*) :: varname
  764. character*(*) :: name
  765. character*(*) :: value
  766. integer :: status
  767. integer :: ncvarid
  768. ! first, get the varid corresponding to varname
  769. status = nf90_inq_varid(ncgroupid, varname, ncvarid)
  770. if (status /= 0) then
  771. call TM5IF_log_error("Failed to inquire id for variable '" // name // "'")
  772. TM5IF_get_var_att_str = 1
  773. return
  774. end if
  775. ! then, get the attribute of this variable
  776. status = nf90_get_att(ncgroupid, ncvarid, name, value)
  777. if (status /= 0) then
  778. call TM5IF_log_error("Failed to get attribute '" // name // "'")
  779. TM5IF_get_var_att_str = 1
  780. return
  781. end if
  782. TM5IF_get_var_att_str = 0
  783. end function TM5IF_get_var_att_str
  784. ! -----------------------------------------------------------------------------
  785. integer function TM5IF_put_var_f2(name, value)
  786. implicit none
  787. character(len=*), intent(in) :: name
  788. real(4), dimension(:,:), intent(inout), allocatable :: value
  789. integer :: status
  790. integer :: ncvarid
  791. integer :: ndims
  792. integer, dimension(nf90_max_var_dims) :: dimids
  793. status = nf90_inq_varid(ncgroupid, name, ncvarid)
  794. if ( status /= 0 ) then
  795. call TM5IF_log_error("Failed to inquire id for variable '" // name // "'")
  796. TM5IF_put_var_f2 = 1
  797. return
  798. end if
  799. status = nf90_inquire_variable(ncgroupid, ncvarid, dimids = dimids, ndims = ndims)
  800. if ( status /= 0 ) then
  801. call TM5IF_log_error("Failed to inquire dims for variable '" // name // "'")
  802. TM5IF_put_var_f2 = 1
  803. return
  804. end if
  805. if ( ndims /= 2 ) then
  806. call TM5IF_log_error("Number of dimensions not supported for variable '" // name // "'")
  807. TM5IF_put_var_f2 = 1
  808. return
  809. end if
  810. status = nf90_put_var(ncgroupid, ncvarid, value)
  811. if ( status /= 0 ) then
  812. call TM5IF_log_error("Failed to put variable '" // name // "'")
  813. TM5IF_put_var_f2 = 1
  814. return
  815. end if
  816. TM5IF_put_var_f2 = 0
  817. end function TM5IF_put_var_f2
  818. ! -----------------------------------------------------------------------------
  819. integer function TM5IF_put_var_f3(name, value)
  820. implicit none
  821. character(len=*), intent(in) :: name
  822. real(4), dimension(:,:,:), intent(inout),allocatable :: value
  823. integer :: status
  824. integer :: ncvarid
  825. integer :: ndims
  826. integer, dimension(nf90_max_var_dims) :: dimids
  827. status = nf90_inq_varid(ncgroupid, name, ncvarid)
  828. if ( status /= 0 ) then
  829. call TM5IF_log_error("Failed to inquire id for variable '" // name // "'")
  830. TM5IF_put_var_f3 = 1
  831. return
  832. end if
  833. status = nf90_inquire_variable(ncgroupid, ncvarid, dimids = dimids, ndims = ndims)
  834. if ( status /= 0 ) then
  835. call TM5IF_log_error("Failed to inquire dims for variable '" // name // "'")
  836. TM5IF_put_var_f3 = 1
  837. return
  838. end if
  839. if ( ndims /= 3 ) then
  840. call TM5IF_log_error("Number of dimensions not supported for variable '" // name // "'")
  841. TM5IF_put_var_f3 = 1
  842. return
  843. end if
  844. status = nf90_put_var(ncgroupid, ncvarid, value)
  845. if ( status /= 0 ) then
  846. call TM5IF_log_error("Failed to put variable '" // name // "'")
  847. TM5IF_put_var_f3 = 1
  848. return
  849. end if
  850. TM5IF_put_var_f3 = 0
  851. end function TM5IF_put_var_f3
  852. ! -----------------------------------------------------------------------------
  853. integer function TM5IF_put_var_f4(name, value)
  854. implicit none
  855. character(len=*), intent(in) :: name
  856. real(4), dimension(:,:,:,:), intent(inout),allocatable :: value
  857. integer :: status
  858. integer :: ncvarid
  859. integer :: ndims
  860. integer, dimension(nf90_max_var_dims) :: dimids
  861. status = nf90_inq_varid(ncgroupid, name, ncvarid)
  862. if ( status /= 0 ) then
  863. call TM5IF_log_error("Failed to inquire id for variable '" // name // "'")
  864. TM5IF_put_var_f4 = 1
  865. return
  866. end if
  867. status = nf90_inquire_variable(ncgroupid, ncvarid, dimids = dimids, ndims = ndims)
  868. if ( status /= 0 ) then
  869. call TM5IF_log_error("Failed to inquire dims for variable '" // name // "'")
  870. TM5IF_put_var_f4 = 1
  871. return
  872. end if
  873. if ( ndims /= 4 ) then
  874. call TM5IF_log_error("Number of dimensions not supported for variable '" // name // "'")
  875. TM5IF_put_var_f4 = 1
  876. return
  877. end if
  878. status = nf90_put_var(ncgroupid, ncvarid, value)
  879. if ( status /= 0 ) then
  880. call TM5IF_log_error("Failed to put variable '" // name // "'")
  881. TM5IF_put_var_f4 = 1
  882. return
  883. end if
  884. TM5IF_put_var_f4 = 0
  885. end function TM5IF_put_var_f4
  886. ! -----------------------------------------------------------------------------
  887. integer function TM5IF_put_var_i3(name, value)
  888. ! unsigned byte, 3D array
  889. implicit none
  890. character(len=*), intent(in) :: name
  891. integer, dimension(:,:,:), intent(inout), allocatable :: value
  892. integer :: status
  893. integer :: ncvarid
  894. integer :: ndims
  895. integer, dimension(nf90_max_var_dims) :: dimids
  896. status = nf90_inq_varid(ncgroupid, name, ncvarid)
  897. if ( status /= 0 ) then
  898. call TM5IF_log_error("Failed to inquire id for variable '" // name // "'")
  899. TM5IF_put_var_i3 = 1
  900. return
  901. end if
  902. status = nf90_inquire_variable(ncgroupid, ncvarid, dimids = dimids, ndims = ndims)
  903. if ( status /= 0 ) then
  904. call TM5IF_log_error("Failed to inquire dims for variable '" // name // "'")
  905. TM5IF_put_var_i3 = 1
  906. return
  907. end if
  908. if ( ndims /= 3 ) then
  909. call TM5IF_log_error("Number of dimensions not supported for variable '" // name // "'")
  910. TM5IF_put_var_i3 = 1
  911. return
  912. end if
  913. status = nf90_put_var(ncgroupid, ncvarid, value)
  914. if ( status /= 0 ) then
  915. call TM5IF_log_error("Failed to put variable '" // name // "'")
  916. TM5IF_put_var_i3 = 1
  917. return
  918. end if
  919. TM5IF_put_var_i3 = 0
  920. end function TM5IF_put_var_i3
  921. ! -----------------------------------------------------------------------------
  922. integer function TM5IF_get_var_f2 ( name, value, printErrorMessage )
  923. implicit none
  924. character(len=*), intent(in) :: name
  925. real(4), dimension(:,:), allocatable, intent(inout) :: value
  926. logical, intent(in), optional :: printErrorMessage
  927. integer :: status
  928. integer :: ncvarid
  929. integer :: ndims, idim
  930. integer, dimension(nf90_max_var_dims) :: dimids
  931. integer, dimension(nf90_max_var_dims) :: dims
  932. logical :: shout
  933. ! messages ?
  934. shout = .true.
  935. if ( present(printErrorMessage) ) shout = printErrorMessage
  936. ! variable should not have been allocated yet
  937. if ( allocated(value) ) deallocate(value)
  938. status = nf90_inq_varid(ncgroupid, name, ncvarid)
  939. if (status /= 0) then
  940. if ( shout ) call TM5IF_log_error("Failed to inquire id for variable '" // name // "'")
  941. TM5IF_get_var_f2 = 1
  942. return
  943. end if
  944. status = nf90_inquire_variable(ncgroupid, ncvarid, dimids = dimids, ndims = ndims)
  945. if ( status /= 0 ) then
  946. call TM5IF_log_error("Failed to inquire dims for variable '" // name // "'")
  947. TM5IF_get_var_f2 = 1
  948. return
  949. end if
  950. if ( ndims /= 2 ) then
  951. call TM5IF_log_error("Number of dimensions not supported for variable '" // name // "'")
  952. TM5IF_get_var_f2 = 1
  953. return
  954. end if
  955. do idim = 1, ndims
  956. status = nf90_inquire_dimension(ncgroupid, dimids(idim), len = dims(idim))
  957. if ( status /= 0 ) then
  958. call TM5IF_log_error("Failed to inquire dims for variable '" // name // "'")
  959. TM5IF_get_var_f2 = 1
  960. return
  961. end if
  962. end do
  963. allocate(value(dims(1), dims(2)))
  964. status = nf90_get_var(ncgroupid, ncvarid, value)
  965. if (status /= 0) then
  966. call TM5IF_log_error("Failed to get variable '" // name // "'")
  967. TM5IF_get_var_f2 = 1
  968. return
  969. end if
  970. TM5IF_get_var_f2 = 0
  971. end function TM5IF_get_var_f2
  972. ! -----------------------------------------------------------------------------
  973. integer function TM5IF_get_var_f3 ( name, value, printErrorMessage )
  974. implicit none
  975. character(len=*), intent(in) :: name
  976. real(4), dimension(:,:,:), intent(inout), allocatable :: value
  977. logical, intent(in), optional :: printErrorMessage
  978. integer :: status
  979. integer :: ncvarid
  980. integer :: ndims, idim
  981. integer, dimension(nf90_max_var_dims) :: dimids
  982. integer, dimension(nf90_max_var_dims) :: dims
  983. logical :: shout
  984. ! messages ?
  985. shout = .true.
  986. if ( present(printErrorMessage) ) shout = printErrorMessage
  987. ! variable should not have been allocated yet
  988. if ( allocated(value) ) deallocate(value)
  989. status = nf90_inq_varid(ncgroupid, name, ncvarid)
  990. if ( status /= 0 ) then
  991. if ( shout ) call TM5IF_log_error("Failed to inquire id for variable '" // name // "'")
  992. TM5IF_get_var_f3 = 1
  993. return
  994. end if
  995. status = nf90_inquire_variable(ncgroupid, ncvarid, dimids = dimids, ndims = ndims)
  996. if ( status /= 0 ) then
  997. call TM5IF_log_error("Failed to inquire dims for variable '" // name // "'")
  998. TM5IF_get_var_f3 = 1
  999. return
  1000. end if
  1001. if ( ndims /= 3 ) then
  1002. call TM5IF_log_error("Number of dimensions not supported for variable '" // name // "'")
  1003. TM5IF_get_var_f3 = 1
  1004. return
  1005. end if
  1006. do idim = 1, ndims
  1007. status = nf90_inquire_dimension(ncgroupid, dimids(idim), len = dims(idim))
  1008. if ( status /= 0 ) then
  1009. call TM5IF_log_error("Failed to inquire dims for variable '" // name // "'")
  1010. TM5IF_get_var_f3 = 1
  1011. return
  1012. end if
  1013. end do
  1014. allocate(value(dims(1), dims(2), dims(3)))
  1015. status = nf90_get_var(ncgroupid, ncvarid, value)
  1016. if (status /= 0) then
  1017. call TM5IF_log_error("Failed to get variable '" // name // "'")
  1018. TM5IF_get_var_f3 = 1
  1019. return
  1020. end if
  1021. TM5IF_get_var_f3 = 0
  1022. end function TM5IF_get_var_f3
  1023. ! -----------------------------------------------------------------------------
  1024. function TM5IF_get_var_f4 ( name, value, printErrorMessage )
  1025. integer TM5IF_get_var_f4
  1026. character*(*) name
  1027. real(4), allocatable :: value(:,:,:,:)
  1028. logical, intent(in), optional :: printErrorMessage
  1029. integer status
  1030. integer ncvarid
  1031. integer ndims, idim
  1032. integer, dimension(nf90_max_var_dims) :: dimids
  1033. integer, dimension(nf90_max_var_dims) :: dims
  1034. logical :: shout
  1035. ! messages ?
  1036. shout = .true.
  1037. if ( present(printErrorMessage) ) shout = printErrorMessage
  1038. ! variable should not have been allocated yet
  1039. if ( allocated(value) ) deallocate(value)
  1040. status = nf90_inq_varid(ncgroupid, name, ncvarid)
  1041. if (status /= 0) then
  1042. if ( shout ) call TM5IF_log_error("Failed to inquire id for variable '" // name // "'")
  1043. TM5IF_get_var_f4 = 1
  1044. return
  1045. end if
  1046. status = nf90_inquire_variable(ncgroupid, ncvarid, dimids = dimids, ndims = ndims)
  1047. if (status /= 0) then
  1048. call TM5IF_log_error("Failed to inquire dims for variable '" // name // "'")
  1049. TM5IF_get_var_f4 = 1
  1050. return
  1051. end if
  1052. if (ndims /= 4) then
  1053. call TM5IF_log_error("Number of dimensions not supported for variable '" // name // "'")
  1054. TM5IF_get_var_f4 = 1
  1055. return
  1056. end if
  1057. do idim = 1, ndims
  1058. status = nf90_inquire_dimension(ncgroupid, dimids(idim), len = dims(idim))
  1059. if (status /= 0) then
  1060. call TM5IF_log_error("Failed to inquire dims for variable '" // name // "'")
  1061. TM5IF_get_var_f4 = 1
  1062. return
  1063. end if
  1064. end do
  1065. allocate(value(dims(1), dims(2), dims(3), dims(4)))
  1066. status = nf90_get_var(ncgroupid, ncvarid, value)
  1067. if (status /= 0) then
  1068. call TM5IF_log_error("Failed to get variable '" // name // "'")
  1069. TM5IF_get_var_f4 = 1
  1070. return
  1071. end if
  1072. TM5IF_get_var_f4 = 0
  1073. end function TM5IF_get_var_f4
  1074. ! -----------------------------------------------------------------------------
  1075. function TM5IF_get_var_i1 ( name, value, printErrorMessage )
  1076. integer TM5IF_get_var_i1
  1077. character*(*) name
  1078. integer, allocatable :: value(:)
  1079. logical, intent(in), optional :: printErrorMessage
  1080. integer status
  1081. integer ncvarid
  1082. integer ndims, idim
  1083. integer, dimension(nf90_max_var_dims) :: dimids
  1084. integer, dimension(nf90_max_var_dims) :: dims
  1085. logical :: shout
  1086. ! messages ?
  1087. shout = .true.
  1088. if ( present(printErrorMessage) ) shout = printErrorMessage
  1089. ! variable should not have been allocated yet
  1090. if ( allocated(value) ) deallocate(value)
  1091. status = nf90_inq_varid(ncgroupid, name, ncvarid)
  1092. if (status /= 0) then
  1093. if ( shout ) call TM5IF_log_error("Failed to inquire id for variable '" // name // "'")
  1094. TM5IF_get_var_i1 = 1
  1095. return
  1096. end if
  1097. status = nf90_inquire_variable(ncgroupid, ncvarid, dimids = dimids, ndims = ndims)
  1098. if (status /= 0) then
  1099. call TM5IF_log_error("Failed to inquire dims for variable '" // name // "'")
  1100. TM5IF_get_var_i1 = 1
  1101. return
  1102. end if
  1103. if (ndims /= 1) then
  1104. call TM5IF_log_error("Number of dimensions not supported for variable '" // name // "'")
  1105. TM5IF_get_var_i1 = 1
  1106. return
  1107. end if
  1108. do idim = 1, ndims
  1109. status = nf90_inquire_dimension(ncgroupid, dimids(idim), len = dims(idim))
  1110. if (status /= 0) then
  1111. call TM5IF_log_error("Failed to inquire dims for variable '" // name // "'")
  1112. TM5IF_get_var_i1 = 1
  1113. return
  1114. end if
  1115. end do
  1116. allocate(value(dims(1)))
  1117. status = nf90_get_var(ncgroupid, ncvarid, value)
  1118. if (status /= 0) then
  1119. call TM5IF_log_error("Failed to get variable '" // name // "'")
  1120. TM5IF_get_var_i1 = 1
  1121. return
  1122. end if
  1123. TM5IF_get_var_i1 = 0
  1124. end function TM5IF_get_var_i1
  1125. ! -----------------------------------------------------------------------------
  1126. function TM5IF_get_var_i2 ( name, value, printErrorMessage )
  1127. integer TM5IF_get_var_i2
  1128. character*(*) name
  1129. integer, allocatable :: value(:,:)
  1130. logical, intent(in), optional :: printErrorMessage
  1131. integer status
  1132. integer ncvarid
  1133. integer ndims, idim
  1134. integer, dimension(nf90_max_var_dims) :: dimids
  1135. integer, dimension(nf90_max_var_dims) :: dims
  1136. logical :: shout
  1137. ! messages ?
  1138. shout = .true.
  1139. if ( present(printErrorMessage) ) shout = printErrorMessage
  1140. ! variable should not have been allocated yet
  1141. if ( allocated(value) ) deallocate(value)
  1142. status = nf90_inq_varid(ncgroupid, name, ncvarid)
  1143. if (status /= 0) then
  1144. if ( shout ) call TM5IF_log_error("Failed to inquire id for variable '" // name // "'")
  1145. TM5IF_get_var_i2 = 1
  1146. return
  1147. end if
  1148. status = nf90_inquire_variable(ncgroupid, ncvarid, dimids = dimids, ndims = ndims)
  1149. if (status /= 0) then
  1150. call TM5IF_log_error("Failed to inquire dims for variable '" // name // "'")
  1151. TM5IF_get_var_i2 = 1
  1152. return
  1153. end if
  1154. if (ndims /= 2) then
  1155. call TM5IF_log_error("Number of dimensions not supported for variable '" // name // "'")
  1156. TM5IF_get_var_i2 = 1
  1157. return
  1158. end if
  1159. do idim = 1, ndims
  1160. status = nf90_inquire_dimension(ncgroupid, dimids(idim), len = dims(idim))
  1161. if (status /= 0) then
  1162. call TM5IF_log_error("Failed to inquire dims for variable '" // name // "'")
  1163. TM5IF_get_var_i2 = 1
  1164. return
  1165. end if
  1166. end do
  1167. allocate(value(dims(1), dims(2)))
  1168. status = nf90_get_var(ncgroupid, ncvarid, value)
  1169. if (status /= 0) then
  1170. call TM5IF_log_error("Failed to get variable '" // name // "'")
  1171. TM5IF_get_var_i2 = 1
  1172. return
  1173. end if
  1174. TM5IF_get_var_i2 = 0
  1175. end function TM5IF_get_var_i2
  1176. ! -----------------------------------------------------------------------------
  1177. function TM5IF_get_var_i3 ( name, value, printErrorMessage )
  1178. integer TM5IF_get_var_i3
  1179. character*(*) name
  1180. integer, allocatable :: value(:,:,:)
  1181. logical, intent(in), optional :: printErrorMessage
  1182. integer status
  1183. integer ncvarid
  1184. integer ndims, idim
  1185. integer, dimension(nf90_max_var_dims) :: dimids
  1186. integer, dimension(nf90_max_var_dims) :: dims
  1187. logical :: shout
  1188. ! messages ?
  1189. shout = .true.
  1190. if ( present(printErrorMessage) ) shout = printErrorMessage
  1191. ! variable should not have been allocated yet
  1192. if ( allocated(value) ) deallocate(value)
  1193. status = nf90_inq_varid(ncgroupid, name, ncvarid)
  1194. if (status /= 0) then
  1195. if ( shout ) call TM5IF_log_error("Failed to inquire id for variable '" // name // "'")
  1196. TM5IF_get_var_i3 = 1
  1197. return
  1198. end if
  1199. status = nf90_inquire_variable(ncgroupid, ncvarid, dimids = dimids, ndims = ndims)
  1200. if (status /= 0) then
  1201. call TM5IF_log_error("Failed to inquire dims for variable '" // name // "'")
  1202. TM5IF_get_var_i3 = 1
  1203. return
  1204. end if
  1205. if (ndims /= 3) then
  1206. call TM5IF_log_error("Number of dimensions not supported for variable '" // name // "'")
  1207. TM5IF_get_var_i3 = 1
  1208. return
  1209. end if
  1210. do idim = 1, ndims
  1211. status = nf90_inquire_dimension(ncgroupid, dimids(idim), len = dims(idim))
  1212. if (status /= 0) then
  1213. call TM5IF_log_error("Failed to inquire dims for variable '" // name // "'")
  1214. TM5IF_get_var_i3 = 1
  1215. return
  1216. end if
  1217. end do
  1218. allocate(value(dims(1), dims(2), dims(3)))
  1219. status = nf90_get_var(ncgroupid, ncvarid, value)
  1220. if (status /= 0) then
  1221. call TM5IF_log_error("Failed to get variable '" // name // "'")
  1222. TM5IF_get_var_i3 = 1
  1223. return
  1224. end if
  1225. TM5IF_get_var_i3 = 0
  1226. end function TM5IF_get_var_i3
  1227. ! -----------------------------------------------------------------------------
  1228. function TM5IF_convert_date(string, date)
  1229. integer TM5IF_convert_date
  1230. character*(*) string
  1231. type(TM5IF_date) :: date
  1232. integer status
  1233. if (len(string) .lt. 19) then
  1234. TM5IF_convert_date = 1
  1235. return
  1236. end if
  1237. read(string(1:4) ,*,iostat=status,err=999) date%year
  1238. read(string(6:7) ,*,iostat=status,err=999) date%month
  1239. read(string(9:10) ,*,iostat=status,err=999) date%day
  1240. read(string(12:13),*,iostat=status,err=999) date%hour
  1241. read(string(15:16),*,iostat=status,err=999) date%minute
  1242. read(string(18:19),*,iostat=status,err=999) date%second
  1243. 999 continue
  1244. if (status /= 0) then
  1245. TM5IF_convert_date = 1
  1246. return
  1247. end if
  1248. TM5IF_convert_date = 0
  1249. end function TM5IF_convert_date
  1250. ! -----------------------------------------------------------------------------
  1251. subroutine TM5IF_log_info(text)
  1252. character*(*) :: text
  1253. write(*,*) trim(text)
  1254. end subroutine TM5IF_log_info
  1255. ! -----------------------------------------------------------------------------
  1256. subroutine TM5IF_log_debug(text)
  1257. character*(*) :: text
  1258. !write(*,*) trim(text)
  1259. end subroutine TM5IF_log_debug
  1260. ! -----------------------------------------------------------------------------
  1261. subroutine TM5IF_log_error(text)
  1262. character*(*) :: text
  1263. write(*,*) trim(text)
  1264. end subroutine TM5IF_log_error
  1265. ! -----------------------------------------------------------------------------
  1266. function TM5IF_time_get_seconds(time)
  1267. integer TM5IF_time_get_seconds
  1268. type(TM5IF_date) :: time
  1269. integer,parameter,dimension(12) :: days = [31,28,31,30,31,30,31,31,30,31,30,31]
  1270. integer,parameter :: epoch = 2000
  1271. integer :: d, i
  1272. d = 0
  1273. do i = epoch, time%year - 1
  1274. d = d + 365
  1275. if ((mod(i, 4) .eq. 0) .and. (mod(i, 100) .ne. 0)) d = d + 1
  1276. end do
  1277. do i = 1, time%month - 1
  1278. d = d + days(i)
  1279. if ((i .eq. 2) .and. (mod(time%year, 4) .eq. 0) .and. (mod(time%year, 100) .ne. 0)) d = d + 1
  1280. end do
  1281. d = d + time%day - 1
  1282. TM5IF_time_get_seconds = d * 86400 + time%hour * 3600 + time%minute * 60 + time%second
  1283. end function TM5IF_time_get_seconds
  1284. ! -----------------------------------------------------------------------------
  1285. function TM5IF_time_to_string(time)
  1286. character*(STR_LEN) TM5IF_time_to_string
  1287. type(TM5IF_date) :: time
  1288. write(TM5IF_time_to_string, '(I4.4,A,I2.2,A,I2.2,A,I2.2,A,I2.2,A,I2.2)') time%year, '-', time%month, '-', time%day, 'T', time%hour, ':', time%minute, ':', time%second
  1289. end function TM5IF_time_to_string
  1290. ! -----------------------------------------------------------------------------
  1291. subroutine TM5IF_time_init(time, year, month, day, hour, minute, second)
  1292. type(TM5IF_date) :: time
  1293. integer :: year, month, day, hour, minute, second
  1294. time%year = year
  1295. time%month = month
  1296. time%day = day
  1297. time%hour = hour
  1298. time%minute = minute
  1299. time%second = second
  1300. end subroutine TM5IF_time_init
  1301. ! -----------------------------------------------------------------------------
  1302. end module TM5IF_module