tmm_mf_tm5_nc.F90 94 KB

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