tmm_mf_tm5_nc.F90 94 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830
  1. !###############################################################################
  2. !
  3. ! Input/output of meteofiles produced by TM5 : NetCDF version.
  4. !
  5. !###############################################################################
  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_tm5_nc
  15. use GO, only : gol, goErr, goPr
  16. use GO , only : TDate
  17. !use MDF, only : MDF_NETCDF
  18. use MDF, only : MDF_NETCDF4
  19. implicit none
  20. ! --- in/out -----------------------------------
  21. private
  22. public :: TMeteoFile_tm5_nc
  23. public :: TMM_MF_TM5_NC_Init, TMM_MF_TM5_NC_Done
  24. public :: Init, Done
  25. public :: Get
  26. public :: ReadRecord
  27. public :: WriteRecord
  28. ! --- const ------------------------------------
  29. character(len=*), parameter :: mname = 'tmm_mf_tm5_nc'
  30. ! ~~~ output keys and defaults
  31. ! current format version
  32. character(len=*), parameter :: output_format = 'tm5-nc'
  33. ! extension and type:
  34. !integer, parameter :: output_type = MDF_NETCDF
  35. integer, parameter :: output_type = MDF_NETCDF4
  36. character(len=*), parameter :: output_ext = '.nc'
  37. ! standard timevalue is seconds since ...
  38. integer, parameter :: since_time6(6) = (/1900,01,01,00,00,00/)
  39. !--- type --------------------------------------
  40. type TMeteoFile_tm5_nc
  41. ! input/output ?
  42. character(len=1) :: io
  43. !
  44. ! field collection
  45. !
  46. character(len=256) :: fname
  47. character(len=256) :: paramkeys ! -aa-bb-cc-
  48. integer :: nparam
  49. character(len=64) :: tres
  50. type(TDate) :: trange(2)
  51. logical :: is_aver
  52. integer :: rnk
  53. !
  54. ! file
  55. !
  56. integer :: hid
  57. integer :: dimid_nv
  58. integer :: dimid_lon, varid_lon, varid_lon_bounds
  59. integer :: dimid_lat, varid_lat, varid_lat_bounds
  60. integer :: dimid_lonb, varid_lonb
  61. integer :: dimid_latb, varid_latb
  62. integer :: dimid_lev, varid_lev, varid_ap, varid_b, varid_ap_bounds, varid_b_bounds
  63. integer :: dimid_lev_u, varid_lev_u
  64. integer :: dimid_lev_v, varid_lev_v
  65. integer :: dimid_time, varid_time, varid_time_bounds, varid_reftime
  66. integer :: dimid_timeval, varid_timevalues, varid_timevalues_bounds, varid_reftimevalues
  67. integer :: varid_cell_area
  68. integer :: varid_ps, varid_ps_u, varid_ps_v
  69. !integer :: dimid_tm5_lm, dimid_tm5_lmb, varid_tm5_at, varid_tm5_bt
  70. integer, allocatable :: varid_param(:)
  71. character(len=16), allocatable :: varname_param(:) ! (/'aa','bb','cc'/)
  72. character(len=256), allocatable :: cfname_param(:) ! from CF table
  73. character(len=64), allocatable :: cfunit_param(:) ! from CF table, following UDUnits
  74. integer, allocatable :: itrec_param(:)
  75. !
  76. ! output
  77. !
  78. logical :: output_initialised
  79. integer :: output_nrec
  80. integer :: output_ntrec
  81. !
  82. ! adhoc ...
  83. integer :: fixyear
  84. end type TMeteoFile_tm5_nc
  85. ! --- interfaces -------------------------------
  86. interface Init
  87. module procedure mf_Init
  88. end interface
  89. interface Done
  90. module procedure mf_Done
  91. end interface
  92. interface Get
  93. module procedure mf_Get
  94. end interface
  95. interface ReadRecord
  96. #ifdef with_parallel_io_meteo
  97. module procedure mf_ReadRecord_parallel_io
  98. #else
  99. module procedure mf_ReadRecord_serial_io
  100. #endif
  101. end interface
  102. interface WriteRecord
  103. module procedure mf_WriteRecord_2d
  104. module procedure mf_WriteRecord_3d
  105. end interface
  106. ! --- var --------------------------------------
  107. ! timer id's:
  108. integer :: itim_readrecord
  109. logical, save :: use_tiedtke
  110. contains
  111. ! ==============================================================
  112. subroutine TMM_MF_TM5_NC_Init( rcf, status )
  113. use GO, only : TrcFile, ReadRc
  114. use GO, only : GO_Timer_Def
  115. use TMM_CF, only : TMM_CF_Init
  116. ! --- in/out ---------------------------------
  117. type(TRcFile), intent(in) :: rcf
  118. integer, intent(out) :: status
  119. ! --- const ----------------------------------
  120. character(len=*), parameter :: rname = mname//'/TMM_MF_TM5_NC_Init'
  121. ! --- local ----------------------------------
  122. ! --- begin ----------------------------------
  123. ! init cf table and udunits package:
  124. call TMM_CF_Init( rcf, status )
  125. IF_NOTOK_RETURN(status=1)
  126. ! are convection fluxes derived (Tiedtke, sub files) or from IFS (convec files)?
  127. call ReadRc( rcF, 'tiedtke', use_tiedtke, status )
  128. IF_NOTOK_RETURN(status=1)
  129. ! define timers:
  130. call GO_Timer_Def( itim_readrecord, 'tmm tm5-nc readrecord', status )
  131. IF_NOTOK_RETURN(status=1)
  132. ! ok
  133. status = 0
  134. end subroutine TMM_MF_TM5_NC_Init
  135. ! ***
  136. subroutine TMM_MF_TM5_NC_Done( status )
  137. use TMM_CF, only : TMM_CF_Done
  138. ! --- in/out ---------------------------------
  139. integer, intent(out) :: status
  140. ! --- const ----------------------------------
  141. character(len=*), parameter :: rname = mname//'/TMM_MF_TM5_NC_Done'
  142. ! --- local ----------------------------------
  143. ! --- begin ----------------------------------
  144. ! done with standard names table and udunits package:
  145. call TMM_CF_Done( status )
  146. IF_NOTOK_RETURN(status=1)
  147. ! ok
  148. status = 0
  149. end subroutine TMM_MF_TM5_NC_Done
  150. ! ==============================================================
  151. subroutine mf_Init( mf, io, dir, archivekeys, paramkey, &
  152. tref, t1, t2, status )
  153. use GO, only : TDate, Set, Get, NewDate, AnyDate, IsAnyDate
  154. use GO, only : rTotal, operator(-), operator(>=)
  155. use GO, only : goVarValue, goWriteKeyNum, goReplace
  156. ! --- in/out ----------------------------
  157. type(TMeteoFile_tm5_nc), intent(out) :: mf
  158. character(len=1), intent(in) :: io
  159. character(len=*), intent(in) :: dir
  160. character(len=*), intent(in) :: archivekeys
  161. character(len=*), intent(in) :: paramkey
  162. type(TDate), intent(in) :: tref, t1, t2
  163. integer, intent(out) :: status
  164. ! --- const --------------------------------------
  165. character(len=*), parameter :: rname = mname//'/mf_Init'
  166. ! --- local --------------------------------
  167. character(len=64) :: mf_mdir
  168. character(len=1) :: mf_psep, mf_nsep
  169. character(len=64) :: mf_filekey
  170. character(len=4) :: mf_fckey
  171. type(TDate) :: tfile
  172. integer :: ccyy, mm, dd, dh
  173. type(TDate) :: tc
  174. ! --- begin --------------------------------
  175. ! store i/o :
  176. mf%io = io
  177. ! default flags:
  178. mf%is_aver = .false.
  179. mf%rnk = 2 ! most 2D fields
  180. !
  181. ! extract fields from archivekey :
  182. ! mdir=ec-fg_3h-ml60-glb3x2;tres=_21p06
  183. !
  184. mf%fixyear = -1
  185. call goVarValue( archivekeys, ';', 'fixyear', '=', mf%fixyear, status )
  186. if (status>0) then; TRACEBACK; status=1; return; end if
  187. mf_mdir = 'no_mdir'
  188. call goVarValue( archivekeys, ';', 'mdir', '=', mf_mdir, status )
  189. if (status>0) then; TRACEBACK; status=1; return; end if
  190. !
  191. mf%tres = 'no_tres'
  192. call goVarValue( archivekeys, ';', 'tres', '=', mf%tres, status )
  193. if (status>0) then; TRACEBACK; status=1; return; end if
  194. !
  195. ! path seperation character:
  196. mf_psep = '/'
  197. call goVarValue( archivekeys, ';', 'pathsep', '=', mf_psep, status )
  198. if (status>0) then; TRACEBACK; status=1; return; end if
  199. !
  200. ! name seperation character:
  201. mf_nsep = '-'
  202. call goVarValue( archivekeys, ';', 'namesep', '=', mf_nsep, status )
  203. if (status>0) then; TRACEBACK; status=1; return; end if
  204. !
  205. ! main file
  206. !
  207. ! * set mf_filekey (uvsp,t,etc) and parmeters:
  208. select case ( paramkey )
  209. case ( 'sp', 'tsp' )
  210. mf_filekey = paramkey
  211. mf%paramkeys = '-'//trim(paramkey)//'-'
  212. mf%nparam = 1
  213. case ( 'mfu', 'mfv' )
  214. mf_filekey = 'mfuv'
  215. mf%paramkeys = '-mfu-mfv-'
  216. mf%nparam = 2
  217. mf%rnk = 3
  218. case ( 'mfw' )
  219. mf_filekey = 'mfw'
  220. mf%paramkeys = '-mfw-'
  221. mf%nparam = 1
  222. mf%rnk = 3
  223. case ( 'T' )
  224. mf_filekey = 't'
  225. mf%paramkeys = '-T-'
  226. mf%nparam = 1
  227. mf%rnk = 3
  228. case ( 'Q' )
  229. mf_filekey = 'q'
  230. mf%paramkeys = '-Q-'
  231. mf%nparam = 1
  232. mf%rnk = 3
  233. case ( 'CLWC', 'CIWC', 'CC', 'CCO', 'CCU', &
  234. 'clwc', 'ciwc', 'cc', 'cco', 'ccu' )
  235. mf_filekey = 'cld'
  236. mf%paramkeys = '-CLWC-CIWC-CC-CCO-CCU-'
  237. mf%nparam = 5
  238. mf%rnk = 3
  239. case ( 'eu', 'ed', 'du', 'dd' ) ! computed online: 'cloud_base', 'cloud_top', 'cloud_lfs'
  240. if (use_tiedtke) then
  241. mf_filekey = 'sub'
  242. else
  243. mf_filekey = 'convec'
  244. endif
  245. mf%paramkeys = '-eu-ed-du-dd-'
  246. mf%nparam = 4
  247. mf%rnk = 3
  248. case ( 'K' )
  249. mf_filekey = 'diffus'
  250. mf%paramkeys = '-K-'
  251. mf%nparam = 1
  252. mf%rnk = 3
  253. ! o constant fields
  254. case ( 'oro', 'lsm' )
  255. mf%tres = 'constant'
  256. mf_filekey = trim(paramkey)
  257. mf%paramkeys = '-'//trim(paramkey)//'-'
  258. mf%nparam = 1
  259. ! o monthly fields:
  260. case ( 'srols' )
  261. mf%tres = 'month'
  262. mf_filekey = trim(paramkey)
  263. mf%paramkeys = '-'//trim(paramkey)//'-'
  264. mf%nparam = 1
  265. ! o vegetation fields
  266. case ( 'cvl', 'cvh', &
  267. 'tv01', 'tv02', 'tv03', 'tv04', 'tv05', &
  268. 'tv06', 'tv07', 'tv09', 'tv10', &
  269. 'tv11', 'tv13', &
  270. 'tv16', 'tv17', 'tv18', 'tv19' )
  271. mf_filekey = 'veg'
  272. mf%paramkeys = '-'//&
  273. 'cvl-cvh-'//&
  274. 'tv01-tv02-tv03-tv04-tv05-'//&
  275. 'tv06-tv07-tv09-tv10-'//&
  276. 'tv11-tv13-'//&
  277. 'tv16-tv17-tv18-tv19-'
  278. mf%nparam = 17
  279. ! o each surface file in a seperate file:
  280. case ( 'sr', 'srmer', &
  281. 'swvl1', 'stl1', &
  282. 'albedo', 'lsrh', 'ci', 'fg10','g10m', 'u10m', 'v10m', 'sd', &
  283. 'blh', &
  284. 't2m', 'd2m', &
  285. 'sstr', 'src', 'raero', 'ustar', &
  286. 'sst', 'sps', 'skt' )
  287. mf_filekey = trim(paramkey)
  288. mf%paramkeys = '-'//trim(paramkey)//'-'
  289. mf%nparam = 1
  290. case ( 'sshf', 'slhf', 'ewss', 'nsss', 'lsp', 'cp', 'sf', &
  291. 'ssr', 'ssrd', 'str', 'strd' )
  292. mf_filekey = trim(paramkey)
  293. mf%paramkeys = '-'//trim(paramkey)//'-'
  294. mf%nparam = 1
  295. mf%is_aver = .true.
  296. case default
  297. write (gol,'("unsupported paramkey `",a,"`")') paramkey; call goErr
  298. TRACEBACK; status=1; return
  299. end select
  300. ! storage:
  301. allocate( mf%varid_param (mf%nparam) )
  302. allocate( mf%varname_param(mf%nparam) )
  303. allocate( mf%cfname_param (mf%nparam) )
  304. allocate( mf%cfunit_param (mf%nparam) )
  305. allocate( mf%itrec_param (mf%nparam) )
  306. ! convert input times to file name times:
  307. call GetTime( mf_filekey, mf%tres, tref, t1, t2, status, &
  308. tfile=tfile, trange=mf%trange )
  309. IF_NOTOK_RETURN(status=1)
  310. ! adhoc: fixed year ?
  311. if ( mf%fixyear > 0 ) call Set( tfile, year=mf%fixyear )
  312. ! extract time values:
  313. call Get( tfile, year=ccyy, month=mm, day=dd )
  314. ! replace time values in directory name:
  315. call goReplace( mf_mdir, '<yyyy>', '(i4.4)', ccyy, status )
  316. IF_NOTOK_RETURN(status=1)
  317. call goReplace( mf_mdir, '<mm>', '(i2.2)', mm, status )
  318. IF_NOTOK_RETURN(status=1)
  319. ! special data set: trap change from fg to fc data:
  320. if ( mf%tres == '_fg006up4tr3' ) then
  321. tc = NewDate( 2000, 09, 12 )
  322. if ( tfile >= tc ) mf%tres = '_fc012up2tr3'
  323. end if
  324. ! forecast key: '', 'f1', .., 'f10' ;
  325. ! no key for constant files (t1 and t2 are anydate)
  326. ! or month files (t1 is begin of month thus probably < tref)
  327. mf_fckey = ''
  328. if ( (.not. IsAnyDate(t1)) .and. (t1 >= tref) ) then
  329. dh = floor( rTotal( t1 - tref, 'day' ) )
  330. if ( dh > 0 ) call goWriteKeyNum( mf_fckey, 'f', dh )
  331. end if
  332. ! create file name:
  333. ! dir / ec_od-ml60-T159 - oro.hdf
  334. ! dir / ec_od-ml60-T159 - T_20000101_fg006up4tr3.hdf
  335. select case ( mf%tres )
  336. case ( 'constant' )
  337. ! filename without date:
  338. write (mf%fname,'(6a)') trim(dir), mf_psep, trim(mf_mdir), mf_nsep, trim(mf_filekey), trim(output_ext)
  339. case ( 'month' )
  340. ! filename without day and forecast key:
  341. write (mf%fname,'(5a,"_",i4.4,i2.2,a)') &
  342. trim(dir), mf_psep, trim(mf_mdir), mf_nsep, trim(mf_filekey), ccyy, mm, trim(output_ext)
  343. case default
  344. ! filename including date:
  345. write (mf%fname,'(5a,"_",i4.4,2i2.2,3a)') &
  346. trim(dir), mf_psep, trim(mf_mdir), mf_nsep, &
  347. trim(mf_filekey), ccyy, mm, dd, trim(mf_fckey), trim(mf%tres), trim(output_ext)
  348. end select
  349. ! in case of output, not initialised yet ...
  350. mf%output_initialised = .false.
  351. ! number of expected time records in a file:
  352. call GetTime( mf_filekey, mf%tres, tref, t1, t2, status, nrec=mf%output_ntrec )
  353. IF_NOTOK_RETURN(status=1)
  354. ! ok
  355. status = 0
  356. end subroutine mf_Init
  357. ! ***
  358. subroutine mf_Done( mf, status )
  359. use MDF, only : MDF_Close
  360. ! --- in/out ------------------------------------
  361. type(TMeteoFile_tm5_nc), intent(inout) :: mf
  362. integer, intent(out) :: status
  363. ! --- const --------------------------------------
  364. character(len=*), parameter :: rname = mname//'/mf_Done'
  365. ! --- begin -------------------------------------
  366. ! file opend for output ?
  367. if ( mf%output_initialised ) then
  368. ! close file:
  369. call MDF_Close( mf%hid, status )
  370. if ( status /= 0 ) then
  371. write (gol,'("closing file : ",a)') trim(mf%fname); call goErr
  372. TRACEBACK; status=1; return
  373. endif
  374. end if
  375. ! clear:
  376. deallocate( mf%varid_param )
  377. deallocate( mf%varname_param )
  378. deallocate( mf%cfname_param )
  379. deallocate( mf%cfunit_param )
  380. deallocate( mf%itrec_param )
  381. ! ok
  382. status = 0
  383. end subroutine mf_Done
  384. ! ***
  385. subroutine mf_Get( mf, status, trange1, trange2, paramkeys, filename )
  386. use GO, only : TDate
  387. ! --- in/out ----------------------------
  388. type(TMeteoFile_tm5_nc), intent(in) :: mf
  389. integer, intent(out) :: status
  390. type(TDate), intent(out), optional :: trange1, trange2
  391. character(len=*), intent(out), optional :: paramkeys
  392. character(len=*), intent(out), optional :: filename
  393. ! --- const --------------------------------------
  394. character(len=*), parameter :: rname = mname//'/mf_Get'
  395. ! --- local --------------------------------
  396. ! --- begin --------------------------------
  397. ! time range:
  398. if ( present(trange1) ) trange1 = mf%trange(1)
  399. if ( present(trange2) ) trange2 = mf%trange(2)
  400. ! parameter names:
  401. if ( present(paramkeys) ) paramkeys = trim(mf%paramkeys)
  402. ! file name:
  403. if ( present(filename) ) filename = trim(mf%fname)
  404. ! ok
  405. status = 0
  406. end subroutine mf_Get
  407. ! ******************************************************************
  408. ! ***
  409. ! *** time range, parameters, file names
  410. ! ***
  411. ! ******************************************************************
  412. !
  413. ! Return time parameters:
  414. ! o tfile : date in filename
  415. ! o trange : time interval covered by fields in file
  416. ! o nrec : number of time records in completed file
  417. !
  418. subroutine GetTime( filekey, tres, tref, t1, t2, status, &
  419. tfile, trange, nrec )
  420. use GO, only : TDate, NewDate, AnyDate, Get, Set, wrtgol, IncrDate, IsAnyDate
  421. use GO, only : operator(<), operator(+), operator(-), rTotal
  422. ! --- in/out --------------------------------
  423. character(len=*), intent(in) :: filekey
  424. character(len=*), intent(in) :: tres
  425. type(TDate), intent(in) :: tref, t1, t2
  426. integer, intent(out) :: status
  427. type(TDate), intent(out), optional :: tfile
  428. type(TDate), intent(out), optional :: trange(2)
  429. integer, intent(out), optional :: nrec
  430. ! --- const --------------------------------------
  431. character(len=*), parameter :: rname = mname//'/GetTime'
  432. ! --- local --------------------------------
  433. integer :: year, month
  434. integer :: hour1, time6(6)
  435. integer :: dd, hh, step
  436. logical :: interval
  437. real :: dhr
  438. ! --- begin --------------------------------
  439. ! set day shift, start hour, and step
  440. select case ( tres )
  441. ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  442. ! tmpp [21,21]
  443. ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  444. case ( '_21p06', '_21p03', '_av21' )
  445. ! routine is called with tref,t1,t2:
  446. ! t1,t1,t2
  447. ! t1,any,any (oro and other constant fields)
  448. ! thus use tref to construct the file times
  449. if ( IsAnyDate(t1) ) then
  450. call Get( tref, hour=hour1 )
  451. interval = .false.
  452. else
  453. call Get( t1, hour=hour1 )
  454. interval = t1 < t2
  455. end if
  456. ! file ccyymmdd contains fields for (21,21];
  457. ! only uvsp is valid for [21,21] since it contains surface pressure for 21:00
  458. if ( present(tfile) ) then
  459. tfile = tref
  460. call Set( tfile, hour=0, min=0, sec=0 )
  461. if ( (hour1 > 21) .or. ((interval .or. filekey=='uvsp') .and. hour1==21) ) then
  462. tfile = tfile + IncrDate(day=1)
  463. end if
  464. end if
  465. ! fields by default valid for (21,21];
  466. ! only uvsp is valid for [21,21] since it contains surface pressure for 21:00
  467. if ( present(trange) ) then
  468. trange(1) = tref
  469. call Set( trange(1), hour=0, min=0, sec=0 ) ! 00:00 today
  470. if ( (hour1 > 21) .or. ((interval .or. filekey=='uvsp') .and. hour1==21) ) then
  471. trange(1) = trange(1) + IncrDate(day=1)
  472. end if
  473. trange(1) = trange(1) - IncrDate(hour=3) ! previous 21:00
  474. trange(2) = trange(1) + IncrDate(day=1) ! next 21:00
  475. ! boundary not included in most cases:
  476. if ( filekey /= 'uvsp' ) trange(1) = trange(1) + IncrDate(mili=1)
  477. end if
  478. ! number of records in file:
  479. if ( present(nrec) ) then
  480. select case ( tres )
  481. case ( '_21p06' ) ; nrec = 24/6
  482. case ( '_21p03' ) ; nrec = 24/3
  483. case ( '_av21' ) ; nrec = 24/24
  484. case default
  485. write (gol,'("unsupported tres for setting nrec : ",a)') tres; call goErr
  486. TRACEBACK; status=1; return
  487. end select
  488. end if
  489. ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  490. ! tm5 constant
  491. ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  492. case ( 'constant' )
  493. ! no date in filename ...
  494. if ( present(tfile) ) tfile = AnyDate()
  495. ! fields always valid ...
  496. if ( present(trange) ) then
  497. trange(1) = AnyDate()
  498. trange(2) = AnyDate()
  499. end if
  500. ! only one output record in constant file:
  501. if ( present(nrec) ) nrec = 1
  502. ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  503. ! tm5 monthly file
  504. ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  505. case ( 'month' )
  506. ! file ccyymmdd contains fields for this month:
  507. if ( present(tfile) ) then
  508. call Get( t1, year=year, month=month )
  509. tfile = NewDate( year=year, month=month, day=1 )
  510. end if
  511. ! field valid from begin to end of month:
  512. if ( present(trange) ) then
  513. call Get( t1, year=year, month=month )
  514. trange(1) = NewDate( year=year, month=month, day=1, hour=00 )
  515. month = month + 1
  516. if ( month > 12 ) then
  517. year = year + 1
  518. month = 1
  519. end if
  520. trange(2) = NewDate( year=year, month=month, day=1, hour=00 )
  521. end if
  522. ! only one output record in month file:
  523. if ( present(nrec) ) nrec = 1
  524. ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  525. ! tm5 [00,24]
  526. ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  527. case ( '_00p06', '_00p03', '_an0tr6', '_fg006up4tr3', '_fc012up2tr3', '_00p01', '_00p24' )
  528. ! file ccyymmdd contains fields for [00,24) :
  529. if ( present(tfile) ) then
  530. tfile = t1
  531. call Set( tfile, hour=0, min=0, sec=0 )
  532. end if
  533. ! fields valid for [00,24) :
  534. if ( present(trange) ) then
  535. trange(1) = t1
  536. call Set( trange(1), hour=0, min=0, sec=0 ) ! 00:00 today
  537. trange(2) = trange(1) + IncrDate(hour=24) - IncrDate(mili=1)
  538. end if
  539. ! number of records in file:
  540. if ( present(nrec) ) then
  541. select case ( tres )
  542. case ( '_00p06' ) ; nrec = 24/6
  543. case ( '_an0tr6' ) ; nrec = 24/6
  544. case ( '_00p03', '_fg006up4tr3', '_fc012up2tr3' )
  545. ! by default: 3 hourly files
  546. ! for forecasts after 12+96, only 6 hourly available:
  547. ! f0 [ 00, 24) : 00 03 06 09 12 15 18 21 : nrec=8
  548. ! f1 [ 24, 48) : 00 03 06 09 12 15 18 21 : nrec=8
  549. ! f2 [ 48, 72) : 00 03 06 09 12 15 18 21 : nrec=8
  550. ! f3 [ 72, 96) : 00 03 06 09 12 15 18 21 : nrec=8
  551. ! f4 [ 96,120) : 00 03 06 09 12 18 : nrec=6
  552. ! f5 [120,144) : 00 06 12 18 : nrec=4
  553. ! :
  554. ! f9 [192,216) : 00 06 12 18 : nrec=4
  555. ! f10 [216,240) : 00 06 12 : nrec=3
  556. dhr = rTotal( t1 - tref, 'hour' )
  557. if ( dhr < 96.0 ) then
  558. nrec = 8
  559. else if ( dhr < 120 ) then
  560. nrec = 6
  561. else if ( dhr < 216 ) then
  562. nrec = 4
  563. else
  564. nrec = 3
  565. end if
  566. case ( '_00p01' ) ; nrec = 24/1
  567. case ( '_00p24' ) ; nrec = 24/24
  568. case default
  569. write (gol,'("unsupported tres for setting nrec : ",a)') tres; call goErr
  570. TRACEBACK; status=1; return
  571. end select
  572. end if
  573. ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  574. ! ???
  575. ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  576. case default
  577. write (gol,'("unsupported time resolution key:")'); call goErr
  578. write (gol,'(" ",a)') trim(tres); call goErr
  579. TRACEBACK; status=1; return
  580. end select
  581. ! ok
  582. status = 0
  583. end subroutine GetTime
  584. ! ******************************************************************
  585. ! ***
  586. ! *** input
  587. ! ***
  588. ! ******************************************************************
  589. !
  590. ! initialiase grid info from sds
  591. !
  592. subroutine lli_Init_mf( lli, nuv, mf, status )
  593. use Grid, only : TllGridInfo, Init
  594. use MDF, only : MDF_Inq_DimID, MDF_Inquire_Dimension
  595. use MDF, only : MDF_Inq_VarID, MDF_Get_Var
  596. ! --- in/out ----------------------------------
  597. type(TllGridInfo), intent(inout) :: lli
  598. character(len=1), intent(in) :: nuv
  599. type(TMeteoFile_tm5_nc), intent(in) :: mf
  600. integer, intent(out) :: status
  601. ! --- const --------------------------------------
  602. character(len=*), parameter :: rname = mname//'/lli_Init_mf'
  603. ! --- local -----------------------------------
  604. integer :: dimid, varid
  605. real, allocatable :: values(:)
  606. real :: lon_deg, dlon_deg
  607. integer :: nlon
  608. real :: lat_deg, dlat_deg
  609. integer :: nlat
  610. ! --- begin ------------------------------------
  611. ! number of longitudes:
  612. call MDF_Inq_DimID( mf%hid, 'lon', dimid, status )
  613. IF_NOTOK_RETURN(status=1)
  614. call MDF_Inquire_Dimension( mf%hid, dimid, status, length=nlon )
  615. IF_NOTOK_RETURN(status=1)
  616. ! lon axis:
  617. allocate( values(nlon) )
  618. ! read:
  619. call MDF_Inq_VarID( mf%hid, 'lon', varid, status )
  620. IF_NOTOK_RETURN(status=1)
  621. call MDF_Get_Var( mf%hid, varid, values, status )
  622. IF_NOTOK_RETURN(status=1)
  623. ! extract:
  624. lon_deg = values(1)
  625. dlon_deg = values(2) - values(1)
  626. ! clear:
  627. deallocate( values )
  628. ! number of latgitudes:
  629. call MDF_Inq_DimID( mf%hid, 'lat', dimid, status )
  630. IF_NOTOK_RETURN(status=1)
  631. call MDF_Inquire_Dimension( mf%hid, dimid, status, length=nlat )
  632. IF_NOTOK_RETURN(status=1)
  633. ! lat axis:
  634. allocate( values(nlat) )
  635. ! read:
  636. call MDF_Inq_VarID( mf%hid, 'lat', varid, status )
  637. IF_NOTOK_RETURN(status=1)
  638. call MDF_Get_Var( mf%hid, varid, values, status )
  639. IF_NOTOK_RETURN(status=1)
  640. ! extract:
  641. lat_deg = values(1)
  642. dlat_deg = values(2) - values(1)
  643. ! clear:
  644. deallocate( values )
  645. ! define grid:
  646. call Init( lli, lon_deg, dlon_deg, nlon, &
  647. lat_deg, dlat_deg, nlat, status )
  648. IF_NOTOK_RETURN(status=1)
  649. ! ok
  650. status = 0
  651. end subroutine lli_Init_mf
  652. ! ***
  653. !
  654. ! initialiase level info from sds
  655. !
  656. subroutine levi_Init_mf( levi, mf, status )
  657. use Grid, only : TLevelInfo, Init
  658. use MDF, only : MDF_Inq_DimID, MDF_Inquire_Dimension
  659. use MDF, only : MDF_Inq_VarID, MDF_Get_Var
  660. use MDF, only : MDF_Get_Att, MDF_GLOBAL
  661. ! --- in/out ----------------------------------
  662. type(TLevelInfo), intent(out) :: levi
  663. type(TMeteoFile_tm5_nc), intent(in) :: mf
  664. integer, intent(out) :: status
  665. ! --- const --------------------------------------
  666. character(len=*), parameter :: rname = mname//'/levi_Init_mf'
  667. ! --- local -----------------------------------
  668. integer :: dimid, varid
  669. integer :: lev
  670. character(len=1) :: nw
  671. integer :: lm
  672. real, allocatable :: at(:), bt(:)
  673. real, allocatable :: ap_bounds(:,:), b_bounds(:,:)
  674. ! --- begin ------------------------------------
  675. ! 2D or 3D ?
  676. select case ( mf%rnk )
  677. case ( 2 )
  678. ! set dummy values ...
  679. call Init( levi, 1, (/0.0,0.0/), (/0.0,0.0/), status )
  680. IF_NOTOK_RETURN(status=1)
  681. case ( 3 )
  682. ! read number of levels from global attribute:
  683. call MDF_Inq_DimID( mf%hid, 'lev', dimid, status )
  684. IF_NOTOK_RETURN(status=1)
  685. call MDF_Inquire_Dimension( mf%hid, dimid, status, length=lev )
  686. IF_NOTOK_RETURN(status=1)
  687. ! layers or levels ?
  688. call MDF_Get_Att( mf%hid, MDF_GLOBAL, 'nw', nw, status )
  689. IF_NOTOK_RETURN(status=1)
  690. ! extract:
  691. select case ( nw )
  692. !~ layers
  693. case ( 'n' )!, '*' )
  694. ! layers is lev ...
  695. lm = lev
  696. ! storage:
  697. allocate( at(lm+1), bt(lm+1) )
  698. allocate( ap_bounds(2,lev), b_bounds(2,lev) )
  699. ! extract hybride coeff
  700. call MDF_Inq_VarID( mf%hid, 'ap_bounds', varid, status )
  701. IF_NOTOK_RETURN(status=1)
  702. call MDF_Get_Var( mf%hid, varid, ap_bounds, status )
  703. IF_NOTOK_RETURN(status=1)
  704. call MDF_Inq_VarID( mf%hid, 'b_bounds', varid, status )
  705. IF_NOTOK_RETURN(status=1)
  706. call MDF_Get_Var( mf%hid, varid, b_bounds, status )
  707. IF_NOTOK_RETURN(status=1)
  708. ! extract values:
  709. at = (/ ap_bounds(1,1), ap_bounds(2,:) /)
  710. bt = (/ b_bounds(1,1), b_bounds(2,:) /)
  711. ! clear:
  712. deallocate( ap_bounds, b_bounds )
  713. !~ half levels
  714. case ( 'w' )
  715. ! layers is one less than lev ...
  716. lm = lev-1
  717. ! storage:
  718. allocate( at(lm+1), bt(lm+1) )
  719. ! extract hybride coeff
  720. call MDF_Inq_VarID( mf%hid, 'ap', varid, status )
  721. IF_NOTOK_RETURN(status=1)
  722. call MDF_Get_Var( mf%hid, varid, at, status )
  723. IF_NOTOK_RETURN(status=1)
  724. call MDF_Inq_VarID( mf%hid, 'b', varid, status )
  725. IF_NOTOK_RETURN(status=1)
  726. call MDF_Get_Var( mf%hid, varid, bt, status )
  727. IF_NOTOK_RETURN(status=1)
  728. !~ unknown ...
  729. case default
  730. write (gol,'("found unsupported value of nw attribute : ",a)') trim(nw); call goErr
  731. write (gol,'(" file : ",a)') trim(mf%fname); call goErr
  732. TRACEBACK; status=1; return
  733. end select
  734. ! fill ...
  735. call Init( levi, lm, at, bt, status )
  736. IF_NOTOK_RETURN(status=1)
  737. ! clear:
  738. deallocate( at, bt )
  739. case default
  740. write (gol,'("unsupported rank : ",i1)') mf%rnk; call goErr
  741. TRACEBACK; status=1; return
  742. end select
  743. ! ok
  744. status = 0
  745. end subroutine levi_Init_mf
  746. ! ***
  747. subroutine GetTimeRecordNumber( mf, t1, t2, irec, status )
  748. use GO, only : TDate, Get
  749. use MDF, only : MDF_Inq_DimID, MDF_Inquire_Dimension
  750. use MDF, only : MDF_Inq_VarID, MDF_Inquire_Variable, MDF_Get_Var
  751. ! --- in/out -------------------------------
  752. type(TMeteoFile_tm5_nc), intent(inout) :: mf
  753. type(TDate), intent(in) :: t1, t2
  754. integer, intent(out) :: irec
  755. integer, intent(out) :: status
  756. ! --- const --------------------------------------
  757. character(len=*), parameter :: rname = mname//'/GetTimeRecordNumber'
  758. ! --- local -------------------------------
  759. integer :: timevalues1(6), timevalues2(6)
  760. integer :: dimid, varid
  761. integer :: ntime, itime
  762. integer, allocatable :: timevalues_bounds(:,:,:)
  763. ! --- begin ---------------------------------
  764. ! target times:
  765. call Get( t1, time6=timevalues1 )
  766. call Get( t2, time6=timevalues2 )
  767. ! number of time records:
  768. call MDF_Inq_DimID( mf%hid, 'time', dimid, status )
  769. IF_NOTOK_RETURN(status=1)
  770. call MDF_Inquire_Dimension( mf%hid, dimid, status, length=ntime )
  771. IF_NOTOK_RETURN(status=1)
  772. ! storage:
  773. allocate( timevalues_bounds(2,6,ntime) )
  774. ! read time boundaries:
  775. call MDF_Inq_VarID( mf%hid, 'timevalues_bounds', varid, status )
  776. IF_NOTOK_RETURN(status=1)
  777. call MDF_Get_Var( mf%hid, varid, timevalues_bounds, status )
  778. IF_NOTOK_RETURN(status=1)
  779. ! search ...
  780. irec = -1
  781. do itime = 1, ntime
  782. ! compare:
  783. if ( all(timevalues_bounds(1,:,itime) == timevalues1) .and. &
  784. all(timevalues_bounds(2,:,itime) == timevalues2) ) then
  785. irec = itime
  786. exit
  787. end if
  788. end do
  789. ! check ...
  790. if ( irec < 0 ) then
  791. write (gol,'("could not find time record for:")'); call goErr
  792. write (gol,'(" t1, t2 : ",i4,2("-",i2.2)," ",i2.2,2(":",i2.2)," , ",'// &
  793. & 'i4,2("-",i2.2)," ",i2.2,2(":",i2.2))') timevalues1, timevalues2; call goErr
  794. write (gol,'("in time bounds:")'); call goErr
  795. do itime = 1, ntime
  796. write (gol,'(" ",i6," : ",i4,2("-",i2.2)," ",i2.2,2(":",i2.2)," , ",'// &
  797. & 'i4,2("-",i2.2)," ",i2.2,2(":",i2.2))') &
  798. itime, timevalues_bounds(1,:,itime), timevalues_bounds(2,:,itime); call goErr
  799. end do
  800. write (gol,'("in file:")'); call goErr
  801. write (gol,'(" ",a)') trim(mf%fname); call goErr
  802. TRACEBACK; status=1; return
  803. end if
  804. ! clear:
  805. deallocate( timevalues_bounds )
  806. ! ok
  807. status = 0
  808. end subroutine GetTimeRecordNumber
  809. !--------------------------------------------------------------------------
  810. ! TM5 !
  811. !--------------------------------------------------------------------------
  812. !BOP
  813. !
  814. ! !IROUTINE: MF_READRECORD_PARALLEL_IO
  815. !
  816. ! !DESCRIPTION: Reads a met field in parallel. If the met field is 3D, also
  817. ! reads the surface pressure.
  818. !\\
  819. !\\
  820. ! !INTERFACE:
  821. !
  822. SUBROUTINE MF_READRECORD_PARALLEL_IO( mf, paramkey, unit, t1, t2, nuv, nw, &
  823. gridtype, levi, lli, ll, sp_ll, status )
  824. !
  825. ! !USES:
  826. !
  827. use PArray, only : pa_Done, pa_SetShape
  828. use GO, only : TDate
  829. use GO, only : GO_Timer_Start, GO_Timer_End
  830. use Grid, only : TllGridInfo, TLevelInfo, Done, operator(==)
  831. use MDF, only : MDF_Open, MDF_READ, MDF_Close
  832. use MDF, only : MDF_Inq_DimID, MDF_Inquire_Dimension, MDF_Var_Par_Access
  833. use MDF, only : MDF_Inq_VarID, MDF_Inquire_Variable, MDF_Get_Var
  834. use MDF, only : MDF_Get_Att, MDF_COLLECTIVE
  835. use partools, only : localComm, MPI_INFO_NULL
  836. use dims, only : nregions_all
  837. use TMM_CF, only : TMM_CF_Convert_Units
  838. use tm5_distgrid, only : dgrid, dist_grid, Get_DistGrid, myid, Init_DistGrid, Done_DistGrid
  839. !
  840. ! !INPUT/OUTPUT PARAMETERS:
  841. !
  842. type(TMeteoFile_tm5_nc), intent(inout) :: mf
  843. !
  844. ! !INPUT PARAMETERS:
  845. !
  846. character(len=*), intent(in) :: paramkey ! name of wanted variable
  847. character(len=*), intent(in) :: unit ! wanted unit
  848. type(TDate), intent(in) :: t1, t2 ! time interval where to look for a time record
  849. character(len=1), intent(in) :: nuv ! horizontal staggering
  850. character(len=1), intent(in) :: nw ! vertical staggering
  851. !
  852. ! !OUTPUT PARAMETERS:
  853. !
  854. character(len=2), intent(out) :: gridtype ! grid type of the met field
  855. type(TLevelInfo), intent(out) :: levi ! level info for METEO grid
  856. type(TllGridInfo), intent(inout) :: lli ! horizontal grid info of METEO grid
  857. real, pointer :: ll(:,:,:) ! read met field
  858. real, pointer :: sp_ll(:,:) ! read surface pressure
  859. integer, intent(out) :: status ! error code
  860. !
  861. ! !REVISION HISTORY:
  862. ! 17 Oct 2013 - Ph. Le Sager - v0
  863. !
  864. ! !REMARKS:
  865. ! - (1) Cannot use the following because it creates a circular dependency:
  866. ! use meteodata, only : global_lli
  867. !
  868. !EOP
  869. !------------------------------------------------------------------------
  870. !BOC
  871. character(len=*), parameter :: rname = mname//'/mf_ReadRecord_parallel_io'
  872. integer :: varid, klm
  873. integer :: irec
  874. integer :: shp(7), ndims, access_mode, sz(3)
  875. character(len=64) :: cfunits
  876. real :: ufac
  877. integer :: i1, i2, j1, j2 ! bounds of the tile w/r/t the METEO grid!
  878. type(TllGridInfo) :: world_lli
  879. type(dist_grid) :: DistGrid
  880. ! --- begin ---------------------------------
  881. ! start timing:
  882. call GO_Timer_Start( itim_readrecord, status )
  883. IF_NOTOK_RETURN(status=1)
  884. ! input ?
  885. if ( mf%io /= 'i' ) then
  886. write (gol,'("file should have been opened for input, but io=",a)') mf%io; call goErr
  887. TRACEBACK; status=1; return
  888. end if
  889. ! access mode & open
  890. access_mode = MDF_COLLECTIVE
  891. call MDF_Open( trim(mf%fname), MDF_NETCDF4, MDF_READ, mf%hid, status, mpi_comm=localComm, mpi_info=MPI_INFO_NULL)
  892. IF_NOTOK_RETURN(status=1)
  893. ! *** VARIABLE ID
  894. call MDF_Inq_VarID( mf%hid, trim(paramkey), varid, status )
  895. IF_NOTOK_RETURN(status=1)
  896. call MDF_Var_Par_Access( mf%hid, varid, access_mode, status )
  897. IF_NOTOK_RETURN(status=1)
  898. ! *** GRID DEFINITION
  899. gridtype = 'll'
  900. ! Global grid info: Find from file's sds and init
  901. call lli_Init_mf( lli, nuv, mf, status )
  902. IF_NOTOK_RETURN(status=1)
  903. ! setup level definition
  904. call levi_Init_mf( levi, mf, status )
  905. IF_NOTOK_RETURN(status=1)
  906. ! get global dimensions (here we are interested by the third dimension only)
  907. call MDF_Inquire_Variable( mf%hid, varid, status, ndims=ndims )
  908. IF_NOTOK_RETURN(status=1)
  909. call MDF_Inquire_Variable( mf%hid, varid, status, shp=shp(1:ndims) )
  910. IF_NOTOK_RETURN(status=1)
  911. ! Get distributed grid information.
  912. ! Assuming that the meteo grid is also one of the 1..nregions_all, find which one:
  913. do klm=1, nregions_all
  914. call Get_DistGrid( dgrid(klm), global_lli=world_lli )
  915. if (lli == world_lli) exit
  916. enddo
  917. call done(world_lli, status) ! garbage clean
  918. IF_NOTOK_RETURN(status=1)
  919. ! Get local bounds and local lli, from either an existing dgrid, or from a
  920. ! newly created one if no match
  921. if ( klm == (nregions_all+1) ) then ! no match
  922. call Init_DistGrid( DistGrid, lli, myid, 0, status)
  923. IF_NOTOK_RETURN(status=1)
  924. call Get_DistGrid( DistGrid, I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2, lli=lli )
  925. call Done_DistGrid(DistGrid, status)
  926. IF_NOTOK_RETURN(status=1)
  927. else
  928. call Get_DistGrid( dgrid(klm), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2, lli=lli )
  929. end if
  930. ! *** WORK ARRAY
  931. ! shape to read - Note overlap between tiles
  932. select case ( nuv )
  933. case ( 'n' )
  934. sz=(/i2-i1+1,j2-j1+1,shp(3)/)
  935. case ( 'u' )
  936. sz=(/i2-i1+2,j2-j1+1,shp(3)/)
  937. case ( 'v' )
  938. sz=(/i2-i1+1,j2-j1+2,shp(3)/)
  939. end select
  940. ! *** EXTRACT DATA
  941. if ( trim(mf%tres) == 'constant' ) then ! constant field
  942. select case ( ndims )
  943. case ( 2 )
  944. allocate( ll(sz(1),sz(2),1) )
  945. call MDF_Get_Var( mf%hid, varid, ll(:,:,1), status, start=(/i1,j1/), count=sz(1:2) )
  946. IF_NOTOK_RETURN(status=1)
  947. case ( 3 )
  948. call pa_SetShape( ll, sz )
  949. call MDF_Get_Var( mf%hid, varid, ll, status, start=(/i1,j1,1/), count=sz )
  950. IF_NOTOK_RETURN(status=1)
  951. case default
  952. write (gol,'("unsupported data rank:",i6)') ndims; call goErr
  953. TRACEBACK; status=1; return
  954. end select
  955. else
  956. ! which time record ?
  957. call GetTimeRecordNumber( mf, t1, t2, irec, status )
  958. IF_NOTOK_RETURN(status=1)
  959. select case ( ndims )
  960. case ( 2+1 )
  961. allocate( ll(sz(1),sz(2),1) )
  962. call MDF_Get_Var( mf%hid, varid, ll(:,:,1), status, start=(/i1,j1,irec/), count=(/sz(1),sz(2),1/) )
  963. IF_NOTOK_RETURN(status=1)
  964. case ( 3+1 )
  965. call pa_SetShape( ll, sz )
  966. call MDF_Get_Var( mf%hid, varid, ll, status, start=(/i1,j1,1,irec/), count=(/sz(1),sz(2),sz(3),1/) )
  967. IF_NOTOK_RETURN(status=1)
  968. case default
  969. write (gol,'("unsupported data rank:",i6)') ndims; call goErr
  970. TRACEBACK; status=1; return
  971. end select
  972. end if
  973. ! *** UNIT CONVERSION
  974. ! get unit from field in file:
  975. call MDF_Get_Att( mf%hid, varid, 'units', cfunits, status )
  976. IF_NOTOK_RETURN(status=1)
  977. ! conversion factor:
  978. call TMM_CF_Convert_Units( trim(cfunits), trim(unit), ufac, status )
  979. IF_NOTOK_RETURN(status=1)
  980. ! apply ?
  981. if ( ufac /= 1.0 ) then
  982. ! convert:
  983. ll = ll * ufac
  984. !! info ...
  985. !write (gol,'(" convert `",a,"` from `",a,"` to `",a,"` with factor ",f8.2," ; new range ",2f8.2)') &
  986. ! trim(paramkey), trim(cfunits), trim(unit), ufac, minval(ll), maxval(ll); call goPr
  987. end if
  988. ! *** SURFACE PRESSURE
  989. if ( mf%rnk == 3 ) then ! required?
  990. ! search variable:
  991. select case ( nuv )
  992. case ( 'n' )
  993. call MDF_Inq_VarID( mf%hid, 'ps', varid, status )
  994. IF_NOTOK_RETURN(status=1)
  995. case ( 'u' )
  996. call MDF_Inq_VarID( mf%hid, 'ps_u', varid, status )
  997. IF_NOTOK_RETURN(status=1)
  998. case ( 'v' )
  999. call MDF_Inq_VarID( mf%hid, 'ps_v', varid, status )
  1000. IF_NOTOK_RETURN(status=1)
  1001. case default
  1002. write (gol,'("unsupported nuv :",a)') nuv; call goErr
  1003. TRACEBACK; status=1; return
  1004. end select
  1005. call MDF_Var_Par_Access( mf%hid, varid, access_mode, status )
  1006. IF_NOTOK_RETURN(status=1)
  1007. call pa_SetShape( sp_ll, sz(1:2) )
  1008. call MDF_Get_Var( mf%hid, varid, sp_ll, status, start=(/i1,j1,irec/), count=(/sz(1),sz(2),1/) )
  1009. IF_NOTOK_RETURN(status=1)
  1010. else
  1011. ! for safety ...
  1012. call pa_Done( sp_ll )
  1013. end if
  1014. ! *** DONE
  1015. call MDF_Close( mf%hid, status )
  1016. IF_NOTOK_RETURN(status=1)
  1017. call GO_Timer_End( itim_readrecord, status )
  1018. IF_NOTOK_RETURN(status=1)
  1019. status = 0
  1020. END SUBROUTINE MF_READRECORD_PARALLEL_IO
  1021. !EOC
  1022. subroutine mf_ReadRecord_serial_io( mf, paramkey, unit, t1, t2, nuv, nw, &
  1023. gridtype, levi, &
  1024. lli, ll, sp_ll, &
  1025. status )
  1026. use PArray, only : pa_Done, pa_SetShape
  1027. use GO, only : TDate
  1028. use GO, only : GO_Timer_Start, GO_Timer_End
  1029. use Grid, only : TllGridInfo, TLevelInfo
  1030. use MDF, only : MDF_Open, MDF_Close
  1031. use MDF, only : MDF_READ
  1032. use MDF, only : MDF_Inq_DimID, MDF_Inquire_Dimension
  1033. use MDF, only : MDF_Inq_VarID, MDF_Inquire_Variable, MDF_Get_Var
  1034. use MDF, only : MDF_Get_Att
  1035. use TMM_CF, only : TMM_CF_Convert_Units
  1036. ! --- in/out -------------------------------
  1037. type(TMeteoFile_tm5_nc), intent(inout) :: mf
  1038. character(len=*), intent(in) :: paramkey
  1039. character(len=*), intent(in) :: unit
  1040. type(TDate), intent(in) :: t1, t2
  1041. character(len=1), intent(in) :: nuv
  1042. character(len=2), intent(out) :: gridtype
  1043. type(TLevelInfo), intent(out) :: levi
  1044. character(len=1), intent(in) :: nw
  1045. type(TllGridInfo), intent(inout) :: lli
  1046. real, pointer :: ll(:,:,:)
  1047. real, pointer :: sp_ll(:,:)
  1048. integer, intent(out) :: status
  1049. ! --- const --------------------------------------
  1050. character(len=*), parameter :: rname = mname//'/mf_ReadRecord'
  1051. ! --- local -------------------------------
  1052. integer :: varid
  1053. integer :: irec
  1054. integer :: shp(7), ndims
  1055. character(len=64) :: cfunits
  1056. real :: ufac
  1057. ! --- begin ---------------------------------
  1058. ! start timing:
  1059. call GO_Timer_Start( itim_readrecord, status )
  1060. IF_NOTOK_RETURN(status=1)
  1061. ! input ?
  1062. if ( mf%io /= 'i' ) then
  1063. write (gol,'("file should have been opened for input, but io=",a)') mf%io; call goErr
  1064. TRACEBACK; status=1; return
  1065. end if
  1066. ! open for reading:
  1067. call MDF_Open( trim(mf%fname), output_type, MDF_READ, mf%hid, status )
  1068. IF_NOTOK_RETURN(status=1)
  1069. ! *** variable id
  1070. ! search variable:
  1071. call MDF_Inq_VarID( mf%hid, trim(paramkey), varid, status )
  1072. IF_NOTOK_RETURN(status=1)
  1073. ! *** grid definition
  1074. ! always regular lat/lon grid ..
  1075. gridtype = 'll'
  1076. ! setup grid definition:
  1077. call lli_Init_mf( lli, nuv, mf, status )
  1078. IF_NOTOK_RETURN(status=1)
  1079. ! setup level definition:
  1080. call levi_Init_mf( levi, mf, status )
  1081. IF_NOTOK_RETURN(status=1)
  1082. ! get dimensions:
  1083. call MDF_Inquire_Variable( mf%hid, varid, status, ndims=ndims )
  1084. IF_NOTOK_RETURN(status=1)
  1085. call MDF_Inquire_Variable( mf%hid, varid, status, shp=shp(1:ndims) )
  1086. IF_NOTOK_RETURN(status=1)
  1087. ! *** data
  1088. ! constant field ?
  1089. if ( trim(mf%tres) == 'constant' ) then
  1090. ! extract data array:
  1091. select case ( ndims )
  1092. !* 2D fields
  1093. case ( 2 )
  1094. ! storage:
  1095. shp(3) = 1
  1096. call pa_SetShape( ll, shp(1:3) )
  1097. ! complete record:
  1098. call MDF_Get_Var( mf%hid, varid, ll(:,:,1), status )
  1099. IF_NOTOK_RETURN(status=1)
  1100. !* 3d fields
  1101. case ( 3 )
  1102. ! storage:
  1103. call pa_SetShape( ll, shp(1:3) )
  1104. ! complete record:
  1105. call MDF_Get_Var( mf%hid, varid, ll, status )
  1106. IF_NOTOK_RETURN(status=1)
  1107. !* unknown
  1108. case default
  1109. write (gol,'("unsupported data rank:",i6)') ndims; call goErr
  1110. TRACEBACK; status=1; return
  1111. end select
  1112. else
  1113. ! which time record ?
  1114. call GetTimeRecordNumber( mf, t1, t2, irec, status )
  1115. IF_NOTOK_RETURN(status=1)
  1116. ! extract data array:
  1117. select case ( ndims )
  1118. !* 2D temporal fields
  1119. case ( 2+1 )
  1120. ! storage:
  1121. shp(3) = 1
  1122. call pa_SetShape( ll, shp(1:3) )
  1123. ! complete record:
  1124. call MDF_Get_Var( mf%hid, varid, ll(:,:,1), status, &
  1125. start=(/1,1,irec/), count=(/shp(1),shp(2),1/) )
  1126. IF_NOTOK_RETURN(status=1)
  1127. !* 3d temporal fields
  1128. case ( 3+1 )
  1129. ! storage:
  1130. call pa_SetShape( ll, shp(1:3) )
  1131. ! complete record:
  1132. call MDF_Get_Var( mf%hid, varid, ll, status, &
  1133. start=(/1,1,1,irec/), count=(/shp(1),shp(2),shp(3),1/) )
  1134. IF_NOTOK_RETURN(status=1)
  1135. !* unknown
  1136. case default
  1137. write (gol,'("unsupported data rank:",i6)') ndims; call goErr
  1138. TRACEBACK; status=1; return
  1139. end select
  1140. end if
  1141. ! *** unit conversion
  1142. ! get unit from field in file:
  1143. call MDF_Get_Att( mf%hid, varid, 'units', cfunits, status )
  1144. IF_NOTOK_RETURN(status=1)
  1145. ! conversion factor:
  1146. call TMM_CF_Convert_Units( trim(cfunits), trim(unit), ufac, status )
  1147. IF_NOTOK_RETURN(status=1)
  1148. ! apply ?
  1149. if ( ufac /= 1.0 ) then
  1150. ! convert:
  1151. ll = ll * ufac
  1152. !! info ...
  1153. !write (gol,'(" convert `",a,"` from `",a,"` to `",a,"` with factor ",f8.2," ; new range ",2f8.2)') &
  1154. ! trim(paramkey), trim(cfunits), trim(unit), ufac, minval(ll), maxval(ll); call goPr
  1155. end if
  1156. ! *** surface pressure
  1157. ! surface pressure required ?
  1158. if ( mf%rnk == 3 ) then
  1159. ! search variable:
  1160. select case ( nuv )
  1161. case ( 'n' )
  1162. call MDF_Inq_VarID( mf%hid, 'ps', varid, status )
  1163. IF_NOTOK_RETURN(status=1)
  1164. case ( 'u' )
  1165. call MDF_Inq_VarID( mf%hid, 'ps_u', varid, status )
  1166. IF_NOTOK_RETURN(status=1)
  1167. case ( 'v' )
  1168. call MDF_Inq_VarID( mf%hid, 'ps_v', varid, status )
  1169. IF_NOTOK_RETURN(status=1)
  1170. case default
  1171. write (gol,'("unsupported nuv :",a)') nuv; call goErr
  1172. TRACEBACK; status=1; return
  1173. end select
  1174. ! storage:
  1175. call pa_SetShape( sp_ll, shp(1:2) )
  1176. ! complete record:
  1177. call MDF_Get_Var( mf%hid, varid, sp_ll, status, &
  1178. start=(/1,1,irec/), count=(/shp(1),shp(2),1/) )
  1179. IF_NOTOK_RETURN(status=1)
  1180. else
  1181. ! for safety ...
  1182. call pa_Done( sp_ll )
  1183. end if
  1184. ! ***
  1185. ! close
  1186. call MDF_Close( mf%hid, status )
  1187. IF_NOTOK_RETURN(status=1)
  1188. ! end timing:
  1189. call GO_Timer_End( itim_readrecord, status )
  1190. IF_NOTOK_RETURN(status=1)
  1191. ! ok
  1192. status = 0
  1193. end subroutine mf_ReadRecord_serial_io
  1194. ! ******************************************************************
  1195. ! ***
  1196. ! *** output
  1197. ! ***
  1198. ! ******************************************************************
  1199. subroutine CF_Put_Standard_Atts( hid, varid, cf_standard_name, cf_units, status )
  1200. use MDF, only : MDF_Put_Att
  1201. ! --- in/out ---------------------------------
  1202. integer, intent(in) :: hid
  1203. integer, intent(in) :: varid
  1204. character(len=*), intent(in) :: cf_standard_name
  1205. character(len=*), intent(in) :: cf_units
  1206. integer, intent(out) :: status
  1207. ! --- const ----------------------------------
  1208. character(len=*), parameter :: rname = mname//'/CF_Put_Standard_Atts'
  1209. ! --- local ----------------------------------
  1210. ! --- begin ----------------------------------
  1211. ! add standard name attribute:
  1212. call MDF_Put_Att( hid, varid, 'standard_name', trim(cf_standard_name), status )
  1213. IF_NOTOK_RETURN(status=1)
  1214. ! add units attribute:
  1215. call MDF_Put_Att( hid, varid, 'units', trim(cf_units), status )
  1216. IF_NOTOK_RETURN(status=1)
  1217. ! ok
  1218. status = 0
  1219. end subroutine CF_Put_Standard_Atts
  1220. ! ***
  1221. subroutine Define_File( mf, lli, nuv, status, levi, nw )!, nlev )
  1222. use GO , only : goReadFromLine
  1223. use Binas , only : grav, ae
  1224. use Grid , only : TllGridInfo, TLevelInfo, AreaOper
  1225. use MDF , only : MDF_Put_Att, MDF_GLOBAL
  1226. use MDF , only : MDF_Def_Var, MDF_Put_Var, MDF_FLOAT, MDF_DOUBLE, MDF_INT
  1227. use MDF , only : MDF_Def_Dim, MDF_UNLIMITED
  1228. use MDF , only : MDF_EndDef
  1229. use TMM_CF, only : TMM_CF_Standard_Units, TMM_CF_Convert_Name
  1230. ! --- in/out -------------------------------
  1231. type(TMeteoFile_tm5_nc), intent(inout) :: mf
  1232. type(TllGridInfo), intent(in) :: lli
  1233. character(len=1), intent(in) :: nuv
  1234. integer, intent(out) :: status
  1235. type(TLevelInfo), intent(in), optional :: levi
  1236. character(len=1), intent(in), optional :: nw
  1237. !integer, intent(in), optional :: nlev
  1238. ! --- const --------------------------------------
  1239. character(len=*), parameter :: rname = mname//'/Define_File'
  1240. ! --- local ----------------------------------
  1241. character(len=512) :: units
  1242. character(len=512) :: cell_measure
  1243. character(len=512) :: cell_methods
  1244. character(len=512) :: coordinates
  1245. real, allocatable :: pat(:,:)
  1246. integer :: l, n
  1247. character(len=1024) :: line
  1248. character(len=32) :: paramkey
  1249. integer :: iparam
  1250. character(len=1024) :: cf_standard_name
  1251. character(len=512) :: cf_units
  1252. integer :: varid
  1253. ! --- begin ----------------------------------
  1254. !
  1255. ! CF standard global attribues
  1256. !
  1257. ! convention id:
  1258. call MDF_Put_Att( mf%hid, MDF_GLOBAL, 'Conventions', 'CF-1.4', status )
  1259. IF_NOTOK_RETURN(status=1)
  1260. ! descriptive title:
  1261. call MDF_Put_Att( mf%hid, MDF_GLOBAL, 'title', 'TM meteo file', status )
  1262. IF_NOTOK_RETURN(status=1)
  1263. ! who?
  1264. call MDF_Put_Att( mf%hid, MDF_GLOBAL, 'institution', 'TM community', status )
  1265. IF_NOTOK_RETURN(status=1)
  1266. ! from ?
  1267. call MDF_Put_Att( mf%hid, MDF_GLOBAL, 'source', 'TM produced meteo file', status )
  1268. IF_NOTOK_RETURN(status=1)
  1269. ! how ?
  1270. call MDF_Put_Att( mf%hid, MDF_GLOBAL, 'history', 'None', status )
  1271. IF_NOTOK_RETURN(status=1)
  1272. ! published material:
  1273. call MDF_Put_Att( mf%hid, MDF_GLOBAL, 'references', 'None', status )
  1274. IF_NOTOK_RETURN(status=1)
  1275. ! other:
  1276. call MDF_Put_Att( mf%hid, MDF_GLOBAL, 'comment', 'None', status )
  1277. IF_NOTOK_RETURN(status=1)
  1278. !
  1279. ! TMM specific global attributes
  1280. !
  1281. ! file format
  1282. call MDF_Put_Att( mf%hid, MDF_GLOBAL, 'tmm_format', trim(output_format), status )
  1283. IF_NOTOK_RETURN(status=1)
  1284. ! grid type
  1285. call MDF_Put_Att( mf%hid, MDF_GLOBAL, 'tmm_gridtype', 'll', status )
  1286. IF_NOTOK_RETURN(status=1)
  1287. ! gravity constant:
  1288. call MDF_Put_Att( mf%hid, MDF_GLOBAL, 'grav', grav, status )
  1289. IF_NOTOK_RETURN(status=1)
  1290. ! earth radius:
  1291. call MDF_Put_Att( mf%hid, MDF_GLOBAL, 'ae', ae, status )
  1292. IF_NOTOK_RETURN(status=1)
  1293. ! save first and last lon/lat (center) for use with HIPHOP
  1294. call MDF_Put_Att( mf%hid, MDF_GLOBAL, 'lonmin', lli%lon_deg(1) , status )
  1295. IF_NOTOK_RETURN(status=1)
  1296. call MDF_Put_Att( mf%hid, MDF_GLOBAL, 'lonmax', lli%lon_deg(lli%nlon), status )
  1297. IF_NOTOK_RETURN(status=1)
  1298. call MDF_Put_Att( mf%hid, MDF_GLOBAL, 'latmin', lli%lat_deg(1) , status )
  1299. IF_NOTOK_RETURN(status=1)
  1300. call MDF_Put_Att( mf%hid, MDF_GLOBAL, 'latmax', lli%lat_deg(lli%nlat), status )
  1301. IF_NOTOK_RETURN(status=1)
  1302. !
  1303. ! axis
  1304. !
  1305. ! extra coordinate axes (with other names than the dimensions):
  1306. coordinates = ''
  1307. ! auxilary cell info:
  1308. cell_measure = ''
  1309. ! how data was formed:
  1310. cell_methods = ''
  1311. ! vertices:
  1312. call MDF_Def_Dim( mf%hid, 'nv', 2, mf%dimid_nv, status )
  1313. IF_NOTOK_RETURN(status=1)
  1314. ! * longitudes
  1315. ! longitude dimension:
  1316. call MDF_Def_Dim( mf%hid, 'lon', lli%nlon, mf%dimid_lon, status )
  1317. IF_NOTOK_RETURN(status=1)
  1318. ! variable:
  1319. call MDF_Def_Var( mf%hid, 'lon', MDF_DOUBLE, (/mf%dimid_lon/), mf%varid_lon, status )
  1320. IF_NOTOK_RETURN(status=1)
  1321. ! convert to CF name and unit:
  1322. cf_standard_name = 'longitude'
  1323. call TMM_CF_Standard_Units( trim(cf_standard_name), cf_units, status )
  1324. IF_NOTOK_RETURN(status=1)
  1325. ! add standard_name and units attributes:
  1326. call CF_Put_Standard_Atts( mf%hid, mf%varid_lon, trim(cf_standard_name), trim(cf_units), status )
  1327. IF_NOTOK_RETURN(status=1)
  1328. ! generic axis name:
  1329. call MDF_Put_Att( mf%hid, mf%varid_lon, 'axis', 'X', status )
  1330. IF_NOTOK_RETURN(status=1)
  1331. ! add attribute with name of variable with boundaries:
  1332. call MDF_Put_Att( mf%hid, mf%varid_lon, 'bounds', 'lon_bounds', status )
  1333. IF_NOTOK_RETURN(status=1)
  1334. ! add variable for boundaries:
  1335. call MDF_Def_Var( mf%hid, 'lon_bounds', MDF_DOUBLE, (/mf%dimid_nv,mf%dimid_lon/), mf%varid_lon_bounds, status )
  1336. IF_NOTOK_RETURN(status=1)
  1337. ! extra:
  1338. if ( nuv /= 'n' ) then
  1339. ! dimension:
  1340. call MDF_Def_Dim( mf%hid, 'lonb', lli%nlon+1, mf%dimid_lonb, status )
  1341. IF_NOTOK_RETURN(status=1)
  1342. ! variable:
  1343. call MDF_Def_Var( mf%hid, 'lonb', MDF_DOUBLE, (/mf%dimid_lonb/), mf%varid_lonb, status )
  1344. IF_NOTOK_RETURN(status=1)
  1345. ! add standard_name and units attributes:
  1346. call CF_Put_Standard_Atts( mf%hid, mf%varid_lonb, trim(cf_standard_name), trim(cf_units), status )
  1347. IF_NOTOK_RETURN(status=1)
  1348. end if
  1349. ! * latitudes
  1350. ! latitude dimension:
  1351. call MDF_Def_Dim( mf%hid, 'lat', lli%nlat, mf%dimid_lat, status )
  1352. IF_NOTOK_RETURN(status=1)
  1353. ! variable:
  1354. call MDF_Def_Var( mf%hid, 'lat', MDF_DOUBLE, (/mf%dimid_lat/), mf%varid_lat, status )
  1355. IF_NOTOK_RETURN(status=1)
  1356. ! convert to CF name and unit:
  1357. cf_standard_name = 'latitude'
  1358. call TMM_CF_Standard_Units( trim(cf_standard_name), cf_units, status )
  1359. IF_NOTOK_RETURN(status=1)
  1360. ! add standard_name and units attributes:
  1361. call CF_Put_Standard_Atts( mf%hid, mf%varid_lat, trim(cf_standard_name), trim(cf_units), status )
  1362. IF_NOTOK_RETURN(status=1)
  1363. ! generic axis name:
  1364. call MDF_Put_Att( mf%hid, mf%varid_lat, 'axis', 'Y', status )
  1365. IF_NOTOK_RETURN(status=1)
  1366. ! add attribute with name of variable with boundaries:
  1367. call MDF_Put_Att( mf%hid, mf%varid_lat, 'bounds', 'lat_bounds', status )
  1368. IF_NOTOK_RETURN(status=1)
  1369. ! add variable for boundaries:
  1370. call MDF_Def_Var( mf%hid, 'lat_bounds', MDF_DOUBLE, (/mf%dimid_nv,mf%dimid_lat/), mf%varid_lat_bounds, status )
  1371. IF_NOTOK_RETURN(status=1)
  1372. ! extra:
  1373. if ( nuv /= 'n' ) then
  1374. ! dimension:
  1375. call MDF_Def_Dim( mf%hid, 'latb', lli%nlat+1, mf%dimid_latb, status )
  1376. IF_NOTOK_RETURN(status=1)
  1377. ! variable:
  1378. call MDF_Def_Var( mf%hid, 'latb', MDF_DOUBLE, (/mf%dimid_latb/), mf%varid_latb, status )
  1379. IF_NOTOK_RETURN(status=1)
  1380. ! add standard_name and units attributes:
  1381. call CF_Put_Standard_Atts( mf%hid, mf%varid_latb, trim(cf_standard_name), trim(cf_units), status )
  1382. IF_NOTOK_RETURN(status=1)
  1383. end if
  1384. ! * area
  1385. ! cell variable ?
  1386. if ( nuv == 'n' ) then
  1387. ! also provide the area:
  1388. cell_measure = trim(cell_measure)//' area: cell_area'
  1389. ! cell area:
  1390. call MDF_Def_Var( mf%hid, 'cell_area', MDF_FLOAT, (/mf%dimid_lon,mf%dimid_lat/), mf%varid_cell_area, status )
  1391. IF_NOTOK_RETURN(status=1)
  1392. ! convert to CF name and unit:
  1393. cf_standard_name = 'cell_area'
  1394. call TMM_CF_Standard_Units( trim(cf_standard_name), cf_units, status )
  1395. IF_NOTOK_RETURN(status=1)
  1396. ! add standard_name and units attributes:
  1397. call CF_Put_Standard_Atts( mf%hid, mf%varid_cell_area, trim(cf_standard_name), trim(cf_units), status )
  1398. IF_NOTOK_RETURN(status=1)
  1399. ! add description:
  1400. call MDF_Put_Att( mf%hid, mf%varid_cell_area, 'long_name', 'area of grid cell', status )
  1401. IF_NOTOK_RETURN(status=1)
  1402. end if
  1403. ! * time
  1404. if ( trim(mf%tres) /= 'constant' ) then
  1405. ! time dimension:
  1406. call MDF_Def_Dim( mf%hid, 'time', MDF_UNLIMITED, mf%dimid_time, status )
  1407. IF_NOTOK_RETURN(status=1)
  1408. ! standard units is single value only ...
  1409. write (units,'("seconds since ",i4.4,2("-",i2.2)," ",i2.2,2(":",i2.2))') since_time6
  1410. ! variable:
  1411. call MDF_Def_Var( mf%hid, 'time', MDF_DOUBLE, (/mf%dimid_time/), mf%varid_time, status )
  1412. IF_NOTOK_RETURN(status=1)
  1413. ! add units attribute:
  1414. call MDF_Put_Att( mf%hid, mf%varid_time, 'standard_name', 'time', status )
  1415. IF_NOTOK_RETURN(status=1)
  1416. ! add units attribute:
  1417. call MDF_Put_Att( mf%hid, mf%varid_time, 'units', trim(units), status )
  1418. IF_NOTOK_RETURN(status=1)
  1419. ! name of variable with interval bounds:
  1420. call MDF_Put_Att( mf%hid, mf%varid_time, 'bounds', 'time_bounds', status )
  1421. IF_NOTOK_RETURN(status=1)
  1422. ! variable:
  1423. call MDF_Def_Var( mf%hid, 'time_bounds', MDF_DOUBLE, (/mf%dimid_nv,mf%dimid_time/), mf%varid_time_bounds, status )
  1424. IF_NOTOK_RETURN(status=1)
  1425. ! add units attribute:
  1426. call MDF_Put_Att( mf%hid, mf%varid_time, 'units', trim(units), status )
  1427. IF_NOTOK_RETURN(status=1)
  1428. ! time averages ?
  1429. if ( mf%is_aver ) then
  1430. ! value is the mean over a time interval:
  1431. cell_methods = trim(cell_methods)//' time: mean'
  1432. else
  1433. ! instant fields:
  1434. cell_methods = trim(cell_methods)//' time: point'
  1435. end if
  1436. ! variable:
  1437. call MDF_Def_Var( mf%hid, 'reftime', MDF_DOUBLE, (/mf%dimid_time/), mf%varid_reftime, status )
  1438. IF_NOTOK_RETURN(status=1)
  1439. ! add units attribute:
  1440. call MDF_Put_Att( mf%hid, mf%varid_reftime, 'units', trim(units), status )
  1441. IF_NOTOK_RETURN(status=1)
  1442. ! description:
  1443. call MDF_Put_Att( mf%hid, mf%varid_reftime, 'long_name', 'reference time', status )
  1444. IF_NOTOK_RETURN(status=1)
  1445. ! extra time coordinates:
  1446. coordinates = trim(coordinates)//' reftime'
  1447. end if
  1448. ! * time values
  1449. if ( trim(mf%tres) /= 'constant' ) then
  1450. ! time values dimension:
  1451. call MDF_Def_Dim( mf%hid, 'timeval', 6, mf%dimid_timeval, status )
  1452. IF_NOTOK_RETURN(status=1)
  1453. ! variable:
  1454. call MDF_Def_Var( mf%hid, 'timevalues', MDF_INT, (/mf%dimid_timeval,mf%dimid_time/), mf%varid_timevalues, status )
  1455. IF_NOTOK_RETURN(status=1)
  1456. ! description:
  1457. call MDF_Put_Att( mf%hid, mf%varid_timevalues, 'long_name', 'year month day hour minute second', status )
  1458. IF_NOTOK_RETURN(status=1)
  1459. ! add units attribute:
  1460. call MDF_Put_Att( mf%hid, mf%varid_timevalues, 'units', '1', status )
  1461. IF_NOTOK_RETURN(status=1)
  1462. ! name of variable with interval bounds:
  1463. call MDF_Put_Att( mf%hid, mf%varid_timevalues, 'bounds', 'timevalues_bounds', status )
  1464. IF_NOTOK_RETURN(status=1)
  1465. ! variable:
  1466. call MDF_Def_Var( mf%hid, 'timevalues_bounds', MDF_INT, &
  1467. (/mf%dimid_nv,mf%dimid_timeval,mf%dimid_time/), &
  1468. mf%varid_timevalues_bounds, status )
  1469. IF_NOTOK_RETURN(status=1)
  1470. ! description:
  1471. call MDF_Put_Att( mf%hid, mf%varid_timevalues_bounds, 'long_name', 'year month day hour minute second', status )
  1472. IF_NOTOK_RETURN(status=1)
  1473. ! add units attribute:
  1474. call MDF_Put_Att( mf%hid, mf%varid_timevalues_bounds, 'units', '1', status )
  1475. IF_NOTOK_RETURN(status=1)
  1476. ! variable:
  1477. call MDF_Def_Var( mf%hid, 'reftimevalues', MDF_INT, (/mf%dimid_timeval,mf%dimid_time/), mf%varid_reftimevalues, status )
  1478. IF_NOTOK_RETURN(status=1)
  1479. ! description:
  1480. call MDF_Put_Att( mf%hid, mf%varid_reftimevalues, 'long_name', 'reference time values', status )
  1481. IF_NOTOK_RETURN(status=1)
  1482. ! add units attribute:
  1483. call MDF_Put_Att( mf%hid, mf%varid_reftimevalues, 'units', '1', status )
  1484. IF_NOTOK_RETURN(status=1)
  1485. end if
  1486. ! * levels
  1487. ! levels ?
  1488. if ( present(levi) ) then
  1489. ! check ...
  1490. if ( .not. present(nw) ) then
  1491. write (gol,'("optional argument levi without nw ...")'); call goErr
  1492. TRACEBACK; status=1; return
  1493. end if
  1494. !! tm5 specials ...
  1495. !call MDF_Def_Dim( mf%hid, 'tm5_lm', levi%nlev, mf%dimid_tm5_lm, status )
  1496. !IF_NOTOK_RETURN(status=1)
  1497. !call MDF_Def_Dim( mf%hid, 'tm5_lmb', levi%nlev+1, mf%dimid_tm5_lmb, status )
  1498. !IF_NOTOK_RETURN(status=1)
  1499. !call MDF_Def_Var( mf%hid, 'tm5_at', MDF_DOUBLE, (/mf%dimid_tm5_lmb/), mf%varid_tm5_at, status )
  1500. !IF_NOTOK_RETURN(status=1)
  1501. !call MDF_Def_Var( mf%hid, 'tm5_bt', MDF_DOUBLE, (/mf%dimid_tm5_lmb/), mf%varid_tm5_bt, status )
  1502. !IF_NOTOK_RETURN(status=1)
  1503. ! save nw to facilitate reading:
  1504. call MDF_Put_Att( mf%hid, MDF_GLOBAL, 'nw', trim(nw), status )
  1505. IF_NOTOK_RETURN(status=1)
  1506. ! where defined ?
  1507. select case ( nw )
  1508. ! layer mid, or selection
  1509. case ( 'n' )!, '*' )
  1510. ! hybride layers:
  1511. !if ( present(nlev) ) then
  1512. ! ! lowest layers only:
  1513. ! call MDF_Def_Dim( mf%hid, 'lev', nlev, mf%dimid_lev, status )
  1514. ! IF_NOTOK_RETURN(status=1)
  1515. !else
  1516. ! full dimension:
  1517. call MDF_Def_Dim( mf%hid, 'lev', levi%nlev, mf%dimid_lev, status )
  1518. IF_NOTOK_RETURN(status=1)
  1519. !end if
  1520. ! variable:
  1521. call MDF_Def_Var( mf%hid, 'lev', MDF_DOUBLE, (/mf%dimid_lev/), mf%varid_lev, status )
  1522. IF_NOTOK_RETURN(status=1)
  1523. ! convert to CF name and unit:
  1524. cf_standard_name = 'atmosphere_hybrid_sigma_pressure_coordinate'
  1525. call TMM_CF_Standard_Units( trim(cf_standard_name), cf_units, status )
  1526. IF_NOTOK_RETURN(status=1)
  1527. ! add standard_name and units attributes:
  1528. call CF_Put_Standard_Atts( mf%hid, mf%varid_lev, trim(cf_standard_name), trim(cf_units), status )
  1529. IF_NOTOK_RETURN(status=1)
  1530. ! description:
  1531. call MDF_Put_Att( mf%hid, mf%varid_lev, 'long_name', 'pressure at layer midpoints', status )
  1532. IF_NOTOK_RETURN(status=1)
  1533. ! direction of increasing pressure:
  1534. call MDF_Put_Att( mf%hid, mf%varid_lev, 'positive', 'down', status )
  1535. IF_NOTOK_RETURN(status=1)
  1536. ! how to compute pressure:
  1537. call MDF_Put_Att( mf%hid, mf%varid_lev, 'forumula', 'p(n,k,j,i) = ap(k) + b(k)*ps(n,j,i)', status )
  1538. IF_NOTOK_RETURN(status=1)
  1539. call MDF_Put_Att( mf%hid, mf%varid_lev, 'forumula_terms', 'ap: ap b: b ps: ps', status )
  1540. IF_NOTOK_RETURN(status=1)
  1541. ! generic axis name:
  1542. call MDF_Put_Att( mf%hid, mf%varid_lev, 'axis', 'Z', status )
  1543. IF_NOTOK_RETURN(status=1)
  1544. ! extra
  1545. if ( nuv /= 'n' ) then
  1546. ! hybride layers:
  1547. call MDF_Def_Dim( mf%hid, 'lev_u', levi%nlev, mf%dimid_lev_u, status )
  1548. IF_NOTOK_RETURN(status=1)
  1549. ! variable:
  1550. call MDF_Def_Var( mf%hid, 'lev_u', MDF_DOUBLE, (/mf%dimid_lev_u/), mf%varid_lev_u, status )
  1551. IF_NOTOK_RETURN(status=1)
  1552. ! convert to CF name and unit:
  1553. cf_standard_name = 'atmosphere_hybrid_sigma_pressure_coordinate'
  1554. call TMM_CF_Standard_Units( trim(cf_standard_name), cf_units, status )
  1555. IF_NOTOK_RETURN(status=1)
  1556. ! add standard_name and units attributes:
  1557. call CF_Put_Standard_Atts( mf%hid, mf%varid_lev_u, trim(cf_standard_name), trim(cf_units), status )
  1558. IF_NOTOK_RETURN(status=1)
  1559. ! description:
  1560. call MDF_Put_Att( mf%hid, mf%varid_lev_u, 'long_name', 'pressure at layer midpoints', status )
  1561. IF_NOTOK_RETURN(status=1)
  1562. ! direction of increasing pressure:
  1563. call MDF_Put_Att( mf%hid, mf%varid_lev_u, 'positive', 'down', status )
  1564. IF_NOTOK_RETURN(status=1)
  1565. ! how to compute pressure:
  1566. call MDF_Put_Att( mf%hid, mf%varid_lev_u, 'forumula', 'p(n,k,j,i) = ap(k) + b(k)*ps(n,j,i)', status )
  1567. IF_NOTOK_RETURN(status=1)
  1568. call MDF_Put_Att( mf%hid, mf%varid_lev_u, 'forumula_terms', 'ap: ap b: b ps: ps_u', status )
  1569. IF_NOTOK_RETURN(status=1)
  1570. ! hybride layers:
  1571. call MDF_Def_Dim( mf%hid, 'lev_v', levi%nlev, mf%dimid_lev_v, status )
  1572. IF_NOTOK_RETURN(status=1)
  1573. ! variable:
  1574. call MDF_Def_Var( mf%hid, 'lev_v', MDF_DOUBLE, (/mf%dimid_lev_v/), mf%varid_lev_v, status )
  1575. IF_NOTOK_RETURN(status=1)
  1576. ! convert to CF name and unit:
  1577. cf_standard_name = 'atmosphere_hybrid_sigma_pressure_coordinate'
  1578. call TMM_CF_Standard_Units( trim(cf_standard_name), cf_units, status )
  1579. IF_NOTOK_RETURN(status=1)
  1580. ! add standard_name and units attributes:
  1581. call CF_Put_Standard_Atts( mf%hid, mf%varid_lev_v, trim(cf_standard_name), trim(cf_units), status )
  1582. IF_NOTOK_RETURN(status=1)
  1583. ! description:
  1584. call MDF_Put_Att( mf%hid, mf%varid_lev_v, 'long_name', 'pressure at layer midpoints', status )
  1585. IF_NOTOK_RETURN(status=1)
  1586. ! direction of increasing pressure:
  1587. call MDF_Put_Att( mf%hid, mf%varid_lev_v, 'positive', 'down', status )
  1588. IF_NOTOK_RETURN(status=1)
  1589. ! how to compute pressure:
  1590. call MDF_Put_Att( mf%hid, mf%varid_lev_v, 'forumula', 'p(n,k,j,i) = ap(k) + b(k)*ps(n,j,i)', status )
  1591. IF_NOTOK_RETURN(status=1)
  1592. call MDF_Put_Att( mf%hid, mf%varid_lev_v, 'forumula_terms', 'ap: ap b: b ps: ps_v', status )
  1593. IF_NOTOK_RETURN(status=1)
  1594. end if
  1595. ! variable:
  1596. call MDF_Def_Var( mf%hid, 'ap', MDF_DOUBLE, (/mf%dimid_lev/), mf%varid_ap, status )
  1597. IF_NOTOK_RETURN(status=1)
  1598. ! description:
  1599. call MDF_Put_Att( mf%hid, mf%varid_ap, 'long_name', 'atmosphere hybrid sigma pressure coefficient ap&
  1600. & at layer midpoints', status )
  1601. IF_NOTOK_RETURN(status=1)
  1602. ! units:
  1603. call MDF_Put_Att( mf%hid, mf%varid_ap, 'units', 'Pa', status )
  1604. IF_NOTOK_RETURN(status=1)
  1605. ! name of variable with boundary values:
  1606. call MDF_Put_Att( mf%hid, mf%varid_ap, 'bounds', 'ap_bounds', status )
  1607. IF_NOTOK_RETURN(status=1)
  1608. ! variable:
  1609. call MDF_Def_Var( mf%hid, 'b', MDF_DOUBLE, (/mf%dimid_lev/), mf%varid_b, status )
  1610. IF_NOTOK_RETURN(status=1)
  1611. ! description:
  1612. call MDF_Put_Att( mf%hid, mf%varid_b, 'long_name', 'atmosphere hybrid sigma pressure coefficient b&
  1613. & at layer midpoints', status )
  1614. IF_NOTOK_RETURN(status=1)
  1615. ! units:
  1616. call MDF_Put_Att( mf%hid, mf%varid_b, 'units', '1', status )
  1617. IF_NOTOK_RETURN(status=1)
  1618. ! name of variable with boundary values:
  1619. call MDF_Put_Att( mf%hid, mf%varid_b, 'bounds', 'b_bounds', status )
  1620. IF_NOTOK_RETURN(status=1)
  1621. ! variable:
  1622. call MDF_Def_Var( mf%hid, 'ap_bounds', MDF_DOUBLE, (/mf%dimid_nv,mf%dimid_lev/), mf%varid_ap_bounds, status )
  1623. IF_NOTOK_RETURN(status=1)
  1624. ! description:
  1625. call MDF_Put_Att( mf%hid, mf%varid_ap_bounds, 'long_name', 'atmosphere hybrid sigma pressure coefficient&
  1626. & ap at layer interfaces', status )
  1627. IF_NOTOK_RETURN(status=1)
  1628. ! units:
  1629. call MDF_Put_Att( mf%hid, mf%varid_ap_bounds, 'units', 'Pa', status )
  1630. IF_NOTOK_RETURN(status=1)
  1631. ! variable:
  1632. call MDF_Def_Var( mf%hid, 'b_bounds', MDF_DOUBLE, (/mf%dimid_nv,mf%dimid_lev/), mf%varid_b_bounds, status )
  1633. IF_NOTOK_RETURN(status=1)
  1634. ! description:
  1635. call MDF_Put_Att( mf%hid, mf%varid_b_bounds, 'long_name', 'atmosphere hybrid sigma pressure coefficient&
  1636. & b at layer interfaces', status )
  1637. IF_NOTOK_RETURN(status=1)
  1638. ! units:
  1639. call MDF_Put_Att( mf%hid, mf%varid_b_bounds, 'units', '1', status )
  1640. IF_NOTOK_RETURN(status=1)
  1641. ! layer interfaces
  1642. case ( 'w' )
  1643. ! hybride layers:
  1644. call MDF_Def_Dim( mf%hid, 'lev', levi%nlev+1, mf%dimid_lev, status )
  1645. IF_NOTOK_RETURN(status=1)
  1646. ! variable:
  1647. call MDF_Def_Var( mf%hid, 'lev', MDF_DOUBLE, (/mf%dimid_lev/), mf%varid_lev, status )
  1648. IF_NOTOK_RETURN(status=1)
  1649. ! convert to CF name and unit:
  1650. cf_standard_name = 'atmosphere_hybrid_sigma_pressure_coordinate'
  1651. call TMM_CF_Standard_Units( trim(cf_standard_name), cf_units, status )
  1652. IF_NOTOK_RETURN(status=1)
  1653. ! add standard_name and units attributes:
  1654. call CF_Put_Standard_Atts( mf%hid, mf%varid_lev, trim(cf_standard_name), trim(cf_units), status )
  1655. IF_NOTOK_RETURN(status=1)
  1656. ! description:
  1657. call MDF_Put_Att( mf%hid, mf%varid_lev, 'long_name', 'pressure at layer interfaces', status )
  1658. IF_NOTOK_RETURN(status=1)
  1659. ! direction of increasing pressure:
  1660. call MDF_Put_Att( mf%hid, mf%varid_lev, 'positive', 'down', status )
  1661. IF_NOTOK_RETURN(status=1)
  1662. ! how to compute pressure:
  1663. call MDF_Put_Att( mf%hid, mf%varid_lev, 'forumula', 'p(n,k,j,i) = ap(k) + b(k)*ps(n,j,i)', status )
  1664. IF_NOTOK_RETURN(status=1)
  1665. call MDF_Put_Att( mf%hid, mf%varid_lev, 'forumula_terms', 'ap: ap b: b ps: ps', status )
  1666. IF_NOTOK_RETURN(status=1)
  1667. ! generic axis name:
  1668. call MDF_Put_Att( mf%hid, mf%varid_lev, 'axis', 'Z', status )
  1669. IF_NOTOK_RETURN(status=1)
  1670. ! variable:
  1671. call MDF_Def_Var( mf%hid, 'ap', MDF_DOUBLE, (/mf%dimid_lev/), mf%varid_ap, status )
  1672. IF_NOTOK_RETURN(status=1)
  1673. ! description:
  1674. call MDF_Put_Att( mf%hid, mf%varid_ap, 'long_name', 'atmosphere hybrid sigma pressure coefficient ap&
  1675. & at layer interfaces', status )
  1676. IF_NOTOK_RETURN(status=1)
  1677. ! units:
  1678. call MDF_Put_Att( mf%hid, mf%varid_ap, 'units', 'Pa', status )
  1679. IF_NOTOK_RETURN(status=1)
  1680. ! variable:
  1681. call MDF_Def_Var( mf%hid, 'b', MDF_DOUBLE, (/mf%dimid_lev/), mf%varid_b, status )
  1682. IF_NOTOK_RETURN(status=1)
  1683. ! description:
  1684. call MDF_Put_Att( mf%hid, mf%varid_b, 'long_name', 'atmosphere hybrid sigma pressure coefficient&
  1685. & b at layer interfaces', status )
  1686. IF_NOTOK_RETURN(status=1)
  1687. ! units:
  1688. call MDF_Put_Att( mf%hid, mf%varid_b, 'units', '1', status )
  1689. IF_NOTOK_RETURN(status=1)
  1690. ! other ...
  1691. case default
  1692. write (gol,'("unsupported nw : ",a)') trim(nw); call goErr
  1693. TRACEBACK; status=1; return
  1694. end select
  1695. ! surface pressure:
  1696. call MDF_Def_Var( mf%hid, 'ps', MDF_FLOAT, (/mf%dimid_lon ,mf%dimid_lat ,mf%dimid_time/), mf%varid_ps, status )
  1697. IF_NOTOK_RETURN(status=1)
  1698. ! convert to CF name and unit:
  1699. cf_standard_name = 'surface_air_pressure'
  1700. call TMM_CF_Standard_Units( trim(cf_standard_name), cf_units, status )
  1701. IF_NOTOK_RETURN(status=1)
  1702. ! add standard_name and units attributes:
  1703. call CF_Put_Standard_Atts( mf%hid, mf%varid_ps, trim(cf_standard_name), trim(cf_units), status )
  1704. IF_NOTOK_RETURN(status=1)
  1705. ! for post processing ...
  1706. l = len_trim(cell_measure)
  1707. if ( l > 0 ) then
  1708. call MDF_Put_Att( mf%hid, mf%varid_ps, 'cell_measure', cell_measure(2:l), status )
  1709. IF_NOTOK_RETURN(status=1)
  1710. end if
  1711. ! specify how computed:
  1712. l = len_trim(cell_methods)
  1713. if ( l > 0 ) then
  1714. call MDF_Put_Att( mf%hid, mf%varid_ps, 'cell_methods', cell_methods(2:l), status )
  1715. IF_NOTOK_RETURN(status=1)
  1716. end if
  1717. ! extra coordinates that apply to this variable:
  1718. l = len_trim(coordinates)
  1719. if ( l > 0 ) then
  1720. call MDF_Put_Att( mf%hid, mf%varid_ps, 'coordinates', coordinates(2:l), status )
  1721. IF_NOTOK_RETURN(status=1)
  1722. end if
  1723. ! extra:
  1724. if ( nuv /= 'n' ) then
  1725. ! surface pressure:
  1726. call MDF_Def_Var( mf%hid, 'ps_u', MDF_FLOAT, (/mf%dimid_lonb,mf%dimid_lat ,mf%dimid_time/), mf%varid_ps_u, status )
  1727. IF_NOTOK_RETURN(status=1)
  1728. ! convert to CF name and unit:
  1729. cf_standard_name = 'surface_air_pressure'
  1730. call TMM_CF_Standard_Units( trim(cf_standard_name), cf_units, status )
  1731. IF_NOTOK_RETURN(status=1)
  1732. ! add standard_name and units attributes:
  1733. call CF_Put_Standard_Atts( mf%hid, mf%varid_ps_u, trim(cf_standard_name), trim(cf_units), status )
  1734. IF_NOTOK_RETURN(status=1)
  1735. ! surface pressure:
  1736. call MDF_Def_Var( mf%hid, 'ps_v', MDF_FLOAT, (/mf%dimid_lon ,mf%dimid_latb,mf%dimid_time/), mf%varid_ps_v, status )
  1737. IF_NOTOK_RETURN(status=1)
  1738. ! convert to CF name and unit:
  1739. cf_standard_name = 'surface_air_pressure'
  1740. call TMM_CF_Standard_Units( trim(cf_standard_name), cf_units, status )
  1741. IF_NOTOK_RETURN(status=1)
  1742. ! add standard_name and units attributes:
  1743. call CF_Put_Standard_Atts( mf%hid, mf%varid_ps_v, trim(cf_standard_name), trim(cf_units), status )
  1744. IF_NOTOK_RETURN(status=1)
  1745. end if
  1746. end if ! levels
  1747. ! * meteo variables
  1748. ! copy the paramkeys ('-aa-bb-cc-') except for the first '-' :
  1749. l = len_trim(mf%paramkeys)
  1750. line = mf%paramkeys(2:l)
  1751. ! loop over all parameters:
  1752. do iparam = 1, mf%nparam
  1753. ! split at '-', read first part:
  1754. call goReadFromLine( line, paramkey, status, sep='-' )
  1755. IF_NOTOK_RETURN(status=1)
  1756. ! define variable:
  1757. if ( present(levi) ) then
  1758. ! 3D field:
  1759. if ( trim(paramkey) == 'mfu' ) then
  1760. call MDF_Def_Var( mf%hid, trim(paramkey), MDF_FLOAT, (/mf%dimid_lonb,mf%dimid_lat ,mf%dimid_lev_u,mf%dimid_time/), &
  1761. varid, status )
  1762. IF_NOTOK_RETURN(status=1)
  1763. else if ( trim(paramkey) == 'mfv' ) then
  1764. call MDF_Def_Var( mf%hid, trim(paramkey), MDF_FLOAT, (/mf%dimid_lon ,mf%dimid_latb,mf%dimid_lev_v,mf%dimid_time/), &
  1765. varid, status )
  1766. IF_NOTOK_RETURN(status=1)
  1767. else
  1768. call MDF_Def_Var( mf%hid, trim(paramkey), MDF_FLOAT, (/mf%dimid_lon ,mf%dimid_lat ,mf%dimid_lev,mf%dimid_time/), &
  1769. varid, status )
  1770. IF_NOTOK_RETURN(status=1)
  1771. end if
  1772. else
  1773. ! 2D field:
  1774. if ( trim(mf%tres) == 'constant' ) then
  1775. call MDF_Def_Var( mf%hid, trim(paramkey), MDF_FLOAT, (/mf%dimid_lon,mf%dimid_lat/), varid, status )
  1776. IF_NOTOK_RETURN(status=1)
  1777. else
  1778. call MDF_Def_Var( mf%hid, trim(paramkey), MDF_FLOAT, (/mf%dimid_lon,mf%dimid_lat,mf%dimid_time/), varid, status )
  1779. IF_NOTOK_RETURN(status=1)
  1780. end if
  1781. end if
  1782. ! convert from tm5 name to standard name:
  1783. call TMM_CF_Convert_Name( trim(paramkey), mf%cfname_param(iparam), status )
  1784. IF_NOTOK_RETURN(status=1)
  1785. ! get standard units:
  1786. call TMM_CF_Standard_Units( trim(mf%cfname_param(iparam)), mf%cfunit_param(iparam), status )
  1787. IF_NOTOK_RETURN(status=1)
  1788. ! add standard_name and units attributes:
  1789. call CF_Put_Standard_Atts( mf%hid, varid, trim(mf%cfname_param(iparam)), trim(mf%cfunit_param(iparam)), status )
  1790. IF_NOTOK_RETURN(status=1)
  1791. ! for post processing ...
  1792. l = len_trim(cell_measure)
  1793. if ( l > 0 ) then
  1794. call MDF_Put_Att( mf%hid, varid, 'cell_measure', cell_measure(2:l), status )
  1795. IF_NOTOK_RETURN(status=1)
  1796. end if
  1797. ! specify how computed:
  1798. l = len_trim(cell_methods)
  1799. if ( l > 0 ) then
  1800. call MDF_Put_Att( mf%hid, varid, 'cell_methods', cell_methods(2:l), status )
  1801. IF_NOTOK_RETURN(status=1)
  1802. end if
  1803. ! extra coordinates that apply to this variable:
  1804. l = len_trim(coordinates)
  1805. if ( l > 0 ) then
  1806. call MDF_Put_Att( mf%hid, varid, 'coordinates', coordinates(2:l), status )
  1807. IF_NOTOK_RETURN(status=1)
  1808. end if
  1809. ! store variable id:
  1810. mf%varid_param(iparam) = varid
  1811. ! store variable name:
  1812. mf%varname_param(iparam) = trim(paramkey)
  1813. ! no records written yet:
  1814. mf%itrec_param(iparam) = 0
  1815. end do
  1816. !
  1817. ! end of defintion phase:
  1818. !
  1819. call MDF_EndDef( mf%hid, status )
  1820. IF_NOTOK_RETURN(status=1)
  1821. !
  1822. ! fill time independent variables
  1823. !
  1824. ! axis:
  1825. call MDF_Put_Var( mf%hid, mf%varid_lon, lli%lon_deg, status )
  1826. IF_NOTOK_RETURN(status=1)
  1827. ! axis bounds:
  1828. call MDF_Put_Var( mf%hid, mf%varid_lon_bounds, lli%lon_bounds_deg, status )
  1829. IF_NOTOK_RETURN(status=1)
  1830. ! extra:
  1831. if ( nuv /= 'n' ) then
  1832. call MDF_Put_Var( mf%hid, mf%varid_lonb, lli%blon_deg, status )
  1833. IF_NOTOK_RETURN(status=1)
  1834. end if
  1835. ! axis:
  1836. call MDF_Put_Var( mf%hid, mf%varid_lat, lli%lat_deg, status )
  1837. IF_NOTOK_RETURN(status=1)
  1838. ! axis bounds:
  1839. call MDF_Put_Var( mf%hid, mf%varid_lat_bounds, lli%lat_bounds_deg, status )
  1840. IF_NOTOK_RETURN(status=1)
  1841. ! extra:
  1842. if ( nuv /= 'n' ) then
  1843. call MDF_Put_Var( mf%hid, mf%varid_latb, lli%blat_deg, status )
  1844. IF_NOTOK_RETURN(status=1)
  1845. end if
  1846. ! cell area ?
  1847. if ( nuv == 'n' ) then
  1848. ! storage:
  1849. allocate( pat(lli%nlon,lli%nlat) )
  1850. ! fill:
  1851. call AreaOper( lli, pat, '=', 'm2', status )
  1852. IF_NOTOK_RETURN(status=1)
  1853. ! write:
  1854. call MDF_Put_Var( mf%hid, mf%varid_cell_area, pat, status )
  1855. IF_NOTOK_RETURN(status=1)
  1856. ! clear:
  1857. deallocate( pat )
  1858. end if
  1859. ! levels ?
  1860. if ( present(levi) ) then
  1861. !! tm5 variables:
  1862. !call MDF_Put_Var( mf%hid, mf%varid_tm5_at, levi%a, status )
  1863. !IF_NOTOK_RETURN(status=1)
  1864. !call MDF_Put_Var( mf%hid, mf%varid_tm5_bt, levi%b, status )
  1865. !IF_NOTOK_RETURN(status=1)
  1866. ! where defined ?
  1867. select case ( nw )
  1868. !~ layer mid points:
  1869. case ( 'n' )!, '*' )
  1870. ! number of layers:
  1871. !if ( present(nlev) ) then
  1872. ! n = nlev
  1873. !else
  1874. n = levi%nlev
  1875. !end if
  1876. ! standard pressures (full levels):
  1877. call MDF_Put_Var( mf%hid, mf%varid_lev, levi%fp0(1:n), status )
  1878. IF_NOTOK_RETURN(status=1)
  1879. ! full level coefficients:
  1880. call MDF_Put_Var( mf%hid, mf%varid_ap, levi%fa(1:n), status )
  1881. IF_NOTOK_RETURN(status=1)
  1882. call MDF_Put_Var( mf%hid, mf%varid_b , levi%fb(1:n), status )
  1883. IF_NOTOK_RETURN(status=1)
  1884. ! half level coefficients:
  1885. call MDF_Put_Var( mf%hid, mf%varid_ap_bounds, levi%fa_bounds(:,1:n), status )
  1886. IF_NOTOK_RETURN(status=1)
  1887. call MDF_Put_Var( mf%hid, mf%varid_b_bounds , levi%fb_bounds(:,1:n), status )
  1888. IF_NOTOK_RETURN(status=1)
  1889. ! extra ?
  1890. if ( nuv /= 'n' ) then
  1891. ! standard pressures (full levels):
  1892. call MDF_Put_Var( mf%hid, mf%varid_lev_u, levi%fp0(1:n), status )
  1893. IF_NOTOK_RETURN(status=1)
  1894. ! standard pressures (full levels):
  1895. call MDF_Put_Var( mf%hid, mf%varid_lev_v, levi%fp0(1:n), status )
  1896. IF_NOTOK_RETURN(status=1)
  1897. end if
  1898. !~ layer interfaces:
  1899. case ( 'w' )
  1900. ! standard pressures (half levels):
  1901. call MDF_Put_Var( mf%hid, mf%varid_lev, levi%p0, status )
  1902. IF_NOTOK_RETURN(status=1)
  1903. ! half level coefficients:
  1904. call MDF_Put_Var( mf%hid, mf%varid_ap, levi%a, status )
  1905. IF_NOTOK_RETURN(status=1)
  1906. call MDF_Put_Var( mf%hid, mf%varid_b , levi%b, status )
  1907. IF_NOTOK_RETURN(status=1)
  1908. !~ other ...
  1909. case default
  1910. write (gol,'("unsupported nw : ",a)') trim(nw); call goErr
  1911. TRACEBACK; status=1; return
  1912. end select
  1913. end if
  1914. !
  1915. ! done
  1916. !
  1917. ! ok
  1918. status = 0
  1919. end subroutine Define_File
  1920. ! ***
  1921. subroutine WriteTimes( mf, itrec, tref, t1, t2, status )
  1922. use GO , only : TDate
  1923. use GO , only : operator(-), operator(+), operator(/), rTotal, Get, NewDate, IsAnyDate
  1924. use MDF , only : MDF_Put_Var
  1925. ! --- in/out -------------------------------
  1926. type(TMeteoFile_tm5_nc), intent(inout) :: mf
  1927. integer, intent(in) :: itrec
  1928. type(TDate), intent(in) :: tref, t1, t2
  1929. integer, intent(out) :: status
  1930. ! --- const --------------------------------------
  1931. character(len=*), parameter :: rname = mname//'/WriteTimes'
  1932. ! --- local ------------------------------
  1933. type(TDate) :: tsince
  1934. type(TDate) :: tmid
  1935. real(8) :: tsec
  1936. integer :: time6(6)
  1937. ! --- begin ---------------------------------
  1938. ! not for constant fields ...
  1939. if ( trim(mf%tres) /= 'constant' ) then
  1940. ! base time:
  1941. tsince = NewDate( time6=since_time6 )
  1942. ! write reference times:
  1943. if ( IsAnyDate(tref) ) then
  1944. tsec = 0.0
  1945. time6 = 0
  1946. else
  1947. tsec = rTotal( tref - tsince, 'sec' )
  1948. call Get( tref, time6=time6 )
  1949. end if
  1950. call MDF_Put_Var( mf%hid, mf%varid_reftime, (/tsec/), status, start=(/itrec/), count=(/1/) )
  1951. IF_NOTOK_RETURN(status=1)
  1952. call MDF_Put_Var( mf%hid, mf%varid_reftimevalues, time6, status, start=(/1,itrec/), count=(/6,1/) )
  1953. IF_NOTOK_RETURN(status=1)
  1954. ! write mid time:
  1955. if ( IsAnyDate(t1) .or. IsAnyDate(t2) ) then
  1956. tsec = 0.0
  1957. time6 = 0
  1958. else
  1959. tmid = t1 + (t2-t1)/2
  1960. tsec = rTotal( tmid - tsince, 'sec' )
  1961. call Get( tmid, time6=time6 )
  1962. end if
  1963. call MDF_Put_Var( mf%hid, mf%varid_time, (/tsec/), status, start=(/itrec/), count=(/1/) )
  1964. IF_NOTOK_RETURN(status=1)
  1965. call MDF_Put_Var( mf%hid, mf%varid_timevalues, time6, status, start=(/1,itrec/), count=(/6,1/) )
  1966. IF_NOTOK_RETURN(status=1)
  1967. ! start time:
  1968. if ( IsAnyDate(t1) ) then
  1969. tsec = 0.0
  1970. time6 = 0
  1971. else
  1972. tsec = rTotal( t1 - tsince, 'sec' )
  1973. call Get( t1, time6=time6 )
  1974. end if
  1975. call MDF_Put_Var( mf%hid, mf%varid_time_bounds, (/tsec/), status, start=(/1,itrec/), count=(/1,1/) )
  1976. IF_NOTOK_RETURN(status=1)
  1977. call MDF_Put_Var( mf%hid, mf%varid_timevalues_bounds, time6, status, start=(/1,1,itrec/), count=(/1,6,1/) )
  1978. IF_NOTOK_RETURN(status=1)
  1979. ! end time:
  1980. if ( IsAnyDate(t2) ) then
  1981. tsec = 0.0
  1982. time6 = 0
  1983. else
  1984. tsec = rTotal( t2 - tsince, 'sec' )
  1985. call Get( t2, time6=time6 )
  1986. end if
  1987. call MDF_Put_Var( mf%hid, mf%varid_time_bounds, (/tsec/), status, start=(/2,itrec/), count=(/1,1/) )
  1988. IF_NOTOK_RETURN(status=1)
  1989. call MDF_Put_Var( mf%hid, mf%varid_timevalues_bounds, time6, status, start=(/2,1,itrec/), count=(/1,6,1/) )
  1990. IF_NOTOK_RETURN(status=1)
  1991. end if ! not const
  1992. ! ok
  1993. status = 0
  1994. end subroutine WriteTimes
  1995. ! ***
  1996. subroutine mf_WriteRecord_2d( mf, tmi, paramkey, unit, tref, t1, t2, &
  1997. lli, nuv, ll, status )
  1998. use GO , only : TDate
  1999. use Grid , only : TllGridInfo
  2000. use MDF , only : MDF_Create, MDF_Close, MDF_REPLACE
  2001. use MDF , only : MDF_Put_Var
  2002. use tmm_info, only : TMeteoInfo
  2003. use TMM_CF , only : TMM_CF_Convert_Units
  2004. ! --- in/out -------------------------------
  2005. type(TMeteoFile_tm5_nc), intent(inout) :: mf
  2006. type(TMeteoInfo), intent(in) :: tmi
  2007. character(len=*), intent(in) :: paramkey, unit
  2008. type(TDate), intent(in) :: tref, t1, t2
  2009. type(TllGridInfo), intent(in) :: lli
  2010. character(len=1), intent(in) :: nuv
  2011. real, intent(in) :: ll(:,:)
  2012. integer, intent(out) :: status
  2013. ! --- const --------------------------------------
  2014. character(len=*), parameter :: rname = mname//'/mf_WriteRecord_2d'
  2015. ! --- local ------------------------------
  2016. integer :: iparam
  2017. integer :: i
  2018. integer :: itrec
  2019. type(TDate) :: tsince
  2020. type(TDate) :: tmid
  2021. real(8) :: tsec
  2022. integer :: time6(6)
  2023. real :: ufac
  2024. ! --- begin ---------------------------------
  2025. ! output ?
  2026. if ( mf%io /= 'o' ) then
  2027. write (gol,'("file should have been opened for output, but io=",a)') mf%io; call goErr
  2028. TRACEBACK; status=1; return
  2029. end if
  2030. ! new or existing ?
  2031. if ( .not. mf%output_initialised ) then
  2032. ! open new file, destroy old:
  2033. call MDF_Create( trim(mf%fname), output_type, MDF_REPLACE, mf%hid, status )
  2034. IF_NOTOK_RETURN(status=1)
  2035. ! write file header:
  2036. call Define_File( mf, lli, nuv, status )
  2037. IF_NOTOK_RETURN(status=1)
  2038. ! status new
  2039. call WriteStatus( mf, 'in-progress', status )
  2040. IF_NOTOK_RETURN(status=1)
  2041. ! no records written yet:
  2042. mf%output_nrec = 0
  2043. ! now the file is initialised
  2044. mf%output_initialised = .true.
  2045. endif
  2046. ! search parameter:
  2047. iparam = -1
  2048. do i = 1, mf%nparam
  2049. if ( trim(paramkey) == trim(mf%varname_param(i)) ) then
  2050. iparam = i
  2051. exit
  2052. end if
  2053. end do
  2054. if ( iparam < 0 ) then
  2055. write (gol,'("could not find parameter `",a,"` in list : ",a)') trim(paramkey), trim(mf%paramkeys); call goErr
  2056. TRACEBACK; status=1; return
  2057. end if
  2058. ! next record:
  2059. mf%itrec_param(iparam) = mf%itrec_param(iparam) + 1
  2060. ! short:
  2061. itrec = mf%itrec_param(iparam)
  2062. ! update time fields:
  2063. call WriteTimes( mf, itrec, tref, t1, t2, status )
  2064. IF_NOTOK_RETURN(status=1)
  2065. ! conversion factor:
  2066. call TMM_CF_Convert_Units( trim(unit), trim(mf%cfunit_param(iparam)), ufac, status )
  2067. IF_NOTOK_RETURN(status=1)
  2068. !! info ...
  2069. !if ( ufac /= 1.0 ) then
  2070. ! write (gol,'(" convert `",a,"` from `",a,"` to `",a,"` with factor ",f8.2," ; write range ",2f8.2)') &
  2071. ! trim(paramkey), trim(unit), trim(mf%cfunit_param(iparam)), ufac, minval(ll*ufac), maxval(ll*ufac); call goPr
  2072. !end if
  2073. ! write data:
  2074. if ( trim(mf%tres) == 'constant' ) then
  2075. call MDF_Put_Var( mf%hid, mf%varid_param(iparam), ll*ufac, status )
  2076. IF_NOTOK_RETURN(status=1)
  2077. else
  2078. call MDF_Put_Var( mf%hid, mf%varid_param(iparam), ll*ufac, status, &
  2079. start=(/1,1,itrec/), count=(/size(ll,1),size(ll,2),1/) )
  2080. IF_NOTOK_RETURN(status=1)
  2081. end if
  2082. ! next record has been written:
  2083. mf%output_nrec = mf%output_nrec + 1
  2084. ! completed ? then re-write status file:
  2085. if ( mf%output_nrec == mf%output_ntrec*mf%nparam ) then
  2086. ! close file:
  2087. call MDF_Close( mf%hid, status )
  2088. IF_NOTOK_RETURN(status=1)
  2089. ! rewrite status file:
  2090. call WriteStatus( mf, 'completed', status )
  2091. IF_NOTOK_RETURN(status=1)
  2092. ! reset flag:
  2093. mf%output_initialised = .false.
  2094. end if
  2095. ! ok
  2096. status = 0
  2097. end subroutine mf_WriteRecord_2d
  2098. ! ***
  2099. subroutine mf_WriteRecord_3d( mf, tmi, spname, paramkey, unit, tref, t1, t2, &
  2100. lli, nuv, levi, nw, ps, ll, status )!, &
  2101. !nlev )
  2102. use GO , only : TDate
  2103. use Grid , only : TllGridInfo, TLevelInfo
  2104. use MDF , only : MDF_Create, MDF_Close, MDF_REPLACE
  2105. use MDF , only : MDF_Put_Var
  2106. use tmm_info, only : TMeteoInfo
  2107. use TMM_CF , only : TMM_CF_Convert_Units
  2108. ! --- in/out -------------------------------
  2109. type(TMeteoFile_tm5_nc), intent(inout) :: mf
  2110. type(TMeteoInfo), intent(in) :: tmi
  2111. character(len=*), intent(in) :: spname, paramkey, unit
  2112. type(TDate), intent(in) :: tref, t1, t2
  2113. type(TllGridInfo), intent(in) :: lli
  2114. character(len=1), intent(in) :: nuv
  2115. type(TLevelInfo), intent(in) :: levi
  2116. character(len=1), intent(in) :: nw
  2117. real, intent(in) :: ps(:,:)
  2118. real, intent(in) :: ll(:,:,:)
  2119. integer, intent(out) :: status
  2120. !integer, intent(in), optional :: nlev
  2121. ! --- const --------------------------------------
  2122. character(len=*), parameter :: rname = mname//'/mf_WriteRecord_3d'
  2123. ! --- local ------------------------------
  2124. integer :: iparam
  2125. integer :: i
  2126. integer :: itrec
  2127. type(TDate) :: tsince
  2128. type(TDate) :: tmid
  2129. real(8) :: tsec
  2130. integer :: time6(6)
  2131. real :: ufac
  2132. real, allocatable :: llX(:,:,:)
  2133. character(len=1) :: nwX
  2134. ! --- begin ---------------------------------
  2135. ! output ?
  2136. if ( mf%io /= 'o' ) then
  2137. write (gol,'("file should have been opened for output, but io=",a)') mf%io; call goErr
  2138. TRACEBACK; status=1; return
  2139. end if
  2140. ! convection fields provided on lowest layers only ...
  2141. if ( nw == '*' ) then
  2142. ! extend to all layers:
  2143. allocate( llX(size(ll,1),size(ll,2),levi%nlev) )
  2144. ! pad with zeros:
  2145. llX = 0.0
  2146. llX(:,:,1:size(ll,3)) = ll
  2147. ! new description:
  2148. nwX = 'n'
  2149. else
  2150. ! just copy:
  2151. allocate( llX(size(ll,1),size(ll,2),size(ll,3)) )
  2152. llX = ll
  2153. nwX = nw
  2154. end if
  2155. ! new or existing ?
  2156. if ( .not. mf%output_initialised ) then
  2157. ! open new file, destroy old:
  2158. call MDF_Create( trim(mf%fname), output_type, MDF_REPLACE, mf%hid, status )
  2159. IF_NOTOK_RETURN(status=1)
  2160. ! write file header:
  2161. call Define_File( mf, lli, nuv, status, levi=levi, nw=nwX )!, nlev=nlev )
  2162. IF_NOTOK_RETURN(status=1)
  2163. ! status new
  2164. call WriteStatus( mf, 'in-progress', status )
  2165. IF_NOTOK_RETURN(status=1)
  2166. ! no records written yet:
  2167. mf%output_nrec = 0
  2168. ! now the file is initialised
  2169. mf%output_initialised = .true.
  2170. endif
  2171. ! search parameter:
  2172. iparam = -1
  2173. do i = 1, mf%nparam
  2174. if ( trim(paramkey) == trim(mf%varname_param(i)) ) then
  2175. iparam = i
  2176. exit
  2177. end if
  2178. end do
  2179. if ( iparam < 0 ) then
  2180. write (gol,'("could not find parameter `",a,"` in list : ",a)') trim(paramkey), trim(mf%paramkeys); call goErr
  2181. TRACEBACK; status=1; return
  2182. end if
  2183. ! next record:
  2184. mf%itrec_param(iparam) = mf%itrec_param(iparam) + 1
  2185. ! short:
  2186. itrec = mf%itrec_param(iparam)
  2187. ! update time fields:
  2188. call WriteTimes( mf, itrec, tref, t1, t2, status )
  2189. IF_NOTOK_RETURN(status=1)
  2190. ! conversion factor:
  2191. call TMM_CF_Convert_Units( trim(unit), trim(mf%cfunit_param(iparam)), ufac, status )
  2192. IF_NOTOK_RETURN(status=1)
  2193. !! info ...
  2194. !if ( ufac /= 1.0 ) then
  2195. ! write (gol,'(" convert `",a,"` from `",a,"` to `",a,"` with factor ",f8.2," ; write range ",2f8.2)') &
  2196. ! trim(paramkey), trim(unit), trim(mf%cfunit_param(iparam)), ufac, minval(llX*ufac), maxval(llX*ufac); call goPr
  2197. !end if
  2198. ! convert:
  2199. llX = llX * ufac
  2200. ! write data:
  2201. call MDF_Put_Var( mf%hid, mf%varid_param(iparam), llX, status, &
  2202. start=(/1,1,1,itrec/), count=(/size(llX,1),size(llX,2),size(llX,3),1/) )
  2203. IF_NOTOK_RETURN(status=1)
  2204. ! clear:
  2205. deallocate( llX )
  2206. ! write surface pressure:
  2207. if ( nuv == 'u' ) then
  2208. call MDF_Put_Var( mf%hid, mf%varid_ps_u, ps, status, &
  2209. start=(/1,1,itrec/), count=(/size(ps,1),size(ps,2),1/) )
  2210. IF_NOTOK_RETURN(status=1)
  2211. else if ( nuv == 'v' ) then
  2212. call MDF_Put_Var( mf%hid, mf%varid_ps_v, ps, status, &
  2213. start=(/1,1,itrec/), count=(/size(ps,1),size(ps,2),1/) )
  2214. IF_NOTOK_RETURN(status=1)
  2215. else
  2216. call MDF_Put_Var( mf%hid, mf%varid_ps, ps, status, &
  2217. start=(/1,1,itrec/), count=(/size(ps,1),size(ps,2),1/) )
  2218. IF_NOTOK_RETURN(status=1)
  2219. end if
  2220. ! next record has been written:
  2221. mf%output_nrec = mf%output_nrec + 1
  2222. ! completed ? then re-write status file:
  2223. if ( mf%output_nrec == mf%output_ntrec*mf%nparam ) then
  2224. ! close file:
  2225. call MDF_Close( mf%hid, status )
  2226. IF_NOTOK_RETURN(status=1)
  2227. ! rewrite status file:
  2228. call WriteStatus( mf, 'completed', status )
  2229. IF_NOTOK_RETURN(status=1)
  2230. ! reset flag:
  2231. mf%output_initialised = .false.
  2232. end if
  2233. ! ok
  2234. status = 0
  2235. end subroutine mf_WriteRecord_3d
  2236. ! ***
  2237. subroutine WriteStatus( mf, msg, status )
  2238. ! --- in/out -------------------------------
  2239. type(TMeteoFile_tm5_nc), intent(inout) :: mf
  2240. character(len=*), intent(in) :: msg
  2241. integer, intent(out) :: status
  2242. ! --- const --------------------------------------
  2243. character(len=*), parameter :: rname = mname//'/WriteStatus'
  2244. ! --- local ------------------------------
  2245. integer :: fu
  2246. logical :: opened
  2247. ! --- begin ---------------------------------
  2248. ! select unused file unit:
  2249. fu = 1234
  2250. do
  2251. inquire( unit=fu, opened=opened )
  2252. if ( .not. opened ) exit
  2253. fu = fu + 1
  2254. end do
  2255. ! open:
  2256. open( fu, file=trim(mf%fname)//'.status', form='formatted', iostat=status )
  2257. if (status/=0) then
  2258. write (gol,'("opening status file:")'); call goErr
  2259. write (gol,'(" file : ",a)') trim(mf%fname); call goErr
  2260. TRACEBACK; status=1; return
  2261. end if
  2262. ! write message:
  2263. write (fu,'(a)',iostat=status) msg
  2264. if (status/=0) then
  2265. write (gol,'("writing status:")'); call goErr
  2266. write (gol,'(" file : ",a)') trim(mf%fname); call goErr
  2267. write (gol,'(" msg : ",a)') msg; call goErr
  2268. TRACEBACK; status=1; return
  2269. end if
  2270. ! done:
  2271. close( fu, iostat=status )
  2272. if (status/=0) then
  2273. write (gol,'("closing status file:")'); call goErr
  2274. write (gol,'(" file : ",a)') trim(mf%fname); call goErr
  2275. TRACEBACK; status=1; return
  2276. end if
  2277. ! ok
  2278. status = 0
  2279. end subroutine WriteStatus
  2280. end module tmm_mf_tm5_nc