tmm_mf.F90 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281
  1. !###############################################################################
  2. !
  3. #define TRACEBACK write (gol,'("in ",a," (",a,", line",i5,")")') rname, __FILE__, __LINE__; call goErr
  4. !
  5. #define IF_NOTOK_RETURN(action) if (status/=0) then; TRACEBACK; action; return; end if
  6. #define IF_ERROR_RETURN(action) if (status >0) then; TRACEBACK; action; return; end if
  7. !
  8. #include "tmm.inc"
  9. !
  10. !###############################################################################
  11. module tmm_mf
  12. use GO , only : gol, goErr, goPr, goBug
  13. use GO , only : TDate
  14. use Grid, only : TllGridInfo, TggGridInfo, TshGridInfo, TshGrid, TLevelInfo
  15. #ifdef with_tmm_tmpp
  16. use tmm_mf_tmpp , only : TMeteoFile_tmpp
  17. #endif
  18. #ifdef with_tmm_tm5
  19. use tmm_mf_tm5_hdf , only : TMeteoFile_tm5_hdf
  20. use tmm_mf_tm5_nc , only : TMeteoFile_tm5_nc
  21. #endif
  22. #ifdef with_tmm_ecmwf
  23. use tmm_mf_ecmwf_tmpp, only : TMeteoFile_ecmwf_tmpp
  24. use tmm_mf_ecmwf_tm5 , only : TMeteoFile_ecmwf_tm5
  25. #endif
  26. #ifdef with_tmm_ncep
  27. use tmm_mf_ncep_cdc , only : TMeteoFile_ncep_cdc
  28. use tmm_mf_ncep_gfs , only : TMeteoFile_ncep_gfs
  29. #endif
  30. #ifdef with_prism
  31. use tmm_mf_prism , only : TMeteoFile_prism
  32. #endif
  33. #ifdef with_tmm_msc
  34. use tmm_mf_msc , only : TMeteoFile_msc
  35. #endif
  36. implicit none
  37. ! --- in/out -------------------------------------
  38. private
  39. public :: TMeteoFile
  40. public :: Init, Done
  41. public :: Opened, CheckTime, CheckParam
  42. public :: SetupInput
  43. public :: ReadRecord
  44. public :: SetupOutput
  45. public :: WriteRecord
  46. ! --- const ---------------------------------------
  47. character(len=*), parameter :: mname = 'tmm_mf'
  48. ! --- types --------------------------------------
  49. type TMeteoFile
  50. ! opened yet ?
  51. logical :: opened
  52. character(len=1) :: io = ''
  53. ! meteo archive keys:
  54. character(len=256) :: dir = ''
  55. character(len=256) :: archivekey = ''
  56. ! parameter keys for fields in this file
  57. character(len=256) :: paramkeys = ''
  58. ! time range for which file is valid
  59. type(TDate) :: t1, t2
  60. !
  61. ! access to current meteo file
  62. !
  63. character(len=10) :: filetype = ''
  64. character(len=256) :: filename = ''
  65. character(len=256) :: spm_filename = ''
  66. #ifdef with_tmm_tmpp
  67. type(TMeteoFile_tmpp) :: mf_tmpp ! tmpp written hdf file
  68. #endif
  69. #ifdef with_tmm_tm5
  70. type(TMeteoFile_tm5_hdf) :: mf_tm5_hdf ! tm5 written hdf file
  71. type(TMeteoFile_tm5_nc) :: mf_tm5_nc ! tm5 written netcdf file
  72. #endif
  73. #ifdef with_tmm_ecmwf
  74. type(TMeteoFile_ecmwf_tmpp) :: mf_ecmwf_tmpp ! grib file retrieved with tmpp
  75. type(TMeteoFile_ecmwf_tm5) :: mf_ecmwf_tm5 ! grib file retrieved with tm5
  76. #endif
  77. #ifdef with_tmm_ncep
  78. type(TMeteoFile_ncep_cdc) :: mf_ncep_cdc ! ncep file from cdc archive
  79. type(TMeteoFile_ncep_gfs) :: mf_ncep_gfs ! ncep gfs file
  80. #endif
  81. #ifdef with_prism
  82. type(TMeteoFile_prism) :: mf_prism ! prism file
  83. #endif
  84. #ifdef with_tmm_msc
  85. type(TMeteoFile_msc) :: mf_msc ! msc file
  86. #endif
  87. end type TMeteoFile
  88. ! --- interfaces -------------------------------
  89. interface Init
  90. module procedure mf_Init
  91. end interface
  92. interface Done
  93. module procedure mf_Done
  94. end interface
  95. interface Opened
  96. module procedure mf_Opened
  97. end interface
  98. interface CheckTime
  99. module procedure mf_CheckTime
  100. end interface
  101. interface CheckParam
  102. module procedure mf_CheckParam
  103. end interface
  104. interface SetupInput
  105. module procedure mf_SetupInput
  106. end interface
  107. interface ReadRecord
  108. module procedure mf_ReadRecord
  109. end interface
  110. ! interface ReadEqvLatStuff
  111. ! module procedure mf_ReadEqvLatStuff
  112. ! end interface
  113. interface SetupOutput
  114. module procedure mf_SetupOutput
  115. end interface
  116. interface WriteRecord
  117. module procedure mf_WriteRecord_2d
  118. module procedure mf_WriteRecord_3d
  119. end interface
  120. contains
  121. ! ===========================================================
  122. !
  123. ! init/done
  124. !
  125. ! ===========================================================
  126. subroutine mf_Init( mf, io, status )
  127. ! --- begin -------------------------------------------
  128. type(TMeteoFile), intent(out) :: mf
  129. character(len=1), intent(in) :: io
  130. integer, intent(out) :: status
  131. ! --- const -------------------------------------------
  132. character(len=*), parameter :: rname = mname//'/mf_Init'
  133. ! --- begin -------------------------------------------
  134. ! input or output ?
  135. mf%io = io
  136. ! file not opened yet
  137. mf%opened = .false.
  138. ! ok
  139. status = 0
  140. end subroutine mf_Init
  141. ! ***
  142. subroutine mf_Done( mf, status )
  143. use GO, only : goSystem
  144. use Grid, only : Done
  145. #ifdef with_tmm_tmpp
  146. use tmm_mf_tmpp , only : Done
  147. #endif
  148. #ifdef with_tmm_tm5
  149. use tmm_mf_tm5_hdf , only : Done
  150. use tmm_mf_tm5_nc , only : Done
  151. #endif
  152. #ifdef with_tmm_ecmwf
  153. use tmm_mf_ecmwf_tmpp, only : Done
  154. use tmm_mf_ecmwf_tm5 , only : Done
  155. #endif
  156. #ifdef with_tmm_ncep
  157. use tmm_mf_ncep_cdc , only : Done
  158. use tmm_mf_ncep_gfs , only : Done
  159. #endif
  160. #ifdef with_prism
  161. use tmm_mf_prism , only : Done
  162. #endif
  163. #ifdef with_tmm_msc
  164. use tmm_mf_msc , only : Done
  165. #endif
  166. ! --- begin -------------------------------------------
  167. type(TMeteoFile), intent(inout) :: mf
  168. integer, intent(out) :: status
  169. ! --- const -------------------------------------------
  170. character(len=*), parameter :: rname = mname//'/mf_Done'
  171. ! --- begin -------------------------------------------
  172. ! close file if necessary
  173. if ( mf%opened ) then
  174. select case ( mf%filetype )
  175. #ifdef with_tmm_tmpp
  176. case ( 'tmpp' )
  177. call Done( mf%mf_tmpp, status )
  178. IF_NOTOK_RETURN(status=1)
  179. #endif
  180. #ifdef with_tmm_tm5
  181. case ( 'hdf', 'tm5-hdf' )
  182. call Done( mf%mf_tm5_hdf, status )
  183. IF_NOTOK_RETURN(status=1)
  184. case ( 'tm5-nc' )
  185. call Done( mf%mf_tm5_nc, status )
  186. IF_NOTOK_RETURN(status=1)
  187. #endif
  188. #ifdef with_tmm_ecmwf
  189. case ( 'ecmwf-tmpp' )
  190. call Done( mf%mf_ecmwf_tmpp, status )
  191. IF_NOTOK_RETURN(status=1)
  192. case ( 'ecmwf-tm5' )
  193. call Done( mf%mf_ecmwf_tm5, status )
  194. IF_NOTOK_RETURN(status=1)
  195. #endif
  196. #ifdef with_tmm_ncep
  197. case ( 'ncep-cdc' )
  198. call Done( mf%mf_ncep_cdc, status )
  199. IF_NOTOK_RETURN(status=1)
  200. case ( 'ncep-gfs' )
  201. call Done( mf%mf_ncep_gfs, status )
  202. IF_NOTOK_RETURN(status=1)
  203. #endif
  204. #ifdef with_prism
  205. case ( 'prism' )
  206. call Done( mf%mf_prism, status )
  207. IF_NOTOK_RETURN(status=1)
  208. #endif
  209. #ifdef with_tmm_msc
  210. case ( 'msc-data' )
  211. call Done( mf%mf_msc, status )
  212. IF_NOTOK_RETURN(status=1)
  213. #endif
  214. case default
  215. write (gol,'("unsupported filetype `",a,"`")') trim(mf%filetype); call goErr
  216. TRACEBACK; status=1; return
  217. end select
  218. mf%opened = .false.
  219. end if
  220. ! ok
  221. status = 0
  222. end subroutine mf_Done
  223. ! ***
  224. logical function mf_Opened( mf )
  225. ! --- begin -------------------------------------------
  226. type(TMeteoFile), intent(in) :: mf
  227. ! --- begin -------------------------------------------
  228. mf_Opened = mf%opened
  229. end function mf_Opened
  230. ! ===========================================================
  231. !
  232. ! check contents of open meteo file
  233. !
  234. ! ===========================================================
  235. ! Check time in meteo file;
  236. ! status:
  237. ! <0 : mf does not include [t1,t2]
  238. ! 0 : mf includes [t,t2]
  239. ! >0 : error; mf not open ?
  240. !
  241. subroutine mf_CheckTime( mf, t1, t2, status )
  242. use GO, only : TDate, IncrDate, wrtgol, IsAnyDate
  243. use GO, only : operator(+), operator(-), operator(==), operator(<), operator(<=)
  244. ! --- begin -------------------------------------------
  245. type(TMeteoFile), intent(in) :: mf
  246. type(TDate), intent(in) :: t1, t2
  247. integer, intent(out) :: status
  248. ! --- const -------------------------------------------
  249. character(len=*), parameter :: rname = mname//'/mf_CheckTime'
  250. ! --- begin -------------------------------------------
  251. ! not open ?
  252. if ( .not. Opened(mf) ) then
  253. write (gol,'("meteo file not opened")'); call goErr
  254. TRACEBACK; status = 1; return
  255. end if
  256. ! trap any date:
  257. if ( IsAnyDate(t1) .and. IsAnyDate(t2) ) then
  258. status = 0; return
  259. end if
  260. ! [t1,t2] is either:
  261. ! covered by mf -> status = 0
  262. ! older than mf -> status = -2
  263. ! newer than mf -> status = -1
  264. ! error ... (half in, half outside mf)
  265. ! seperate tests for intervals and instant time:
  266. if ( t1 == t2 ) then
  267. ! instant time
  268. if ( ( (mf%t1 <= t1) .and. (t1 <= mf%t2) ) ) then
  269. status = 0; return
  270. else if ( t1 < mf%t1 ) then
  271. status = -2; return
  272. else if ( mf%t2 <= t1 ) then
  273. status = -1; return
  274. else
  275. write (gol,'("requested instant time t1 (=t2) overlaps part of mf time:")'); call goErr
  276. call wrtgol( ' t1 : ', t1 ); call goErr
  277. call wrtgol( ' t2 : ', t2 ); call goErr
  278. call wrtgol( ' mf%t1 : ', mf%t1 ); call goErr
  279. call wrtgol( ' mf%t2 : ', mf%t2 ); call goErr
  280. write (gol,'(" params : ",a)') trim(mf%paramkeys); call goErr
  281. TRACEBACK; status = 1; return
  282. end if
  283. else if ( t1 < t2 ) then
  284. ! interval
  285. ! extra: [t1,t2] is covered by mf%(t1,t2) ...
  286. if ( ( (mf%t1 <= t1) .and. (t2 <= mf%t2 ) ) .or. &
  287. ( (mf%t1-IncrDate(mili=1) <= t1) .and. (t2 <= mf%t2+IncrDate(mili=1)) ) ) then
  288. status = 0; return
  289. else if ( t2 <= mf%t1 ) then
  290. ! request for field older than those in file
  291. status = -2; return
  292. else if ( mf%t2 <= t1 ) then
  293. ! request for field newer than those in file
  294. status = -1; return
  295. else
  296. write (gol,'("requested interval [t1,t2] overlaps part of mf time:")'); call goErr
  297. call wrtgol( ' t1 : ', t1 ); call goErr
  298. call wrtgol( ' t2 : ', t2 ); call goErr
  299. call wrtgol( ' mf%t1 : ', mf%t1 ); call goErr
  300. call wrtgol( ' mf%t2 : ', mf%t2 ); call goErr
  301. write (gol,'(" params : ",a)') trim(mf%paramkeys); call goErr
  302. TRACEBACK; status = 1; return
  303. end if
  304. else
  305. write (gol,'("arguments should specify an instant time or valid interval :")'); call goErr
  306. call wrtgol( ' t1 : ', t1 ); call goErr
  307. call wrtgol( ' t2 : ', t2 ); call goErr
  308. TRACEBACK; status = 1; return
  309. end if
  310. ! something wrong if this point is reached ...
  311. status = 1
  312. end subroutine mf_CheckTime
  313. ! ***
  314. ! Check if param is included in meteo file;
  315. ! status:
  316. ! <0 : mf does not include param
  317. ! 0 : mf includes param
  318. ! >0 : error; mf not open ?
  319. !
  320. subroutine mf_CheckParam( mf, io, archivekey, paramkey, status )
  321. use GO, only : goLoCase
  322. ! --- begin -------------------------------------------
  323. type(TMeteoFile), intent(in) :: mf
  324. character(len=*), intent(in) :: io
  325. character(len=*), intent(in) :: archivekey
  326. character(len=*), intent(in) :: paramkey
  327. integer, intent(out) :: status
  328. ! --- const -------------------------------------------
  329. character(len=*), parameter :: rname = mname//'/mf_CheckParam'
  330. ! --- local --------------------------------------------
  331. integer :: pos
  332. ! --- begin -------------------------------------------
  333. ! not open ?
  334. if ( .not. Opened(mf) ) then
  335. write (gol,'("meteo file not opened")'); call goErr
  336. TRACEBACK; status = 1; return
  337. end if
  338. ! by default not found ..
  339. status = -1
  340. ! wrong input/output ? then leave:
  341. if ( io /= mf%io ) return
  342. ! wrong grid ? then leave
  343. if ( archivekey /= mf%archivekey ) return
  344. ! param list is for example: '-ps-pu-pv-',
  345. ! thus search for example for '-pu-' ...
  346. ! convert all to lowercase
  347. pos = index( goLoCase(trim(mf%paramkeys)), '-'//goLoCase(trim(paramkey))//'-' )
  348. if ( pos < 1 ) return
  349. ! ok
  350. status = 0
  351. end subroutine mf_CheckParam
  352. ! ===========================================================
  353. !
  354. ! open meteo file for input
  355. !
  356. ! ===========================================================
  357. !
  358. ! Open the meteo file that contains the field specified by
  359. ! archivekey, parameter key, time,
  360. ! or do nothing if the requested file has been opened already.
  361. !
  362. ! <archivekey> = <archivetype>:<archivename>
  363. !
  364. ! tmpp:od-fc-ml60-glb3x2
  365. ! tmppS:od-fc-ml60-glb3x2
  366. ! grib:od-fc-ml60-glb3x2
  367. ! prism:
  368. !
  369. subroutine mf_SetupInput( mf, archivekey, paramkey, tday, t1, t2, &
  370. rcfilename, dir, status )
  371. use GO, only : goSplitLine, goReadFromLine
  372. use GO, only : goSystem
  373. use GO, only : TrcFile, Init, Done, ReadRc
  374. use GO, only : TDate, IncrDate, Get, NewDate, wrtgol, &
  375. Operator(+), Operator(-), Operator(/)
  376. #ifdef with_tmm_tmpp
  377. use tmm_mf_tmpp , only : Init, Get
  378. #endif
  379. #ifdef with_tmm_tm5
  380. use tmm_mf_tm5_hdf , only : Init, Get
  381. use tmm_mf_tm5_nc , only : Init, Get
  382. #endif
  383. #ifdef with_tmm_ecmwf
  384. use tmm_mf_ecmwf_tmpp, only : Init, Get
  385. use tmm_mf_ecmwf_tm5 , only : Init, Get
  386. #endif
  387. #ifdef with_tmm_ncep
  388. use tmm_mf_ncep_cdc , only : Init, Get
  389. use tmm_mf_ncep_gfs , only : Init, Get
  390. #endif
  391. #ifdef with_prism
  392. use tmm_mf_prism , only : Init
  393. #endif
  394. #ifdef with_tmm_msc
  395. use tmm_mf_msc , only : Init, Get
  396. #endif
  397. ! --- in/out -------------------------------------
  398. type(TMeteoFile), intent(inout) :: mf
  399. character(len=*), intent(in) :: archivekey
  400. character(len=*), intent(in) :: paramkey
  401. type(TDate), intent(in) :: tday, t1, t2
  402. character(len=*), intent(in) :: rcfilename
  403. character(len=*), intent(in) :: dir
  404. integer, intent(inout) :: status
  405. ! --- const -------------------------------------
  406. character(len=*), parameter :: rname = mname//'/mf_SetupInput'
  407. ! name of info file:
  408. character(len=*), parameter :: infofilename = 'tmm_info.rc'
  409. ! --- local -------------------------------------
  410. character(len=10) :: archivetype
  411. character(len=256) :: archivename
  412. character(len=256) :: command
  413. integer :: year1, month1, day1, hour1
  414. integer :: year2, month2, day2, hour2
  415. integer :: dth
  416. type(TrcFile) :: infofile
  417. character(len=256) :: archivename2
  418. character(len=10) :: mclass
  419. character(len=10) :: mtype
  420. character(len=10) :: mlevs
  421. character(len=10) :: mgrid
  422. character(len=10) :: filekey
  423. character(len=16) :: treskey
  424. logical :: with_spm
  425. logical :: constant
  426. ! --- begin -------------------------------------
  427. ! store archive key:
  428. mf%archivekey = trim(archivekey)
  429. mf%dir = trim(dir)
  430. ! split archive key in type and name:
  431. call goSplitLine( archivekey, archivetype, ':', archivename, status )
  432. IF_NOTOK_RETURN(status=1)
  433. ! usually, meteo is storred in file;
  434. ! for PRISM project, meteo is in the memory ...
  435. select case ( archivetype )
  436. #ifdef with_tmm_tmpp
  437. ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  438. ! hdf files written by tmpp
  439. ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  440. case ( 'tmpp' )
  441. ! wich of the 'mf%mf_???' is used ?
  442. mf%filetype = 'tmpp'
  443. ! setup file:
  444. call Init( mf%mf_tmpp, 'i', dir, archivename, paramkey, &
  445. tday, t1, t2, status )
  446. IF_NOTOK_RETURN(status=1)
  447. ! store filename:
  448. mf%filename = mf%mf_tmpp%fname
  449. ! extract time range:
  450. call Get( mf%mf_tmpp, status, trange1=mf%t1, trange2=mf%t2 )
  451. IF_NOTOK_RETURN(status=1)
  452. ! extract paramkeys for fields in file:
  453. call Get( mf%mf_tmpp, status, paramkeys=mf%paramkeys )
  454. IF_NOTOK_RETURN(status=1)
  455. #endif
  456. #ifdef with_tmm_tm5
  457. ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  458. ! hdf or netcdf files written by tm5
  459. ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  460. case ( 'tm5-hdf' )
  461. ! wich of the 'mf%mf_???' is used ?
  462. mf%filetype = 'tm5-hdf'
  463. ! setup file:
  464. call Init( mf%mf_tm5_hdf, 'i', dir, archivename, paramkey, &
  465. tday, t1, t2, status )
  466. IF_NOTOK_RETURN(status=1)
  467. ! store filename:
  468. mf%filename = mf%mf_tm5_hdf%fname
  469. ! extract time range:
  470. call Get( mf%mf_tm5_hdf, status, trange1=mf%t1, trange2=mf%t2 )
  471. IF_NOTOK_RETURN(status=1)
  472. ! extract paramkeys for fields in file:
  473. call Get( mf%mf_tm5_hdf, status, paramkeys=mf%paramkeys )
  474. IF_NOTOK_RETURN(status=1)
  475. case ( 'tm5-nc' )
  476. ! wich of the 'mf%mf_???' is used ?
  477. mf%filetype = 'tm5-nc'
  478. ! setup file:
  479. call Init( mf%mf_tm5_nc, 'i', dir, archivename//';form='//trim(archivetype), paramkey, &
  480. tday, t1, t2, status )
  481. IF_NOTOK_RETURN(status=1)
  482. ! store filename:
  483. mf%filename = mf%mf_tm5_nc%fname
  484. ! extract time range:
  485. call Get( mf%mf_tm5_nc, status, trange1=mf%t1, trange2=mf%t2 )
  486. IF_NOTOK_RETURN(status=1)
  487. ! extract paramkeys for fields in file:
  488. call Get( mf%mf_tm5_nc, status, paramkeys=mf%paramkeys )
  489. IF_NOTOK_RETURN(status=1)
  490. #endif
  491. #ifdef with_tmm_ecmwf
  492. ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  493. ! ecmwf grib files
  494. ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  495. case ( 'ecmwf-tmpp' )
  496. ! wich of the 'mf%mf_???' is used ?
  497. mf%filetype = 'ecmwf-tmpp'
  498. ! setup file:
  499. call Init( mf%mf_ecmwf_tmpp, dir, archivename, paramkey, &
  500. tday, t1, t2, status )
  501. IF_NOTOK_RETURN(status=1)
  502. ! store filename:
  503. mf%filename = mf%mf_ecmwf_tmpp%fname
  504. ! extract time range:
  505. call Get( mf%mf_ecmwf_tmpp, status, trange1=mf%t1, trange2=mf%t2 )
  506. IF_NOTOK_RETURN(status=1)
  507. ! extract list of parameters in files:
  508. call Get( mf%mf_ecmwf_tmpp, status, paramkeys=mf%paramkeys )
  509. IF_NOTOK_RETURN(status=1)
  510. case ( 'ecmwf-tm5' )
  511. ! wich of the 'mf%mf_???' is used ?
  512. mf%filetype = 'ecmwf-tm5'
  513. ! setup file:
  514. call Init( mf%mf_ecmwf_tm5, dir, trim(archivename), paramkey, &
  515. tday, t1, t2, status )
  516. IF_NOTOK_RETURN(status=1)
  517. ! store filename:
  518. mf%filename = mf%mf_ecmwf_tm5%fname
  519. ! extract time range:
  520. call Get( mf%mf_ecmwf_tm5, status, trange1=mf%t1, trange2=mf%t2 )
  521. IF_NOTOK_RETURN(status=1)
  522. ! extract list of parameters in files:
  523. call Get( mf%mf_ecmwf_tm5, status, paramkeys=mf%paramkeys )
  524. IF_NOTOK_RETURN(status=1)
  525. #endif
  526. #ifdef with_tmm_ncep
  527. ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  528. ! ncep files
  529. ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  530. case ( 'ncep-cdc' )
  531. ! wich of the 'mf%mf_???' is used ?
  532. mf%filetype = 'ncep-cdc'
  533. ! setup file:
  534. call Init( mf%mf_ncep_cdc, dir, archivename, paramkey, &
  535. tday, t1, t2, status )
  536. IF_NOTOK_RETURN(status=1)
  537. ! store filename:
  538. mf%filename = mf%mf_ncep_cdc%fname
  539. ! extract time range:
  540. call Get( mf%mf_ncep_cdc, status, trange1=mf%t1, trange2=mf%t2 )
  541. IF_NOTOK_RETURN(status=1)
  542. ! extract list of parameters in files:
  543. call Get( mf%mf_ncep_cdc, status, paramkeys=mf%paramkeys )
  544. IF_NOTOK_RETURN(status=1)
  545. case ( 'ncep-gfs' )
  546. ! wich of the 'mf%mf_???' is used ?
  547. mf%filetype = 'ncep-gfs'
  548. ! setup file:
  549. call Init( mf%mf_ncep_gfs, dir, archivename, paramkey, &
  550. tday, t1, t2, status )
  551. IF_NOTOK_RETURN(status=1)
  552. ! store filename:
  553. mf%filename = mf%mf_ncep_gfs%fname
  554. ! extract time range:
  555. call Get( mf%mf_ncep_gfs, status, trange1=mf%t1, trange2=mf%t2 )
  556. IF_NOTOK_RETURN(status=1)
  557. ! extract list of parameters in files:
  558. call Get( mf%mf_ncep_gfs, status, paramkeys=mf%paramkeys )
  559. IF_NOTOK_RETURN(status=1)
  560. #endif
  561. #ifdef with_tmm_msc
  562. ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  563. ! msc-data text files
  564. ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  565. case ( 'msc-data' )
  566. ! wich of the 'mf%mf_???' is used ?
  567. mf%filetype = 'msc-data'
  568. ! setup file:
  569. call Init( mf%mf_msc, dir, archivename, paramkey, &
  570. tday, t1, t2, status )
  571. IF_NOTOK_RETURN(status=1)
  572. ! store filename:
  573. mf%filename = mf%mf_msc%fname
  574. ! extract time range:
  575. call Get( mf%mf_msc, status, trange1=mf%t1, trange2=mf%t2 )
  576. IF_NOTOK_RETURN(status=1)
  577. ! extract which fields are stored in the file:
  578. call Get( mf%mf_msc, status, paramkeys=mf%paramkeys )
  579. IF_NOTOK_RETURN(status=1)
  580. #endif
  581. #ifdef with_prism
  582. ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  583. ! prism meteo in memory
  584. ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  585. case ( 'prism' )
  586. ! only the requested parameter is provided by this prism 'file' ...
  587. mf%paramkeys = '-'//paramkey//'-'
  588. ! infinite time range ...
  589. mf%t1 = NewDate( year=1900, month=1, day=1, hour=1 )
  590. mf%t2 = NewDate( year=9999, month=9, day=9, hour=9 )
  591. !call wrtgol( ' fields valid from : ', mf%t1 )
  592. !call wrtgol( ' to : ', mf%t2 )
  593. ! set file type and file name:
  594. mf%filetype = 'prism'
  595. mf%filename = 'dummy'
  596. ! setup prism access;
  597. ! tday is used for orography date
  598. ! (adhoc solution; at the moment only [t1,t2] is provided to ReadRecord
  599. ! but this should become tday, [t1,t2] )
  600. call Init( mf%mf_prism, tday, status )
  601. IF_NOTOK_RETURN(status=1)
  602. #endif
  603. ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  604. ! error ...
  605. ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  606. case default
  607. write (gol,'("unsupported archivetype `",a,"`")') trim(archivetype); call goErr
  608. TRACEBACK; status=1; return
  609. end select
  610. ! file is opened (or, at least file name is known)
  611. mf%opened = .true.
  612. ! ok
  613. status = 0
  614. end subroutine mf_SetupInput
  615. ! ===========================================================
  616. !
  617. ! read fields, grid definition, etc
  618. !
  619. ! ===========================================================
  620. subroutine mf_ReadRecord( mf, paramkey, unit, tday, t1, t2, nuv, nw, &
  621. gridtype, levi, &
  622. lli, ll, sp_ll, &
  623. ggi, gg, sp_gg, &
  624. shi, sh, lnsp_sh, &
  625. tmi, status )
  626. use GO , only : TDate, operator(+), operator(-), operator(/)
  627. use Grid , only : TllGridInfo, TggGridInfo, TshGridInfo, TLevelInfo
  628. use tmm_info , only : TMeteoInfo, Init, AddHistory
  629. #ifdef with_tmm_tmpp
  630. use tmm_mf_tmpp , only : ReadRecord
  631. #endif
  632. #ifdef with_tmm_tm5
  633. use tmm_mf_tm5_hdf , only : ReadRecord
  634. use tmm_mf_tm5_nc , only : ReadRecord
  635. #endif
  636. #ifdef with_tmm_ecmwf
  637. use tmm_mf_ecmwf_tmpp, only : ReadRecord
  638. use tmm_mf_ecmwf_tm5 , only : ReadRecord
  639. #endif
  640. #ifdef with_tmm_ncep
  641. use tmm_mf_ncep_cdc , only : ReadRecord
  642. use tmm_mf_ncep_gfs , only : ReadRecord
  643. #endif
  644. #ifdef with_prism
  645. use tmm_mf_prism , only : ReadRecord
  646. #endif
  647. #ifdef with_tmm_msc
  648. use tmm_mf_msc , only : ReadRecord
  649. #endif
  650. ! --- in/out -------------------------------
  651. type(TMeteoFile), intent(inout) :: mf
  652. character(len=*), intent(in) :: paramkey
  653. character(len=*), intent(in) :: unit
  654. type(TDate), intent(in) :: tday, t1, t2
  655. character(len=1), intent(in) :: nuv
  656. character(len=1), intent(in) :: nw
  657. character(len=2), intent(out) :: gridtype
  658. type(TLevelInfo), intent(out) :: levi
  659. type(TllGridInfo), intent(inout) :: lli
  660. real, pointer :: ll(:,:,:)
  661. real, pointer :: sp_ll(:,:)
  662. type(TggGridInfo), intent(inout) :: ggi
  663. real, pointer :: gg(:,:)
  664. real, pointer :: sp_gg(:)
  665. type(TshGridInfo), intent(inout) :: shi
  666. complex, pointer :: sh(:,:)
  667. complex, pointer :: lnsp_sh(:)
  668. type(TMeteoInfo), intent(out) :: tmi
  669. integer, intent(out) :: status
  670. ! --- const --------------------------------------
  671. character(len=*), parameter :: rname = mname//'/mf_ReadRecord'
  672. ! --- local --------------------------------------
  673. type(TDate) :: tmid
  674. ! --- begin ---------------------------------
  675. !write (*,'(a,": begin")') name
  676. select case ( mf%filetype )
  677. #ifdef with_tmm_tmpp
  678. case ( 'tmpp' )
  679. ! read from hdf file:
  680. call ReadRecord( mf%mf_tmpp, paramkey, t1, t2, nuv, nw, &
  681. gridtype, levi, &
  682. lli, ll, sp_ll, &
  683. status )
  684. IF_NOTOK_RETURN(status=1)
  685. ! fill some info values:
  686. call Init( tmi, paramkey, 'unkown', status )
  687. call AddHistory( tmi, 'archivekey=='//trim(mf%archivekey), status )
  688. #endif
  689. #ifdef with_tmm_tm5
  690. case ( 'hdf', 'tm5-hdf' )
  691. ! read from hdf file:
  692. call ReadRecord( mf%mf_tm5_hdf, paramkey, t1, t2, nuv, nw, &
  693. gridtype, levi, &
  694. lli, ll, sp_ll, &
  695. status )
  696. IF_NOTOK_RETURN(status=1)
  697. ! fill some info values:
  698. call Init( tmi, paramkey, 'unkown', status )
  699. call AddHistory( tmi, 'archivekey=='//trim(mf%archivekey), status )
  700. case ( 'tm5-nc' ) ! read from netcdf file
  701. call ReadRecord( mf%mf_tm5_nc, paramkey, unit, t1, t2, nuv, nw, &
  702. gridtype, levi, lli, ll, sp_ll, status )
  703. IF_NOTOK_RETURN(status=1)
  704. ! fill some info values:
  705. call Init( tmi, paramkey, 'unkown', status )
  706. call AddHistory( tmi, 'archivekey=='//trim(mf%archivekey), status )
  707. #endif
  708. #ifdef with_tmm_ecmwf
  709. case ( 'ecmwf-tmpp' )
  710. ! read from grib file:
  711. call ReadRecord( mf%mf_ecmwf_tmpp, paramkey, t1, t2, nuv, nw, &
  712. gridtype, levi, &
  713. lli, ll, sp_ll, &
  714. ggi, gg, sp_gg, &
  715. shi, sh, lnsp_sh, &
  716. tmi, status )
  717. IF_NOTOK_RETURN(status=1)
  718. case ( 'ecmwf-tm5' )
  719. ! read from grib file:
  720. call ReadRecord( mf%mf_ecmwf_tm5, paramkey, tday, t1, t2, nuv, nw, &
  721. gridtype, levi, &
  722. lli, ll, sp_ll, &
  723. ggi, gg, sp_gg, &
  724. shi, sh, lnsp_sh, &
  725. tmi, status )
  726. IF_NOTOK_RETURN(status=1)
  727. #endif
  728. #ifdef with_tmm_ncep
  729. case ( 'ncep-cdc' )
  730. ! read from ncep file:
  731. call ReadRecord( mf%mf_ncep_cdc, paramkey, t1, t2, nuv, nw, &
  732. gridtype, levi, &
  733. lli, ll, sp_ll, &
  734. ggi, gg, sp_gg, &
  735. shi, sh, lnsp_sh, &
  736. tmi, status )
  737. IF_NOTOK_RETURN(status=1)
  738. #endif
  739. #ifdef with_tmm_ncep
  740. case ( 'ncep-gfs' )
  741. ! read from ncep file:
  742. call ReadRecord( mf%mf_ncep_gfs, paramkey, t1, t2, nuv, nw, &
  743. gridtype, levi, &
  744. lli, ll, sp_ll, &
  745. ggi, gg, sp_gg, &
  746. shi, sh, lnsp_sh, &
  747. tmi, status )
  748. IF_NOTOK_RETURN(status=1)
  749. #endif
  750. #ifdef with_prism
  751. case ( 'prism' )
  752. ! receive from oasis coupler:
  753. call ReadRecord( mf%mf_prism, paramkey, t1, t2, nuv, nw, &
  754. gridtype, levi, &
  755. lli, ll, sp_ll, &
  756. ggi, gg, sp_gg, &
  757. shi, sh, lnsp_sh, &
  758. tmi, status )
  759. IF_NOTOK_RETURN(status=1)
  760. #endif
  761. #ifdef with_tmm_msc
  762. case ( 'msc-data' )
  763. ! read from grib file:
  764. tmid = t1 + (t2-t1)/2
  765. call ReadRecord( mf%mf_msc, paramkey, tmid, tmid, nuv, nw, &
  766. gridtype, levi, &
  767. lli, ll, sp_ll, &
  768. ggi, gg, sp_gg, &
  769. shi, sh, lnsp_sh, &
  770. tmi, status )
  771. IF_NOTOK_RETURN(status=1)
  772. #endif
  773. case default
  774. write (gol,'("unsupported filetype `",a,"`")') trim(mf%filetype); call goErr
  775. TRACEBACK; status=1; return
  776. end select
  777. ! ok
  778. status = 0
  779. !write (*,'(a,": end")') name
  780. end subroutine mf_ReadRecord
  781. ! ***
  782. ! ===========================================================
  783. !
  784. ! open meteo file for output
  785. !
  786. ! ===========================================================
  787. !
  788. ! Open the meteo file that should contain the field specified by
  789. ! archivekey, parameter key, time,
  790. ! or do nothing if the requested file has been opened already.
  791. !
  792. ! <archivekey> = <archivetype>:<archivename>
  793. !
  794. ! tmpp:od-fc-ml60-glb3x2
  795. !
  796. subroutine mf_SetupOutput( mf, archivekey, paramkey, tday, t1, t2, &
  797. rcfilename, dir, status )
  798. use GO, only : goSplitLine
  799. use GO, only : TrcFile, Init, Done, ReadRc
  800. use GO, only : TDate
  801. #ifdef with_tmm_tm5
  802. use tmm_mf_tm5_hdf , only : Init, Get
  803. use tmm_mf_tm5_nc , only : Init, Get
  804. #endif
  805. ! --- in/out -------------------------------------
  806. type(TMeteoFile), intent(inout) :: mf
  807. character(len=*), intent(in) :: archivekey
  808. character(len=*), intent(in) :: paramkey
  809. type(TDate), intent(in) :: tday, t1, t2
  810. character(len=*), intent(in) :: rcfilename
  811. character(len=*), intent(in) :: dir
  812. integer, intent(inout) :: status
  813. ! --- const -------------------------------------
  814. character(len=*), parameter :: rname = mname//'/mf_SetupOutput'
  815. ! --- local -------------------------------------
  816. character(len=10) :: archivetype
  817. character(len=256) :: archivename
  818. ! character(len=256) :: command
  819. ! integer :: year1, month1, day1, hour1
  820. ! integer :: year2, month2, day2, hour2
  821. ! integer :: dth
  822. type(TrcFile) :: infofile
  823. character(len=256) :: archivename2
  824. character(len=10) :: mclass
  825. character(len=10) :: mtype
  826. character(len=10) :: mlevs
  827. character(len=10) :: mgrid
  828. character(len=10) :: filekey
  829. character(len=16) :: treskey
  830. logical :: with_spm
  831. ! --- begin -------------------------------------
  832. ! store archive key:
  833. mf%archivekey = trim(archivekey)
  834. ! split archive key in type and name:
  835. call goSplitLine( archivekey, archivetype, ':', archivename, status )
  836. IF_NOTOK_RETURN(status=1)
  837. ! deceide on archive type:
  838. select case ( archivetype )
  839. #ifdef with_tmm_tm5
  840. ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  841. ! daily hdf day files
  842. ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  843. case ( 'tm5-hdf' )
  844. ! always hdf files:
  845. mf%filetype = 'tm5-hdf'
  846. ! setup file:
  847. call Init( mf%mf_tm5_hdf, 'o', dir, trim(archivename), paramkey, &
  848. tday, t1, t2, status )
  849. IF_NOTOK_RETURN(status=1)
  850. ! store filename:
  851. call Get( mf%mf_tm5_hdf, status, filename=mf%filename )
  852. IF_NOTOK_RETURN(status=1)
  853. ! extract time range:
  854. call Get( mf%mf_tm5_hdf, status, trange1=mf%t1, trange2=mf%t2 )
  855. IF_NOTOK_RETURN(status=1)
  856. ! extract paramkeys for fields in file:
  857. call Get( mf%mf_tm5_hdf, status, paramkeys=mf%paramkeys )
  858. IF_NOTOK_RETURN(status=1)
  859. case ( 'tm5-nc' )
  860. ! always netcdf files:
  861. mf%filetype = 'tm5-nc'
  862. ! setup file:
  863. call Init( mf%mf_tm5_nc, 'o', dir, trim(archivename), paramkey, &
  864. tday, t1, t2, status )
  865. IF_NOTOK_RETURN(status=1)
  866. ! store filename:
  867. call Get( mf%mf_tm5_nc, status, filename=mf%filename )
  868. IF_NOTOK_RETURN(status=1)
  869. ! extract time range:
  870. call Get( mf%mf_tm5_nc, status, trange1=mf%t1, trange2=mf%t2 )
  871. IF_NOTOK_RETURN(status=1)
  872. ! extract paramkeys for fields in file:
  873. call Get( mf%mf_tm5_nc, status, paramkeys=mf%paramkeys )
  874. IF_NOTOK_RETURN(status=1)
  875. #endif
  876. ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  877. ! error ...
  878. ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  879. case default
  880. write (gol,'("unsupported archivetype `",a,"`")') trim(archivetype); call goErr
  881. write (gol,'(" for archivekey `",a,"`")') trim(archivekey); call goErr
  882. write (gol,'(" and for paramkey `",a,"`")') trim(paramkey); call goErr
  883. TRACEBACK; status=1; return
  884. end select
  885. ! file is opened (or, at least file name is known)
  886. mf%opened = .true.
  887. ! ok
  888. status = 0
  889. end subroutine mf_SetupOutput
  890. ! ***
  891. subroutine mf_WriteRecord_2d( mf, tmi, paramkey, unit, tday, t1, t2, &
  892. lli, nuv, ll, status )
  893. use GO , only : TDate
  894. use Grid , only : TllGridInfo
  895. use tmm_info , only : TMeteoInfo
  896. #ifdef with_tmm_tm5
  897. use tmm_mf_tm5_hdf, only : WriteRecord
  898. use tmm_mf_tm5_nc , only : WriteRecord
  899. #endif
  900. ! --- in/out -------------------------------
  901. type(TMeteoFile), intent(inout) :: mf
  902. type(TMeteoInfo), intent(in) :: tmi
  903. character(len=*), intent(in) :: paramkey, unit
  904. type(TDate), intent(in) :: tday, t1, t2
  905. type(TllGridInfo), intent(in) :: lli
  906. character(len=1), intent(in) :: nuv
  907. real, intent(in) :: ll(:,:)
  908. integer, intent(out) :: status
  909. ! --- const --------------------------------------
  910. character(len=*), parameter :: rname = mname//'/mf_WriteRecord_2d'
  911. ! --- begin ---------------------------------
  912. select case ( mf%filetype )
  913. #ifdef with_tmm_tm5
  914. case ( 'hdf', 'tm5-hdf' )
  915. call WriteRecord( mf%mf_tm5_hdf, tmi, paramkey, unit, tday, t1, t2, &
  916. lli, nuv, ll, status )
  917. IF_NOTOK_RETURN(status=1)
  918. case ( 'tm5-nc' )
  919. call WriteRecord( mf%mf_tm5_nc, tmi, paramkey, unit, tday, t1, t2, &
  920. lli, nuv, ll, status )
  921. IF_NOTOK_RETURN(status=1)
  922. #endif
  923. case default
  924. write (gol,'("unsupported filetype `",a,"`")') trim(mf%filetype); call goErr
  925. TRACEBACK; status=1; return
  926. end select
  927. ! ok
  928. status = 0
  929. end subroutine mf_WriteRecord_2d
  930. ! ***
  931. subroutine mf_WriteRecord_3d( mf, tmi, spname, paramkey, unit, tday, t1, t2, &
  932. lli, nuv, levi, nw, ps, ll, status )!, &
  933. !nlev )
  934. use GO , only : TDate
  935. use Grid , only : TllGridInfo, TLevelInfo
  936. use tmm_info , only : TMeteoInfo
  937. #ifdef with_tmm_tm5
  938. use tmm_mf_tm5_hdf, only : WriteRecord
  939. use tmm_mf_tm5_nc , only : WriteRecord
  940. #endif
  941. ! --- in/out -------------------------------
  942. type(TMeteoFile), intent(inout) :: mf
  943. type(TMeteoInfo), intent(in) :: tmi
  944. character(len=*), intent(in) :: spname, paramkey, unit
  945. type(TDate), intent(in) :: tday, t1, t2
  946. type(TllGridInfo), intent(in) :: lli
  947. character(len=1), intent(in) :: nuv
  948. type(TLevelInfo), intent(in) :: levi
  949. character(len=1), intent(in) :: nw
  950. real, intent(in) :: ps(:,:)
  951. real, intent(in) :: ll(:,:,:)
  952. integer, intent(out) :: status
  953. !integer, intent(in), optional :: nlev
  954. ! --- const --------------------------------------
  955. character(len=*), parameter :: rname = mname//'/mf_WriteRecord_3d'
  956. ! --- begin ---------------------------------
  957. select case ( mf%filetype )
  958. #ifdef with_tmm_tm5
  959. case ( 'tm5-hdf' )
  960. call WriteRecord( mf%mf_tm5_hdf, tmi, spname, paramkey, unit, tday, t1, t2, &
  961. lli, nuv, levi, nw, ps, ll, status )!, &
  962. !nlev=nlev )
  963. IF_NOTOK_RETURN(status=1)
  964. case ( 'tm5-nc' )
  965. call WriteRecord( mf%mf_tm5_nc, tmi, spname, paramkey, unit, tday, t1, t2, &
  966. lli, nuv, levi, nw, ps, ll, status )!, &
  967. !nlev=nlev )
  968. IF_NOTOK_RETURN(status=1)
  969. #endif
  970. case default
  971. write (gol,'("unsupported filetype `",a,"`")') trim(mf%filetype); call goErr
  972. TRACEBACK; status=1; return
  973. end select
  974. ! ok
  975. status = 0
  976. end subroutine mf_WriteRecord_3d
  977. end module tmm_mf