tmm_mf_msc.F90 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  1. !###############################################################################
  2. !
  3. ! Input/output of meteofiles : MSC meteo version.
  4. !
  5. !### macro's ###################################################################
  6. !
  7. #define TRACEBACK write (gol,'("in ",a," (",a,", line",i5,")")') rname, __FILE__, __LINE__; call goErr
  8. #define IF_NOTOK_RETURN(action) if (status/=0) then; TRACEBACK; action; return; end if
  9. #define IF_ERROR_RETURN(action) if (status> 0) then; TRACEBACK; action; return; end if
  10. !
  11. #include "tmm.inc"
  12. !
  13. !###############################################################################
  14. module tmm_mf_msc
  15. use GO, only : gol, goErr, goPr
  16. use GO, only : TDate
  17. implicit none
  18. ! --- in/out ---------------------------
  19. private
  20. public :: TMeteoFile_msc
  21. public :: Init, Done
  22. public :: Get
  23. public :: ReadRecord
  24. ! --- const ------------------------------
  25. character(len=*), parameter :: mname = 'tmm_mf_msc'
  26. ! --- types -------------------------------
  27. type TMeteoFile_msc
  28. ! file name:
  29. character(len=256) :: fname
  30. ! current time range:
  31. type(TDate) :: t1, t2
  32. ! params stored in file:
  33. character(len=256) :: paramkeys
  34. ! extra ..
  35. character(len=10) :: sp_unit
  36. end type TMeteoFile_msc
  37. ! --- interfaces --------------------------
  38. interface Init
  39. module procedure mf_Init
  40. end interface
  41. interface Done
  42. module procedure mf_Done
  43. end interface
  44. interface Get
  45. module procedure mf_Get
  46. end interface
  47. interface ReadRecord
  48. module procedure mf_ReadRecord
  49. end interface
  50. contains
  51. ! ==================================================================
  52. ! Initialise msc file:
  53. ! o setup filename for given:
  54. ! * input dir
  55. ! * archive keys (see tmm_mf_hdf for inspiration, or tmm_mf_grib/Init2)
  56. ! * parameter name ('LNSP', 'VO', etc)
  57. ! * times (now only t1 is used)
  58. !
  59. subroutine mf_Init( mf, dir, archivekeys, paramkey, &
  60. tday, t1, t2, status )
  61. use GO, only : TDate, NewDate, Get
  62. use GO, only : goVarValue
  63. ! --- in/out -----------------------
  64. type(TMeteoFile_msc), intent(out) :: mf
  65. character(len=*), intent(in) :: dir
  66. character(len=*), intent(in) :: archivekeys
  67. character(len=*), intent(in) :: paramkey
  68. type(TDate), intent(in) :: tday, t1, t2
  69. integer, intent(out) :: status
  70. ! --- const --------------------------------------
  71. character(len=*), parameter :: rname = mname//'/mf_Init'
  72. ! --- local ---------------------
  73. logical :: exist
  74. character(len=20) :: msc_mdir, msc_tres, msc_type
  75. integer :: ccyy, mm, dd, mm2, dd2
  76. integer :: year1, month1, day1, hour1
  77. integer :: year2, month2, day2
  78. ! --- begin ------------------------
  79. !
  80. ! extract fields from archivekey :
  81. ! nlev=71;sh=47;mdir=cmam;tres=_1dag_6hrly
  82. !
  83. msc_mdir = 'cmam'
  84. call goVarValue( archivekeys, ';', 'mdir', '=', msc_mdir, status )
  85. if (status>0) then; write (gol,'("in ",a)') rname; call goErr; status=1; return; end if
  86. !
  87. msc_type = 'unknown'
  88. call goVarValue( archivekeys, ';', 'type', '=', msc_type, status )
  89. if (status>0) then; write (gol,'("in ",a)') rname; call goErr; status=1; return; end if
  90. !
  91. msc_tres = '_20000101.dat'
  92. call goVarValue( archivekeys, ';', 'tres', '=', msc_tres, status )
  93. if (status>0) then; write (gol,'("in ",a)') rname; call goErr; status=1; return; end if
  94. !
  95. mf%sp_unit = 'unknown'
  96. call goVarValue( archivekeys, ';', 'sp_unit', '=', mf%sp_unit, status )
  97. if (status>0) then; write (gol,'("in ",a)') rname; call goErr; status=1; return; end if
  98. ! extract time values:
  99. call Get( t1, year=ccyy, month=mm, day=dd )
  100. ! fill filename (should be function of t1 etc):
  101. write (mf%fname,'(a,"/",a,"-",a,"-",a,"_",i4.4,i2.2,i2.2,a,".dat")') &
  102. trim(dir), trim(msc_mdir), trim(msc_type),'all', ccyy, mm, dd, trim(msc_tres)
  103. ! file exist ?
  104. inquire( file=mf%fname, exist=exist )
  105. if ( .not. exist ) then
  106. write (gol,'("msc file not found:")'); call goErr
  107. write (gol,'(" ",a)') trim(mf%fname); call goErr
  108. write (gol,'("in ",a)') rname; call goErr; status=1; return
  109. end if
  110. ! file contains data for the following time range:
  111. mf%t1 = NewDate( 2000, 01, 01, 00, 00, 00 )
  112. mf%t2 = NewDate( 2000, 01, 01, 18, 00, 00 )
  113. ! params stored in file; specify a 'minus' seperated list:
  114. mf%paramkeys = '-VO-D-T-LNSP-'
  115. ! ok
  116. status = 0
  117. end subroutine mf_Init
  118. ! ***
  119. subroutine mf_Done( mf, status )
  120. ! --- in/out -----------------------
  121. type(TMeteoFile_msc), intent(inout) :: mf
  122. integer, intent(out) :: status
  123. ! --- const --------------------------------------
  124. character(len=*), parameter :: rname = mname//'/mf_Done'
  125. ! --- begin ------------------------
  126. ! deallocate temporary arrays etc
  127. ! ok
  128. status = 0
  129. end subroutine mf_Done
  130. ! ***
  131. subroutine mf_Get( mf, status, trange1, trange2, paramkeys )
  132. use GO, only : TDate
  133. ! --- in/out ----------------------------
  134. type(TMeteoFile_msc), intent(in) :: mf
  135. integer, intent(out) :: status
  136. type(TDate), intent(out), optional :: trange1, trange2
  137. character(len=*), intent(out), optional :: paramkeys
  138. ! --- const --------------------------------------
  139. character(len=*), parameter :: rname = mname//'/mf_Get'
  140. ! --- local --------------------------------
  141. ! --- begin --------------------------------
  142. ! time range:
  143. if ( present(trange1) ) trange1 = mf%t1
  144. if ( present(trange2) ) trange2 = mf%t2
  145. ! params:
  146. if ( present(paramkeys) ) paramkeys = mf%paramkeys
  147. ! ok
  148. status = 0
  149. end subroutine mf_Get
  150. ! ***
  151. ! Return a field given parameter name, time, etc.
  152. ! Only one of grid types is filled!
  153. subroutine mf_ReadRecord( mf, paramkey, t1, t2, nuv, nw, &
  154. gridtype, levi, &
  155. lli, ll, sp_ll, &
  156. ggi, gg, sp_gg, &
  157. shi, sh, lnsp_sh, &
  158. tmi, status )
  159. use GO , only : TDate, wrtgol, Get
  160. use GO , only : goGetFU
  161. use Grid , only : TLevelInfo, Init
  162. use Grid , only : TllGridInfo, TggGridInfo, TshGridInfo
  163. use PArray , only : pa_Init, pa_Done, pa_SetShape
  164. use tmm_info , only : TMeteoInfo, Init, AddHistory
  165. ! --- in/out -------------------------------
  166. type(TMeteoFile_msc), intent(inout) :: mf
  167. character(len=*), intent(in) :: paramkey
  168. type(TDate), intent(in) :: t1, t2
  169. character(len=1), intent(in) :: nuv
  170. character(len=1), intent(in) :: nw
  171. character(len=2), intent(out) :: gridtype
  172. type(TLevelInfo), intent(out) :: levi
  173. type(TllGridInfo), intent(inout) :: lli
  174. real, pointer :: ll(:,:,:)
  175. real, pointer :: sp_ll(:,:)
  176. type(TggGridInfo), intent(inout) :: ggi
  177. real, pointer :: gg(:,:)
  178. real, pointer :: sp_gg(:)
  179. type(TshGridInfo), intent(inout) :: shi
  180. complex, pointer :: sh(:,:)
  181. complex, pointer :: lnsp_sh(:)
  182. type(TMeteoInfo), intent(out) :: tmi
  183. integer, intent(out) :: status
  184. ! --- const --------------------------------------
  185. character(len=*), parameter :: rname = mname//'/mf_ReadRecord'
  186. ! --- const --------------------------------
  187. ! number of layers
  188. integer, parameter :: nlev3d = 71
  189. ! spectral resolution
  190. integer, parameter :: shT = 47
  191. ! number of lines in record (one layer)
  192. integer, parameter :: nline = 393
  193. ! --- local -------------------------------
  194. integer :: fu
  195. integer :: year1, month1, day1, hour1, itrec
  196. integer :: nskip
  197. integer :: iline, iline_tot
  198. character(len=256) :: line
  199. character(len=10) :: htime
  200. character(len=4) :: hname
  201. integer :: ilev, nlev
  202. character(len=64) :: key
  203. logical :: read_lnsp
  204. ! --- begin ---------------------------------
  205. !write (*,'("grib read record: paramkey : ",a)') paramkey
  206. !call wrtgol( 'grib read record: t1 : ', t1 )
  207. !call wrtgol( 'grib read record: t2 : ', t2 )
  208. ! no fluxes through boundaries ...
  209. if ( nuv /= 'n' ) then
  210. write (gol,'("unsupported nuv key : ",a)') nuv; call goErr
  211. write (gol,'("in ",a)') rname; call goErr; status=1; return
  212. end if
  213. ! extract year, month, day and hour:
  214. call Get( t1, year=year1, month=month1, day=day1, hour=hour1 )
  215. ! time records for 00/06/12/18 only:
  216. select case ( hour1 )
  217. case ( 00 )
  218. itrec = 1
  219. write (htime,'(i4.4,i2.2,i2.2,i2.2)') year1,month1,day1,hour1
  220. case ( 06 )
  221. itrec = 2
  222. write (htime,'(i4.4,i2.2,i2.2,i2.2)') year1,month1,day1,hour1
  223. case ( 12 )
  224. itrec = 3
  225. write (htime,'(i4.4,i2.2,i2.2,i2.2)') year1,month1,day1,hour1
  226. case ( 18 )
  227. itrec = 4
  228. write (htime,'(i4.4,i2.2,i2.2,i2.2)') year1,month1,day1,hour1
  229. end select
  230. ! example of history:
  231. ! model==msc;sh==159;nlev==60
  232. !
  233. call Init( tmi, paramkey, 'unknown', status )
  234. call AddHistory( tmi, 'model==msc', status )
  235. !
  236. write (key,'("nlev==",i3.3)') nlev
  237. call AddHistory( tmi, trim(key), status )
  238. !
  239. write (key,'("sh==",i4.4)') shT
  240. call AddHistory( tmi, trim(key), status )
  241. ! routine returns sh grid:
  242. gridtype = 'sh'
  243. ! intialize spherical harmonic field info:
  244. call Init( shi, shT, status )
  245. IF_NOTOK_RETURN(status=1)
  246. !
  247. ! ~~~ 3d field
  248. !
  249. ! select free file unit
  250. call goGetFU( fu, status )
  251. IF_NOTOK_RETURN(status=1)
  252. ! open text file
  253. open( fu, file=trim(mf%fname), form='formatted', iostat=status )
  254. IF_NOTOK_RETURN(status=1)
  255. ! by default: 3d field, read lnsp
  256. nlev = nlev3d
  257. read_lnsp = .true.
  258. ! skip previous time records:
  259. nskip = nline * ( nlev3d * 3 + 1 ) * (itrec-1)
  260. ! number of lines to skip;
  261. ! name of field in header line:
  262. select case ( paramkey )
  263. case ( 'VO' )
  264. nskip = nskip + 0
  265. hname = 'VORT'
  266. case ( 'D' )
  267. nskip = nskip + nline * nlev3d
  268. hname = ' DIV'
  269. case ( 'T' )
  270. nskip = nskip + nline * nlev3d * 2
  271. hname = 'TEMP'
  272. case ( 'LNSP' )
  273. nskip = nskip + nline * nlev3d * 3
  274. hname = 'LNSP'
  275. nlev = 1
  276. read_lnsp = .false.
  277. case default
  278. write (gol,'("unsupported paramkey `",a,"` for nskip")') trim(paramkey); call goErr
  279. write (gol,'("in ",a)') rname; call goErr; status=1; return
  280. end select
  281. ! allocate output:
  282. call pa_SetShape( sh, shi%np, nlev )
  283. ! no lines read yet:
  284. iline_tot = 0
  285. ! skip first lines
  286. do iline = 1, nskip
  287. iline_tot = iline_tot + 1
  288. read (fu,'(a)',iostat=status) line
  289. if ( status /= 0 ) then
  290. write (gol,'("while reading line : ",i10)') iline_tot; call goErr
  291. write (gol,'("in ",a)') rname; call goErr; status=1; return
  292. end if
  293. end do
  294. ! read spectral coeff
  295. do ilev = 1, nlev
  296. ! skip header line
  297. iline_tot = iline_tot + 1
  298. read (fu,'(a)',iostat=status) line
  299. if ( status /= 0 ) then
  300. write (gol,'("while reading line : ",i10)') iline_tot; call goErr
  301. write (gol,'("in ",a)') rname; call goErr; status=1; return
  302. end if
  303. ! check: header line should contain correct variable name:
  304. if ( index(line,hname) < 1 ) then
  305. write (gol,'("record variable not ok:")'); call goErr
  306. write (gol,'(" line nr : ",i6)') iline_tot; call goErr
  307. write (gol,'(" header : ",a)') trim(line); call goErr
  308. write (gol,'(" searched : ",a)') htime; call goErr
  309. write (gol,'("in ",a)') rname; call goErr; status=1; return
  310. end if
  311. ! check: header line should contain correct time :
  312. if ( index(line,htime) < 1 ) then
  313. write (gol,'("record time not ok:")'); call goErr
  314. write (gol,'(" line nr : ",i10)') iline_tot; call goErr
  315. write (gol,'(" header : ",a)') trim(line); call goErr
  316. write (gol,'(" searched : ",a)') htime; call goErr
  317. write (gol,'("in ",a)') rname; call goErr; status=1; return
  318. end if
  319. ! read coeff
  320. do iline = 1, nline-1
  321. iline_tot = iline_tot + 1
  322. read (fu,'(6e22.15)',iostat=status) sh(iline*3-2:iline*3,ilev)
  323. if ( status /= 0 ) then
  324. write (gol,'("while reading line : ",i10)') iline_tot; call goErr
  325. write (gol,'("in ",a)') rname; call goErr; status=1; return
  326. end if
  327. end do
  328. end do
  329. ! close
  330. close( fu, iostat=status )
  331. IF_NOTOK_RETURN(status=1)
  332. ! unit conversion:
  333. select case ( paramkey )
  334. case ( 'LNSP' )
  335. ! sp * fac = exp( lnsp + ln(fac) )
  336. ! = exp( {sum_i=1,n c_i p_i} + ln(fac) )
  337. ! = exp( c_1 + {sum_i=2,n c_i p_i} + ln(fac) )
  338. select case ( mf%sp_unit )
  339. case ( 'hPa' )
  340. ! add ln(fac) to first complex coeff (only level 1 is in use):
  341. do ilev = 1, nlev
  342. sh(1,ilev) = sh(1,ilev) + cmplx(log(100.0),0.0)
  343. end do
  344. case default
  345. write (gol,'("unsupported sp unit `",a,"`")') trim(mf%sp_unit); call goErr
  346. write (gol,'("in ",a)') rname; call goErr; status=1; return
  347. end select
  348. end select
  349. ! levels
  350. select case ( nlev )
  351. case ( 1 )
  352. call Init( levi, nlev, (/0.0,0.0/), (/0.0,0.0/), status )
  353. IF_NOTOK_RETURN(status=1)
  354. case ( 71 )
  355. call Init( levi, 'msc71', status )
  356. IF_NOTOK_RETURN(status=1)
  357. case default
  358. write (gol,'("unsupported nlev `",i4,"` for levi")') nlev; call goErr
  359. write (gol,'("in ",a)') rname; call goErr; status=1; return
  360. end select
  361. !
  362. ! ~~~ surface pressure
  363. !
  364. if ( read_lnsp ) then
  365. ! allocate output:
  366. call pa_SetShape( lnsp_sh, shi%np )
  367. ! open text file
  368. open( fu, file=trim(mf%fname), form='formatted', iostat=status )
  369. IF_NOTOK_RETURN(status=1)
  370. ! skip previous time records:
  371. nskip = nline * ( nlev3d * 3 + 1 ) * (itrec-1)
  372. ! skip 3D fields
  373. nskip = nskip + nline * nlev3d * 3
  374. hname = 'LNSP'
  375. ! no lines read yet:
  376. iline_tot = 0
  377. ! skip first lines
  378. do iline = 1, nskip
  379. iline_tot = iline_tot + 1
  380. read (fu,'(a)',iostat=status) line
  381. if ( status /= 0 ) then
  382. write (gol,'("while reading line : ",i6)') iline_tot; call goErr
  383. write (gol,'("in ",a)') rname; call goErr; status=1; return
  384. end if
  385. end do
  386. ! skip header line
  387. iline_tot = iline_tot + 1
  388. read (fu,'(a)',iostat=status) line
  389. if ( status /= 0 ) then
  390. write (gol,'("while reading line : ",i6)') iline_tot; call goErr
  391. write (gol,'("in ",a)') rname; call goErr; status=1; return
  392. end if
  393. ! check: header line should contain correct variable name:
  394. if ( index(line,hname) < 1 ) then
  395. write (gol,'("record variable not ok:")'); call goErr
  396. write (gol,'(" line nr : ",i6)') iline_tot; call goErr
  397. write (gol,'(" header : ",a)') trim(line); call goErr
  398. write (gol,'(" searched : ",a)') htime; call goErr
  399. write (gol,'("in ",a)') rname; call goErr; status=1; return
  400. end if
  401. ! check: header line should contain correct time :
  402. if ( index(line,htime) < 1 ) then
  403. write (gol,'("record time not ok:")'); call goErr
  404. write (gol,'(" line nr : ",i6)') iline_tot; call goErr
  405. write (gol,'(" header : ",a)') trim(line); call goErr
  406. write (gol,'(" searched : ",a)') htime; call goErr
  407. write (gol,'("in ",a)') rname; call goErr; status=1; return
  408. end if
  409. ! read spectral coeff
  410. do iline = 1, nline-1
  411. iline_tot = iline_tot + 1
  412. read (fu,'(6e22.15)',iostat=status) lnsp_sh(iline*3-2:iline*3)
  413. if ( status /= 0 ) then
  414. write (gol,'("while reading line : ",i6)') iline_tot; call goErr
  415. write (gol,'("in ",a)') rname; call goErr; status=1; return
  416. end if
  417. end do
  418. ! close
  419. close( fu, iostat=status )
  420. IF_NOTOK_RETURN(status=1)
  421. ! unit conversion:
  422. ! sp * fac = exp( lnsp + ln(fac) )
  423. ! = exp( {sum_i=1,n c_i p_i} + ln(fac) )
  424. ! = exp( c_1 + {sum_i=2,n c_i p_i} + ln(fac) )
  425. select case ( mf%sp_unit )
  426. case ( 'hPa' )
  427. ! add ln(fac) to first complex coeff:
  428. lnsp_sh(1) = lnsp_sh(1) + cmplx(log(100.0),0.0)
  429. case default
  430. write (gol,'("unsupported sp unit `",a,"`")') trim(mf%sp_unit); call goErr
  431. write (gol,'("in ",a)') rname; call goErr; status=1; return
  432. end select
  433. end if
  434. !
  435. ! ~~~ end
  436. !
  437. ! ok
  438. status = 0
  439. end subroutine mf_ReadRecord
  440. end module tmm_mf_msc