tmm_mf_ncep_cdc.F90 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657
  1. !###############################################################################
  2. !
  3. ! Interface to NCEP re-analysis data.
  4. !
  5. ! Database
  6. ! --------
  7. !
  8. ! http://www.cdc.noaa.gov/cdc/reanalysis/reanalysis.shtml
  9. !
  10. ! NetCDF files
  11. ! ------------
  12. !
  13. ! global attributes:
  14. ! Conventions = "CDC Non-gridded" ;
  15. ! title = "4x Daily Spectral Coefficients from the NMC Reanalysis for Natural Log of Pressure at the Surface" ;
  16. ! base_date = 2000s, 1s, 1s ;
  17. ! history = ... ;
  18. ! description = "Data is from NMC initialized reanalysis",
  19. ! platform = "Model" ;
  20. ! m_fastest = "F" ;
  21. ! storage_type = "Spectral" ;
  22. ! compression_used = "T" ;
  23. !
  24. !
  25. ! dimensions:
  26. ! num_values = 4032
  27. ! level = 28
  28. ! num_mean = 2 ;
  29. ! time = UNLIMITED ;
  30. !
  31. ! level data sets:
  32. !
  33. ! level float array[level]
  34. ! units = "sigma_level"
  35. ! long_name = "Sigma"
  36. ! positive = "down"
  37. !
  38. ! spectral data sets:
  39. !
  40. ! mean float array[2*level,time]
  41. ! long_name string "First Spectral Coefficients for Natural Log of Pressure at the Surface"
  42. ! units string "-"
  43. ! missing_value float
  44. !
  45. ! add_offset float array[level,time]
  46. ! long_name "Add offset of Spectral Coefficients for Natural Log of Pressure"
  47. ! units "-"
  48. ! missing_value
  49. !
  50. ! scale_factor float array[level,time]
  51. ! long_name "Scale Factor of Spectral Coefficients for Natural Log of Pressure"
  52. ! units "-"
  53. ! missing_value
  54. !
  55. ! time double array[time]
  56. ! units "hours since 1-1-1 00:00:0.0" ;
  57. ! long_name "Time" ;
  58. ! delta_t "0000-00-00 06:00:00" ;
  59. !
  60. ! pres int array[num_values,level,time]
  61. ! long_name "Spectral Coefficients for Natural Log of Pressure at the Surface"
  62. ! units "natural log of pressure in centibars" ;
  63. ! missing_value
  64. ! precision = 0s ;
  65. ! least_significant_digit = 32767s ;
  66. ! trunc_count = 62s ;
  67. ! trunc_type = "Triangular" ;
  68. ! var_desc = "Pressure", "P" ;
  69. ! dataset = "NMC Reanalysis", "L" ;
  70. ! level_desc = "Surface", "F" ;
  71. ! statistic = "Individual Obs\n", "I" ;
  72. ! parent_stat = "Other\n", "-" ;
  73. !
  74. ! gaussian or lon/lat data sets:
  75. !
  76. ! short pres(time, lat, lon) ;
  77. ! long_name = "4xDaily Surface Pressure" ;
  78. ! valid_range = 40000.f, 115000.f ;
  79. ! actual_range = 48540.f, 108990.f ;
  80. ! units = "Pascals" ;
  81. ! add_offset = 367650.f ;
  82. ! scale_factor = 10.f ;
  83. ! missing_value = 32766s ;
  84. ! precision = -1s ;
  85. ! least_significant_digit = -1s ;
  86. ! GRIB_id = 1s ;
  87. ! GRIB_name = "PRES" ;
  88. ! var_desc = "Pressure\n", "CC" ;
  89. ! dataset = "NMC Reanalysis\n", "L" ;
  90. !
  91. ! Date and time
  92. ! -------------
  93. !
  94. ! Global attribute 'base_date' specifies the first date :
  95. ! base_date = (/2000,01,01/)
  96. !
  97. ! Data set 'time' contains hours since year 1 or there about.
  98. ! Substract the first element from the array to have an offset
  99. ! in hours from midnight at base_date.
  100. !
  101. ! Spectral fields
  102. ! -----------
  103. !
  104. ! From the 'discription':
  105. !
  106. ! For each latitude (going from north pole to south pole).
  107. ! the associated legendre functions are defined:
  108. ! Pbar(m,n,theta) =
  109. ! sqrt((2*n+1)*factorial(n-m)/(2*factorial(n+m)))*sin(theta)**m/(2**n*factorial(n))
  110. ! times the (n+m)th derivative of (x**2-1)**n with respect to x=cos(theta)
  111. !
  112. ! note: theta = 0.5*pi - phi, where phi is latitude and theta is colatitude.
  113. ! Therefore, cos(theta) = sin(phi) and sin(theta) = cos(phi).
  114. !
  115. ! where n is degree (subscript), m is order (superscript),
  116. ! and theta is colatitude in radians.
  117. ! The functions are orthogonal polynomials on the surface of the sphere and
  118. ! are normalized so that the integral of (PBAR(n,m,theta)**2)*sin(theta)
  119. ! on the interval theta=0 to theta=pi equals 1.
  120. ! Note that Pbar(0,0,theta) = sqrt(2)/2
  121. !
  122. ! Truncation:
  123. ! number of data values : 4032 = 2016 complex numbers
  124. ! number of spectral coeff = (T+1)*(T+2)/2 = 2016, thus T=62
  125. !
  126. ! The 'mean' are the first spectral coeff and should be added.
  127. !
  128. ! Packing
  129. ! -------
  130. !
  131. ! From http://www.cdc.noaa.gov/PublicData/faq.html#12 :
  132. ! "Most of the data in our netCDF files are packed. That is to say they have been
  133. ! transformed by a scale factor and an add offset to reduce the storage needed to
  134. ! two bytes per value. When you extract the short integers, you must unpack the
  135. ! data to recover the correct floating point data values. Data files that contain
  136. ! packed data will have a non-zero add offset and/or a scale factor not equal to 1.
  137. ! The transformation is:
  138. ! float_value = (short_value * scale_factor) + add_offset "
  139. !
  140. !
  141. !### macro's ###################################################################
  142. !
  143. #define TRACEBACK write (gol,'("in ",a," (",a,", line",i5,")")') rname, __FILE__, __LINE__; call goErr
  144. #define IF_NOTOK_RETURN(action) if (status/=0) then; TRACEBACK; action; return; end if
  145. #define IF_ERROR_RETURN(action) if (status> 0) then; TRACEBACK; action; return; end if
  146. !
  147. #include "tmm.inc"
  148. !
  149. !###############################################################################
  150. module tmm_mf_ncep_cdc
  151. use GO , only : gol, goErr, goPr
  152. use GO , only : TDate
  153. implicit none
  154. ! --- in/out ----------------------------
  155. private
  156. public :: TMeteoFile_ncep_cdc
  157. public :: Init, Done
  158. public :: Get
  159. public :: ReadRecord
  160. ! --- const ------------------------------
  161. character(len=*), parameter :: mname = 'tmm_mf_ncep_cdc'
  162. !--- type ---------------------------------
  163. type TMeteoFile_ncep_cdc
  164. ! field collection
  165. character(len=256) :: paramkeys
  166. type(TDate) :: trange(2)
  167. ! file names
  168. character(len=256) :: dir
  169. integer :: ccyy
  170. character(len=1) :: pathsep, namesep
  171. end type TMeteoFile_ncep_cdc
  172. ! --- interfaces -------------------------
  173. interface Init
  174. module procedure mf_Init
  175. end interface
  176. interface Done
  177. module procedure mf_Done
  178. end interface
  179. interface Get
  180. module procedure mf_Get
  181. end interface
  182. interface ReadRecord
  183. module procedure mf_ReadRecord
  184. end interface
  185. contains
  186. ! ==============================================================
  187. subroutine mf_Init( mf, dir, archivekeys, paramkey, &
  188. tref, t1, t2, status )
  189. use GO, only : TDate, Get, NewDate, operator(>)
  190. use GO, only : goVarValue
  191. ! --- in/out ----------------------------
  192. type(TMeteoFile_ncep_cdc), intent(out) :: mf
  193. character(len=*), intent(in) :: dir
  194. character(len=*), intent(in) :: archivekeys
  195. character(len=*), intent(in) :: paramkey
  196. type(TDate), intent(in) :: tref, t1, t2
  197. integer, intent(out) :: status
  198. ! --- const --------------------------------------
  199. character(len=*), parameter :: rname = mname//'/mf_Init'
  200. ! --- local -------------------------------
  201. type(TDate) :: tend
  202. ! --- begin --------------------------------
  203. ! store directory:
  204. mf%dir = dir
  205. !
  206. ! extract fields from archivekey :
  207. ! mdir=spectral
  208. !
  209. mf%pathsep = '/'
  210. call goVarValue( archivekeys, ';', 'pathsep', '=', mf%pathsep, status )
  211. if (status>0) then; write (gol,'("in ",a)') rname; call goErr; status=1; return; end if
  212. !
  213. mf%namesep = '-'
  214. call goVarValue( archivekeys, ';', 'namesep', '=', mf%namesep, status )
  215. if (status>0) then; write (gol,'("in ",a)') rname; call goErr; status=1; return; end if
  216. ! extract year in filename from requested time range:
  217. call Get( t2, year=mf%ccyy )
  218. tend = NewDate( time6=(/mf%ccyy,12,31,18,00,00/) )
  219. if ( t2 > tend ) mf%ccyy = mf%ccyy + 1
  220. ! files valid for complete year:
  221. mf%trange(1) = NewDate( mf%ccyy-1, 12, 31, 18, 00, 00, 001 )
  222. mf%trange(2) = NewDate( mf%ccyy , 12, 31, 18, 00, 00, 000 )
  223. ! files contain one param only:
  224. mf%paramkeys = '-'//trim(paramkey)//'-'
  225. ! dummy filename (might be used in error messages)
  226. mf%filename = 'ncep cdc file'
  227. ! ok
  228. status = 0
  229. end subroutine mf_Init
  230. ! ***
  231. subroutine mf_Done( mf, status )
  232. ! --- in/out ------------------------------------
  233. type(TMeteoFile_ncep_cdc), intent(inout) :: mf
  234. integer, intent(out) :: status
  235. ! --- const --------------------------------------
  236. character(len=*), parameter :: rname = mname//'/mf_Done'
  237. ! --- begin -------------------------------------
  238. ! files have been closed in ReadRecord/WriteRecord
  239. ! ok
  240. status = 0
  241. end subroutine mf_Done
  242. ! ***
  243. subroutine mf_Get( mf, status, trange1, trange2, paramkeys )
  244. use GO, only : TDate
  245. ! --- in/out ----------------------------
  246. type(TMeteoFile_ncep_cdc), intent(in) :: mf
  247. integer, intent(out) :: status
  248. type(TDate), intent(out), optional :: trange1, trange2
  249. character(len=*), intent(out), optional :: paramkeys
  250. ! --- const --------------------------------------
  251. character(len=*), parameter :: rname = mname//'/mf_Get'
  252. ! --- local --------------------------------
  253. ! --- begin --------------------------------
  254. ! time range:
  255. if ( present(trange1) ) trange1 = mf%trange(1)
  256. if ( present(trange2) ) trange2 = mf%trange(2)
  257. ! parameter names:
  258. if ( present(paramkeys) ) paramkeys = mf%paramkeys
  259. ! ok
  260. status = 0
  261. end subroutine mf_Get
  262. ! ***
  263. ! Return a field given parameter name, time, etc.
  264. ! Only one of grid types is filled!
  265. subroutine mf_ReadRecord( mf, paramkey, t1, t2, nuv, nw, &
  266. gridtype, levi, &
  267. lli, ll, sp_ll, &
  268. ggi, gg, sp_gg, &
  269. shi, sh, lnsp_sh, &
  270. tmi, status )
  271. use parray , only : pa_Init, pa_Done
  272. use GO , only : TDate
  273. use Grid , only : TLevelInfo
  274. use Grid , only : TllGridInfo, TggGridInfo, TshGridInfo
  275. use tmm_info , only : TMeteoInfo
  276. ! --- in/out -------------------------------
  277. type(TMeteoFile_ncep_cdc), intent(inout) :: mf
  278. character(len=*), intent(in) :: paramkey
  279. type(TDate), intent(in) :: t1, t2
  280. character(len=1), intent(in) :: nuv
  281. character(len=1), intent(in) :: nw
  282. character(len=2), intent(out) :: gridtype
  283. type(TLevelInfo), intent(out) :: levi
  284. type(TllGridInfo), intent(inout) :: lli
  285. real, pointer :: ll(:,:,:)
  286. real, pointer :: sp_ll(:,:)
  287. type(TggGridInfo), intent(inout) :: ggi
  288. real, pointer :: gg(:,:)
  289. real, pointer :: sp_gg(:)
  290. type(TshGridInfo), intent(inout) :: shi
  291. complex, pointer :: sh(:,:)
  292. complex, pointer :: lnsp_sh(:)
  293. type(TMeteoInfo), intent(out) :: tmi
  294. integer, intent(out) :: status
  295. ! --- const --------------------------------------
  296. character(len=*), parameter :: rname = mname//'/mf_ReadRecord'
  297. ! --- local -------------------------------
  298. real, pointer :: ll2(:,:,:)
  299. real, pointer :: gg2(:,:)
  300. complex, pointer :: sh2(:,:)
  301. ! --- begin ---------------------------------
  302. ! combined field ?
  303. select case ( paramkey )
  304. !
  305. ! total surface stress : sstr^2 = ewss^2 + nsss^2
  306. !
  307. case ( 'sstr' )
  308. ! read first field:
  309. call mf_ReadRecord_1( mf, 'ewss', t1, t2, nuv, nw, gridtype, levi, &
  310. lli, ll, sp_ll, ggi, gg, sp_gg, shi, sh, lnsp_sh, &
  311. tmi, status )
  312. IF_NOTOK_RETURN(status=1)
  313. ! init pointer:
  314. call pa_Init( ll2 ) ; call pa_Init( gg2 ) ; call pa_Init( sh2 )
  315. ! read second field:
  316. call mf_ReadRecord_1( mf, 'nsss', t1, t2, nuv, nw, gridtype, levi, &
  317. lli, ll2, sp_ll, ggi, gg2, sp_gg, shi, sh2, lnsp_sh, &
  318. tmi, status )
  319. IF_NOTOK_RETURN(status=1)
  320. ! process:
  321. select case ( gridtype )
  322. case ( 'll' ) ; ll = sqrt( ll**2 + ll2**2 )
  323. case ( 'gg' ) ; gg = sqrt( gg**2 + gg2**2 )
  324. case default
  325. write (gol,'("unsupported gridtype for sstr :",a)') gridtype; call goErr
  326. write (gol,'("in ",a)') rname; call goErr; status=1; return
  327. end select
  328. ! clear pointers:
  329. call pa_Done( ll2 ) ; call pa_Done( gg2 ) ; call pa_Done( sh2 )
  330. write (gol,'("WARNING : adhoc constant value for ncep surface stress ...")'); call goPr
  331. gg = 0.1 ! N/m2
  332. !
  333. ! sea surface temperature : skin temperture * sea-mask
  334. !
  335. case ( 'sst' )
  336. ! read skin temperature:
  337. call mf_ReadRecord_1( mf, 'skt', t1, t2, nuv, nw, gridtype, levi, &
  338. lli, ll, sp_ll, ggi, gg, sp_gg, shi, sh, lnsp_sh, &
  339. tmi, status )
  340. IF_NOTOK_RETURN(status=1)
  341. ! init pointers:
  342. call pa_Init( ll2 ) ; call pa_Init( gg2 ) ; call pa_Init( sh2 )
  343. ! read land-sea mask:
  344. call mf_ReadRecord_1( mf, 'lsm', t1, t2, nuv, nw, gridtype, levi, &
  345. lli, ll2, sp_ll, ggi, gg2, sp_gg, shi, sh2, lnsp_sh, &
  346. tmi, status )
  347. IF_NOTOK_RETURN(status=1)
  348. ! process:
  349. select case ( gridtype )
  350. case ( 'll' ) ; ll = ll * max( 0.0, 1.0 - ll2 )
  351. case ( 'gg' ) ; gg = gg * max( 0.0, 1.0 - gg2 )
  352. case default
  353. write (gol,'("unsupported gridtype for sst :",a)') gridtype; call goErr
  354. write (gol,'("in ",a)') rname; call goErr; status=1; return
  355. end select
  356. ! clear pointers:
  357. call pa_Done( ll2 ) ; call pa_Done( gg2 ) ; call pa_Done( sh2 )
  358. !
  359. ! no specials ...
  360. !
  361. case default
  362. call mf_ReadRecord_1( mf, paramkey, t1, t2, nuv, nw, gridtype, levi, &
  363. lli, ll, sp_ll, ggi, gg, sp_gg, shi, sh, lnsp_sh, &
  364. tmi, status )
  365. IF_NOTOK_RETURN(status=1)
  366. end select
  367. ! ok
  368. status = 0
  369. end subroutine mf_ReadRecord
  370. ! ***
  371. ! Return a field given parameter name, time, etc.
  372. ! Only one of grid types is filled!
  373. subroutine mf_ReadRecord_1( mf, paramkey, t1, t2, nuv, nw, &
  374. gridtype, levi, &
  375. lli, ll, sp_ll, &
  376. ggi, gg, sp_gg, &
  377. shi, sh, lnsp_sh, &
  378. tmi, status )
  379. use PArray , only : pa_Init, pa_Done, pa_SetShape
  380. use file_hdf , only : THdfFile, TSds, Init, Done, ReadAttribute, ReadData, GetInfo
  381. use binas , only : grav
  382. use GO , only : TDate, NewDate, Get, rTotal, IncrDate
  383. use GO , only : operator(+), operator(-), operator(/=), operator(<)
  384. use Grid , only : TLevelInfo, Init, Done
  385. use Grid , only : TllGridInfo, TggGridInfo, TshGridInfo
  386. use Grid , only : Interpol
  387. use tmm_info , only : TMeteoInfo, Init, AddHistory
  388. ! --- in/out -------------------------------
  389. type(TMeteoFile_ncep_cdc), intent(inout) :: mf
  390. character(len=*), intent(in) :: paramkey
  391. type(TDate), intent(in) :: t1, t2
  392. character(len=1), intent(in) :: nuv
  393. character(len=1), intent(in) :: nw
  394. character(len=2), intent(out) :: gridtype
  395. type(TLevelInfo), intent(out) :: levi
  396. type(TllGridInfo), intent(inout) :: lli
  397. real, pointer :: ll(:,:,:)
  398. real, pointer :: sp_ll(:,:)
  399. type(TggGridInfo), intent(inout) :: ggi
  400. real, pointer :: gg(:,:)
  401. real, pointer :: sp_gg(:)
  402. type(TshGridInfo), intent(inout) :: shi
  403. complex, pointer :: sh(:,:)
  404. complex, pointer :: lnsp_sh(:)
  405. type(TMeteoInfo), intent(out) :: tmi
  406. integer, intent(out) :: status
  407. ! --- const --------------------------------------
  408. character(len=*), parameter :: rname = mname//'/mf_ReadRecord_1'
  409. ! --- local -------------------------------
  410. logical :: read_2d, read_3d
  411. logical :: constant
  412. type(TDate) :: tbase
  413. integer :: year, hours
  414. integer :: tstart
  415. real :: tfactor
  416. integer :: nlev, ilev
  417. integer :: data_dims(1)
  418. real, allocatable :: levels(:)
  419. character(len=16) :: levtype
  420. integer :: shT
  421. real, pointer :: gg1(:)
  422. complex, pointer :: sh1(:)
  423. character(len=256) :: fname
  424. character(len=64) :: mdir
  425. character(len=16) :: fkey
  426. character(len=16) :: gridkey
  427. logical :: exist
  428. type(THdfFile) :: hdf
  429. type(TSds) :: sds
  430. character(len=16) :: sds_name
  431. character(len=64) :: key
  432. ! --- begin ---------------------------------
  433. ! no fluxes through boundaries ...
  434. if ( nuv /= 'n' ) then
  435. write (gol,'("unsupported nuv key : ",a)') nuv; call goErr
  436. write (gol,'("in ",a)') rname; call goErr; status=1; return
  437. end if
  438. ! init info; example of history: model==msc;sh==159;nlev==60
  439. call Init( tmi, paramkey, 'unknown', status )
  440. call AddHistory( tmi, 'model==ncep/ncar reanalysis 1', status )
  441. call AddHistory( tmi, 'archive==CDC netcdf archive', status )
  442. !
  443. ! ~~~ setup
  444. !
  445. read_2d = .false.
  446. read_3d = .false.
  447. constant = .false.
  448. ! set mf_filekey to first part of file name:
  449. select case ( paramkey )
  450. !
  451. case ( 'LNSP' ) ; read_2d=.true.; mdir='spectral' ; fkey='pres.nlog.sfc'; sds_name='pres'
  452. case ( 'VO' ) ; read_3d=.true.; mdir='spectral' ; fkey='vort' ; sds_name='vort'
  453. case ( 'D' ) ; read_3d=.true.; mdir='spectral' ; fkey='div' ; sds_name='div'
  454. case ( 'Tv' ) ; read_3d=.true.; mdir='spectral' ; fkey='vair' ; sds_name='vair'
  455. case ( 'Q' ) ; read_3d=.true.; mdir='spectral' ; fkey='shum' ; sds_name='shum'
  456. case ( 'W' ) ; read_3d=.true.; mdir='pressure' ; fkey='omega' ; sds_name='omega'
  457. !
  458. case ( 'oro' ) ; read_2d=.true.; mdir='surface_gauss'; fkey='hgt.sfc' ; sds_name='hgt' ; constant=.true.
  459. case ( 'lsm' ) ; read_2d=.true.; mdir='surface_gauss'; fkey='land.sfc' ; sds_name='land' ; constant=.true.
  460. case ( 'sr' ) ; read_2d=.true.; mdir='surface_gauss'; fkey='sfcr.sfc' ; sds_name='sfcr'
  461. case ( 'sps' ) ; read_2d=.true.; mdir='surface_gauss'; fkey='pres.sfc' ; sds_name='pres'
  462. case ( 'ci' ) ; read_2d=.true.; mdir='surface_gauss'; fkey='icec.sfc' ; sds_name='icec'
  463. case ( 'skt' ) ; read_2d=.true.; mdir='surface_gauss'; fkey='skt.sfc' ; sds_name='skt'
  464. case ( 'u10m' ) ; read_2d=.true.; mdir='surface_gauss'; fkey='uwnd.10m' ; sds_name='uwnd'
  465. case ( 'v10m' ) ; read_2d=.true.; mdir='surface_gauss'; fkey='vwnd.10m' ; sds_name='vwnd'
  466. case ( 'slhf' ) ; read_2d=.true.; mdir='surface_gauss'; fkey='lhtfl.sfc' ; sds_name='lhtfl'
  467. case ( 'sshf' ) ; read_2d=.true.; mdir='surface_gauss'; fkey='shtfl.sfc' ; sds_name='shtfl'
  468. case ( 'ewss' ) ; read_2d=.true.; mdir='surface_gauss'; fkey='ugwd.sfc' ; sds_name='ugwd'
  469. case ( 'nsss' ) ; read_2d=.true.; mdir='surface_gauss'; fkey='vgwd.sfc' ; sds_name='vgwd'
  470. case ( 'lsp' ) ; read_2d=.true.; mdir='surface_gauss'; fkey='prate.sfc' ; sds_name='prate'
  471. case ( 'cp' ) ; read_2d=.true.; mdir='surface_gauss'; fkey='cprat.sfc' ; sds_name='cprat'
  472. case ( 't2m' ) ; read_2d=.true.; mdir='surface_gauss'; fkey='air.2m' ; sds_name='air'
  473. case ( 'ssr' ) ; read_2d=.true.; mdir='surface_gauss'; fkey='dswrf.sfc' ; sds_name='dswrf'
  474. case ( 'sd' ) ; read_2d=.true.; mdir='surface_gauss'; fkey='weasd.sfc' ; sds_name='weasd'
  475. case ( 'swvl1' ) ; read_2d=.true.; mdir='surface_gauss'; fkey='soilw.0-10cm' ; sds_name='soilw'
  476. !
  477. case default
  478. write (gol,'("unsupported paramkey `",a,"` for ncep 2d files")') paramkey; call goErr
  479. write (gol,'("in ",a)') rname; call goErr; status=1; return
  480. end select
  481. ! time index: number of 6 hour intervals from start of year.
  482. if ( constant ) then
  483. ! index 0 in data sets ...
  484. tstart = 0
  485. else
  486. ! base date:
  487. tbase = NewDate( year=mf%ccyy, month=1, day=1 )
  488. ! last 6 hours of previous year ?
  489. if ( t2 < tbase ) then
  490. ! first record covers (-6,0]
  491. tstart = 0
  492. else
  493. ! number of hours:
  494. hours = nint(rTotal( t2 - tbase, 'hour' ))
  495. ! index = 0, 1, 2, ...
  496. tstart = ceiling( real(hours)/real(6.0) )
  497. end if
  498. end if
  499. !
  500. ! ~~~ 2d field
  501. !
  502. if ( read_2d ) then
  503. ! example file names:
  504. ! pres.nlog.sfc.spec.2000.nc
  505. select case ( mdir )
  506. case ( 'surface_gauss' ) ; gridtype = 'gg' ; gridkey = '.gauss'
  507. case ( 'spectral' ) ; gridtype = 'sh' ; gridkey = '.spec'
  508. case default
  509. write (gol,'("do not know gridtype for mdir : ",a)') trim(mdir); call goErr
  510. write (gol,'("in ",a)') rname; call goErr; status=1; return
  511. end select
  512. ! write filename
  513. if ( constant ) then
  514. write (fname,'(a,a,a,a,a,a,".",a)') &
  515. trim(mf%dir), mf%pathsep, trim(mdir), mf%namesep, trim(fkey), trim(gridkey), 'nc'
  516. else
  517. write (fname,'(a,a,a,a,a,a,".",i4.4,".",a)') &
  518. trim(mf%dir), mf%pathsep, trim(mdir), mf%namesep, trim(fkey), trim(gridkey), mf%ccyy, 'nc'
  519. end if
  520. ! file exist ?
  521. inquire( file=fname, exist=exist )
  522. if ( .not. exist ) then
  523. write (gol,'("file not found:")'); call goErr
  524. write (gol,'(" ",a)') trim(fname); call goErr
  525. write (gol,'("in ",a)') rname; call goErr; status=1; return
  526. end if
  527. ! open file:
  528. call Init( hdf, trim(fname), 'read', status )
  529. IF_NOTOK_RETURN(status=1)
  530. ! check time
  531. if ( constant ) then
  532. tfactor = 1.0
  533. else
  534. call Check_Time( hdf, tstart, t1, t2, tfactor, status )
  535. IF_NOTOK_RETURN(status=1)
  536. end if
  537. ! read 2d field: fill ggi/gg, or shi/sh :
  538. select case ( gridtype )
  539. case ( 'gg' )
  540. call pa_Init( gg1 )
  541. call Read_Gaussian_2d( hdf, sds_name, tstart, ggi, gg1, status )
  542. IF_NOTOK_RETURN(status=1)
  543. call pa_SetShape( gg, ggi%np, 1 )
  544. gg(:,1) = gg1
  545. call pa_Done( gg1 )
  546. ! apply time factor:
  547. gg = gg * tfactor
  548. case ( 'sh' )
  549. call pa_Init( sh1 )
  550. call Read_Spectral_2d( hdf, sds_name, tstart, shi, sh1, status )
  551. IF_NOTOK_RETURN(status=1)
  552. call pa_SetShape( sh, shi%np, 1 )
  553. sh(:,1) = sh1
  554. call pa_Done( sh1 )
  555. ! apply time factor:
  556. sh = sh * tfactor
  557. case default
  558. write (gol,'("unsupported grid type : ",a)') gridtype; call goErr
  559. write (gol,'("in ",a)') rname; call goErr; status=1; return
  560. end select
  561. ! info ...
  562. write (key,'("sh==",i4.4)') shi%T
  563. call AddHistory( tmi, trim(key), status )
  564. ! close file:
  565. call Done( hdf, status )
  566. IF_NOTOK_RETURN(status=1)
  567. ! unit conversion:
  568. select case ( paramkey )
  569. !
  570. ! factor for conversion from cbar to Pa :
  571. ! [Pa] = [cbar] * 1e-2 [bar/cbar] * 1e5 [Pa/bar] = [mbar] * 1e3
  572. ! add to first complex coeff:
  573. ! sp * fac = exp( lnsp + nlog(fac) )
  574. ! = exp( {sum_i=1,n c_i p_i} + nlog(fac) )
  575. ! = exp( c_1 + {sum_i=2,n c_i p_i} + nlog(fac) )
  576. case ( 'LNSP' )
  577. sh(1,1) = sh(1,1) + cmplx(log(1.0e3),0.0)
  578. !
  579. ! ncep oro in in [m], should be [m][g] = [m m/s2]
  580. case ( 'oro' )
  581. gg(:,1) = gg(:,1) * grav
  582. !
  583. ! for some probably historical reaseon, TM expects land/sea mask in % ...
  584. case ( 'lsm' )
  585. gg(:,1) = gg(:,1) * 100.0 ! 0-1 -> %
  586. !
  587. ! adhoc surface roughness
  588. case ( 'sr' )
  589. write (gol,'("WARNING - adhoc constant value for surface roughness ...")'); call goPr
  590. gg(:,1) = 0.001 ! m
  591. !
  592. ! fluxes downward (ecmwf direction) instead of upward (ncep direction)
  593. case ( 'slhf', 'sshf' )
  594. gg(:,1) = - gg(:,1)
  595. !
  596. ! kg water / m2 / s -> m water / s
  597. ! With density of 998 kg water / m3 : kg/m2/s / (kg/m3) = m/s
  598. case ( 'lsp', 'cp' )
  599. gg(:,1) = gg(:,1) / 998.0 ! m water / s
  600. end select
  601. ! dummy levels
  602. call Init( levi, 1, (/0.0,0.0/), (/1.0,0.0/), status )
  603. IF_NOTOK_RETURN(status=1)
  604. end if ! read 2d ?
  605. !
  606. ! ~~~ 3d field
  607. !
  608. if ( read_3d ) then
  609. ! example file names:
  610. !
  611. ! div.spec.2000.nc
  612. ! pres.nlog.sfc.spec.2000.nc
  613. ! vort.spec.2000.nc
  614. select case ( mdir )
  615. case ( 'spectral' ) ; gridtype = 'sh' ; gridkey = '.spec' ; levtype = 'sigma'
  616. case ( 'pressure' ) ; gridtype = 'll' ; gridkey = '' ; levtype = 'pressure'
  617. case default
  618. write (gol,'("do not know grid- and levtype for mdir : ",a)') trim(mdir); call goErr
  619. write (gol,'("in ",a)') rname; call goErr; status=1; return
  620. end select
  621. ! write filename
  622. write (fname,'(a,a,a,a,a,a,".",i4.4,".",a)') &
  623. trim(mf%dir), mf%pathsep, trim(mdir), mf%namesep, trim(fkey), trim(gridkey), mf%ccyy, 'nc'
  624. ! file exist ?
  625. inquire( file=fname, exist=exist )
  626. if ( .not. exist ) then
  627. write (gol,'("file not found:")'); call goErr
  628. write (gol,'(" ",a)') trim(fname); call goErr
  629. write (gol,'("in ",a)') rname; call goErr; status=1; return
  630. end if
  631. ! open file:
  632. call Init( hdf, trim(fname), 'read', status )
  633. IF_NOTOK_RETURN(status=1)
  634. ! check time
  635. if ( .not. constant ) then
  636. call Check_Time( hdf, tstart, t1, t2, tfactor, status )
  637. IF_NOTOK_RETURN(status=1)
  638. end if
  639. ! extract level stuff:
  640. select case ( levtype )
  641. !
  642. case ( 'sigma' )
  643. ! open level data set:
  644. call Init( sds, hdf, 'level', status )
  645. IF_NOTOK_RETURN(status=1)
  646. ! extract dimensions:
  647. call GetInfo( sds, status, data_dims=data_dims )
  648. IF_NOTOK_RETURN(status=1)
  649. nlev = data_dims(1)
  650. !call ReadData( sds, sigma, status )
  651. !IF_NOTOK_RETURN(status=1)
  652. call Done( sds, status )
  653. IF_NOTOK_RETURN(status=1)
  654. ! level defintion
  655. select case ( nlev )
  656. case ( 28 )
  657. call Init( levi, 'nc28', status )
  658. IF_NOTOK_RETURN(status=1)
  659. case default
  660. write (gol,'("level definition not supported for nlev ",i4)') nlev; call goErr
  661. write (gol,'("in ",a)') rname; call goErr; status=1; return
  662. end select
  663. !
  664. case ( 'pressure' )
  665. ! open level data set:
  666. call Init( sds, hdf, 'level', status )
  667. IF_NOTOK_RETURN(status=1)
  668. ! extract dimensions:
  669. call GetInfo( sds, status, data_dims=data_dims )
  670. IF_NOTOK_RETURN(status=1)
  671. nlev = data_dims(1)
  672. ! read pressure levels:
  673. allocate( levels(nlev) )
  674. call ReadData( sds, levels, status )
  675. IF_NOTOK_RETURN(status=1)
  676. ! close data set:
  677. call Done( sds, status )
  678. IF_NOTOK_RETURN(status=1)
  679. ! level defintion
  680. write (gol,'("WARNING - adhoc implementation of pressure levels!")'); call goPr
  681. call Init( levi, nlev, (/levels,0.0/), (/levels*0.0,0.0/), status )
  682. IF_NOTOK_RETURN(status=1)
  683. ! clear
  684. deallocate( levels )
  685. !
  686. case default
  687. write (gol,'("level type not supported :",a)') levtype; call goErr
  688. write (gol,'("in ",a)') rname; call goErr; status=1; return
  689. end select
  690. ! info ...
  691. write (key,'("nlev==",i3.3)') nlev
  692. call AddHistory( tmi, trim(key), status )
  693. ! read 3d field: fill lli/ll, ggi/gg, or shi/sh
  694. select case ( gridtype )
  695. case ( 'll' )
  696. call Read_LonLat_3d( hdf, sds_name, tstart, nlev, nw, lli, ll, status )
  697. IF_NOTOK_RETURN(status=1)
  698. ! apply time factor:
  699. ll = ll * tfactor
  700. case ( 'sh' )
  701. call Read_Spectral_3d( hdf, sds_name, tstart, nlev, shi, sh, status )
  702. IF_NOTOK_RETURN(status=1)
  703. ! apply time factor:
  704. sh = sh * tfactor
  705. case default
  706. write (gol,'("unsupported grid type : ",a)') gridtype; call goErr
  707. write (gol,'("in ",a)') rname; call goErr; status=1; return
  708. end select
  709. ! info ...
  710. write (key,'("sh==",i4.4)') shT
  711. call AddHistory( tmi, trim(key), status )
  712. ! close file:
  713. call Done( hdf, status )
  714. IF_NOTOK_RETURN(status=1)
  715. ! unit conversion:
  716. select case ( paramkey )
  717. ! For some reason, the u/v/w from VO/D needs a factor -1 ...
  718. ! The minus is probably caused by the upwards coordinate system of ncep
  719. ! instead of the downward from ecmwf.
  720. case ( 'VO', 'D' )
  721. sh = - sh
  722. end select
  723. !
  724. ! ~~~ surface pressure
  725. !
  726. ! name of ncep file and data set:
  727. mdir = 'spectral'
  728. fkey = 'pres.nlog.sfc' ; sds_name = 'pres'
  729. ! write surface pressure filename
  730. write (fname,'(a,"/",a,"-",a,a,".",i4.4,".",a)') &
  731. trim(mf%dir), trim(mdir), trim(fkey), '.spec', mf%ccyy, 'nc'
  732. ! file exist ?
  733. inquire( file=fname, exist=exist )
  734. if ( .not. exist ) then
  735. write (gol,'("file not found:")'); call goErr
  736. write (gol,'(" ",a)') trim(fname); call goErr
  737. write (gol,'("in ",a)') rname; call goErr; status=1; return
  738. end if
  739. ! open file:
  740. call Init( hdf, trim(fname), 'read', status )
  741. IF_NOTOK_RETURN(status=1)
  742. ! check time
  743. call Check_Time( hdf, tstart, t1, t2, tfactor, status )
  744. IF_NOTOK_RETURN(status=1)
  745. ! read spectral field
  746. call Read_Spectral_2d( hdf, sds_name, tstart, shi, lnsp_sh, status )
  747. IF_NOTOK_RETURN(status=1)
  748. ! lnsp never accumulated, thus no time factor ...
  749. ! close file:
  750. call Done( hdf, status )
  751. IF_NOTOK_RETURN(status=1)
  752. ! unit conversion:
  753. ! sp * fac = exp( lnsp + nlog(fac) )
  754. ! = exp( {sum_i=1,n c_i p_i} + nlog(fac) )
  755. ! = exp( c_1 + {sum_i=2,n c_i p_i} + nlog(fac) )
  756. ! factor for conversion from cbar to Pa :
  757. ! [Pa] = [cbar] * 1e-2 [bar/cbar] * 1e5 [Pa/bar] = [mbar] * 1e3
  758. lnsp_sh(1) = lnsp_sh(1) + cmplx(log(1.0e3),0.0)
  759. end if ! read 3d ?
  760. !
  761. ! ~~~ end
  762. !
  763. ! ok
  764. status = 0
  765. end subroutine mf_ReadRecord_1
  766. ! ***
  767. subroutine Check_Time( hdf, tstart, t1, t2, tfactor, status )
  768. use file_hdf , only : THdfFile, TSds, Init, Done, ReadAttribute, ReadData
  769. use GO , only : TDate, NewDate, IncrDate, wrtgol
  770. use GO , only : operator(+), operator(-), rTotal
  771. use GO , only :operator(/=), operator(==), operator(>=), operator(<=)
  772. ! --- in/out ---------------------------------------------
  773. type(THdfFile), intent(inout) :: hdf
  774. integer, intent(in) :: tstart
  775. type(TDate), intent(in) :: t1, t2
  776. real, intent(out) :: tfactor
  777. integer, intent(out) :: status
  778. ! --- const --------------------------------------
  779. character(len=*), parameter :: rname = mname//'/Check_Time'
  780. ! --- local ----------------------------------------------
  781. type(TSds) :: sds
  782. integer :: base_date(3)
  783. real(8) :: time1(1), time(1), dhour
  784. integer :: idh
  785. type(TDate) :: tbase
  786. type(TDate) :: trec
  787. character(len=32) :: avg_period
  788. integer :: avg_dhour
  789. ! --- begin ----------------------------------------------
  790. ! o read start date:
  791. call ReadAttribute( hdf, 'base_date', base_date, status )
  792. IF_NOTOK_RETURN(status=1)
  793. tbase = NewDate( year=base_date(1), month=base_date(2), day=base_date(3) )
  794. ! init time dataset:
  795. call Init( sds, hdf, 'time', status )
  796. IF_NOTOK_RETURN(status=1)
  797. ! read hour offsets:
  798. call ReadData( sds, time1, status, start=(/0/) )
  799. if (status/=0) then
  800. write (gol,'("reading time value for start=0")'); call goErr
  801. write (gol,'("in ",a)') rname; call goErr; status=1; return
  802. end if
  803. call ReadData( sds, time, status, start=(/tstart/) )
  804. if (status/=0) then
  805. write (gol,'("reading time value for start=",i6)') tstart; call goErr
  806. call wrtgol( ' base_date : ', tbase ); call goErr
  807. call wrtgol( ' t1 : ', t1 ); call goErr
  808. call wrtgol( ' t2 : ', t2 ); call goErr
  809. write (gol,'(" file name : ",a)') trim(hdf%fname); call goErr
  810. write (gol,'("in ",a)') rname; call goErr; status=1; return
  811. end if
  812. ! record time :
  813. dhour = time(1) - time1(1)
  814. trec = tbase + IncrDate( hour=floor(dhour), min=int((dhour-floor(dhour))*60.0) )
  815. ! by default, no time factor needs to applied:
  816. tfactor = 1.0
  817. ! instant field or time average ?
  818. if ( t1 == t2 ) then
  819. ! instant time; check: trec == t1==t2 ?
  820. if ( trec /= t1 ) then
  821. write (gol,'("time of supposed record does not match with requested time:")'); call goErr
  822. write (gol,'(" index : ",i6)') tstart; call goErr
  823. write (gol,'(" base_time : ",i4,2i3.2)') base_date; call goErr
  824. call wrtgol( ' record time : ', trec ); call goErr
  825. call wrtgol( ' t1 : ', t1 ); call goErr
  826. call wrtgol( ' t2 : ', t2 ); call goErr
  827. write (gol,'("in ",a)') rname; call goErr; status=1; return
  828. end if
  829. else if ( t1 <= t2 ) then
  830. ! interval; check : [t1,t2] in [trec-6,trec] ?
  831. ! identify averaging period:
  832. call ReadAttribute( sds, 'avg_period', avg_period, status )
  833. if (status/=0) then
  834. write (gol,'("reading avg_period; time inteval requested while not time average fields ?")'); call goErr
  835. write (gol,'("in ",a)') rname; call goErr; status=1; return
  836. end if
  837. select case ( avg_period )
  838. case ( '0000-00-00 06:00:00' ) ; avg_dhour = 6
  839. case default
  840. write (gol,'("unsupported avg_period : ",a)') trim(avg_period); call goErr
  841. write (gol,'("in ",a)') rname; call goErr; status=1; return
  842. end select
  843. ! check:
  844. if ( (t1 >= trec-IncrDate(hour=avg_dhour)) .and. (t2 <= trec) ) then
  845. ! ok, compute fraction:
  846. idh = nint(rTotal( t2 - t1, 'hour' ))
  847. tfactor = real(idh)/real(avg_dhour)
  848. else
  849. write (gol,'("time of supposed record does not match with requested time:")'); call goErr
  850. write (gol,'(" index : ",i6)') tstart; call goErr
  851. write (gol,'(" base_time : ",i4,2i3.2)') base_date; call goErr
  852. call wrtgol( ' record time : ', trec ); call goErr
  853. write (gol,'(" avg_period : ",a)') trim(avg_period); call goErr
  854. call wrtgol( ' t1 : ', t1 ); call goErr
  855. call wrtgol( ' t2 : ', t2 ); call goErr
  856. write (gol,'("in ",a)') rname; call goErr; status=1; return
  857. end if
  858. else
  859. write (gol,'("times should be the same or interval [t1,t2] : ")'); call goErr
  860. call wrtgol( ' t1 : ', t1 ); call goErr
  861. call wrtgol( ' t2 : ', t2 ); call goErr
  862. write (gol,'("in ",a)') rname; call goErr; status=1; return
  863. end if ! instant or interval
  864. ! ok
  865. status = 0
  866. end subroutine Check_Time
  867. ! ***
  868. subroutine Read_Spectral_2d( hdf, sds_name, tstart, shi, sh, status )
  869. use parray , only : pa_SetShape
  870. use file_hdf, only : THdfFile, TSds, Init, Done, ReadAttribute, ReadData
  871. use Grid , only : TshGridInfo, Init
  872. ! --- in/out -------------------------------------
  873. type(THdfFile), intent(inout) :: hdf
  874. character(len=*), intent(in) :: sds_name
  875. integer, intent(in) :: tstart
  876. type(TShGridInfo), intent(out) :: shi
  877. complex, pointer :: sh(:)
  878. integer, intent(out) :: status
  879. ! --- const --------------------------------------
  880. character(len=*), parameter :: rname = mname//'/Read_Spectral_2d'
  881. ! --- local -------------------------------
  882. type(TSds) :: sds
  883. character(len=1) :: compression_used
  884. real :: meanr(2,1)
  885. real :: add_offset(1)
  886. real :: scale_factor(1)
  887. integer :: trunc_count
  888. ! some cdc nc files contain a float for the packed data ...
  889. real, allocatable :: idata(:,:)
  890. ! --- begin ---------------------------------
  891. ! mean = first complex coeff
  892. call Init( sds, hdf, 'mean', status )
  893. IF_NOTOK_RETURN(status=1)
  894. call ReadData( sds, meanr, status, start=(/0,tstart/) )
  895. IF_NOTOK_RETURN(status=1)
  896. call Done( sds, status )
  897. IF_NOTOK_RETURN(status=1)
  898. ! packed ?
  899. call ReadAttribute( hdf, 'compression_used', compression_used, status )
  900. IF_NOTOK_RETURN(status=1)
  901. ! only packed yet ...
  902. if ( scan(compression_used,'Tt') == 0 ) then
  903. write (gol,'("only packed ncep data supported yet ...")'); call goErr
  904. write (gol,'("in ",a)') rname; call goErr; status=1; return
  905. end if
  906. ! read packing offset:
  907. call Init( sds, hdf, 'add_offset', status )
  908. IF_NOTOK_RETURN(status=1)
  909. call ReadData( sds, add_offset, status, start=(/tstart/) )
  910. IF_NOTOK_RETURN(status=1)
  911. call Done( sds, status )
  912. IF_NOTOK_RETURN(status=1)
  913. ! read packing factor:
  914. call Init( sds, hdf, 'scale_factor', status )
  915. IF_NOTOK_RETURN(status=1)
  916. call ReadData( sds, scale_factor, status, start=(/tstart/) )
  917. IF_NOTOK_RETURN(status=1)
  918. call Done( sds, status )
  919. IF_NOTOK_RETURN(status=1)
  920. ! open actual data set:
  921. call Init( sds, hdf, sds_name, status )
  922. IF_NOTOK_RETURN(status=1)
  923. ! read spectral truncation:
  924. call ReadAttribute( sds, 'trunc_count', trunc_count, status )
  925. IF_NOTOK_RETURN(status=1)
  926. ! setup output spectral definition:
  927. call Init( shi, trunc_count, status )
  928. IF_NOTOK_RETURN(status=1)
  929. ! data array:
  930. allocate( idata(shi%np*2,1) )
  931. ! read data:
  932. call ReadData( sds, idata, status, start=(/0,tstart/) )
  933. IF_NOTOK_RETURN(status=1)
  934. ! close data set:
  935. call Done( sds, status )
  936. IF_NOTOK_RETURN(status=1)
  937. ! setup output grid:
  938. call pa_SetShape( sh, shi%np )
  939. ! unpack and transform from realreal to complex:
  940. sh = transfer( ( idata(:,1) * scale_factor(1) ) + add_offset(1) , sh )
  941. ! add mean to first coeff:
  942. select case ( sds_name )
  943. case ( 'orog' )
  944. ! for some reason, adding the mean messes gives a bias in orography ..
  945. case default
  946. sh(1) = sh(1) + cmplx(meanr(1,1),meanr(2,1))
  947. end select
  948. ! convert from NCEP spectral coeff to ECMWF spectral coeff:
  949. sh = sh / sqrt(2.0)
  950. ! clear
  951. deallocate( idata )
  952. ! ok
  953. status = 0
  954. end subroutine Read_Spectral_2d
  955. ! ***
  956. subroutine Read_Spectral_3d( hdf, sds_name, tstart, nlev, shi, sh, status )
  957. use parray , only : pa_SetShape
  958. use file_hdf, only : THdfFile, TSds, Init, Done, ReadAttribute, ReadData
  959. use grid , only : TshGridInfo, Init
  960. ! --- in/out -------------------------------------
  961. type(THdfFile), intent(inout) :: hdf
  962. character(len=*), intent(in) :: sds_name
  963. integer, intent(in) :: tstart
  964. integer, intent(in) :: nlev
  965. type(TShGridInfo), intent(out) :: shi
  966. complex, pointer :: sh(:,:)
  967. integer, intent(out) :: status
  968. ! --- const --------------------------------------
  969. character(len=*), parameter :: rname = mname//'/Read_Spectral_3d'
  970. ! --- local -------------------------------
  971. integer :: ilev
  972. type(TSds) :: sds
  973. character(len=1) :: compression_used
  974. real :: meanr(nlev*2,1)
  975. real :: add_offset(nlev,1)
  976. real :: scale_factor(nlev,1)
  977. integer, allocatable :: idata(:,:,:)
  978. integer :: trunc_count
  979. ! --- begin ---------------------------------
  980. ! mean = first complex coeff
  981. call Init( sds, hdf, 'mean', status )
  982. IF_NOTOK_RETURN(status=1)
  983. call ReadData( sds, meanr, status, start=(/0,tstart/) )
  984. IF_NOTOK_RETURN(status=1)
  985. call Done( sds, status )
  986. IF_NOTOK_RETURN(status=1)
  987. ! packed ?
  988. call ReadAttribute( hdf, 'compression_used', compression_used, status )
  989. IF_NOTOK_RETURN(status=1)
  990. ! only packed yet ...
  991. if ( scan(compression_used,'Tt') == 0 ) then
  992. write (gol,'("only packed ncep data supported yet ...")'); call goErr
  993. write (gol,'("in ",a)') rname; call goErr; status=1; return
  994. end if
  995. ! read packing offset:
  996. call Init( sds, hdf, 'add_offset', status )
  997. IF_NOTOK_RETURN(status=1)
  998. call ReadData( sds, add_offset, status, start=(/0,tstart/) )
  999. IF_NOTOK_RETURN(status=1)
  1000. call Done( sds, status )
  1001. IF_NOTOK_RETURN(status=1)
  1002. ! read packing factor:
  1003. call Init( sds, hdf, 'scale_factor', status )
  1004. IF_NOTOK_RETURN(status=1)
  1005. call ReadData( sds, scale_factor, status, start=(/0,tstart/) )
  1006. IF_NOTOK_RETURN(status=1)
  1007. call Done( sds, status )
  1008. IF_NOTOK_RETURN(status=1)
  1009. ! open actual data set:
  1010. call Init( sds, hdf, sds_name, status )
  1011. IF_NOTOK_RETURN(status=1)
  1012. ! read spectral truncation:
  1013. call ReadAttribute( sds, 'trunc_count', trunc_count, status )
  1014. IF_NOTOK_RETURN(status=1)
  1015. ! setup output spectral definition:
  1016. call Init( shi, trunc_count, status )
  1017. IF_NOTOK_RETURN(status=1)
  1018. ! data array:
  1019. allocate( idata(shi%np*2,nlev,1) )
  1020. ! read data:
  1021. call ReadData( sds, idata, status, start=(/0,0,tstart/) )
  1022. IF_NOTOK_RETURN(status=1)
  1023. ! close data set:
  1024. call Done( sds, status )
  1025. IF_NOTOK_RETURN(status=1)
  1026. ! setup output grid:
  1027. call pa_SetShape( sh, shi%np, nlev )
  1028. ! unpack and transform from realreal to complex:
  1029. do ilev = 1, nlev
  1030. sh(:,ilev) = transfer( ( idata(:,ilev,1) * scale_factor(ilev,1) ) + add_offset(ilev,1) , sh(:,ilev) )
  1031. end do
  1032. ! add mean to first coeff:
  1033. do ilev = 1, nlev
  1034. sh(1,ilev) = sh(1,ilev) + cmplx(meanr((ilev-1)*2+1,1),meanr((ilev-1)*2+2,1))
  1035. end do
  1036. ! convert from NCEP spectral coeff to ECMWF spectral coeff:
  1037. sh = sh / sqrt(2.0)
  1038. ! clear
  1039. deallocate( idata )
  1040. ! ok
  1041. status = 0
  1042. end subroutine Read_Spectral_3d
  1043. ! ***
  1044. subroutine Read_Gaussian_2d( hdf, sds_name, tstart, ggi, gg, status )
  1045. use parray , only : pa_SetShape
  1046. use file_hdf, only : THdfFile, TSds, Init, Done, ReadAttribute, ReadData, GetInfo
  1047. use Grid , only : TggGridInfo, Init
  1048. ! --- in/out -------------------------------------
  1049. type(THdfFile), intent(inout) :: hdf
  1050. character(len=*), intent(in) :: sds_name
  1051. integer, intent(in) :: tstart
  1052. type(TggGridInfo), intent(out) :: ggi
  1053. real, pointer :: gg(:)
  1054. integer, intent(out) :: status
  1055. ! --- const --------------------------------------
  1056. character(len=*), parameter :: rname = mname//'/Read_Gaussian_2d'
  1057. ! --- local -------------------------------
  1058. type(TSds) :: sds
  1059. integer :: data_dims(3)
  1060. real :: add_offset
  1061. real :: scale_factor
  1062. integer, allocatable :: idata(:,:,:)
  1063. ! --- begin ---------------------------------
  1064. ! open actual data set:
  1065. call Init( sds, hdf, sds_name, status )
  1066. IF_NOTOK_RETURN(status=1)
  1067. ! extract grid size:
  1068. call GetInfo( sds, status, data_dims=data_dims )
  1069. IF_NOTOK_RETURN(status=1)
  1070. ! setup grid definition:
  1071. call Init( ggi, data_dims(2)/2, .false., status )
  1072. IF_NOTOK_RETURN(status=1)
  1073. ! data array:
  1074. allocate( idata(data_dims(1),data_dims(2),1) )
  1075. ! read packing:
  1076. call ReadAttribute( sds, 'add_offset', add_offset, status )
  1077. IF_NOTOK_RETURN(status=1)
  1078. call ReadAttribute( sds, 'scale_factor', scale_factor, status )
  1079. IF_NOTOK_RETURN(status=1)
  1080. ! read data:
  1081. call ReadData( sds, idata, status, start=(/0,0,tstart/) )
  1082. IF_NOTOK_RETURN(status=1)
  1083. ! close data set:
  1084. call Done( sds, status )
  1085. IF_NOTOK_RETURN(status=1)
  1086. ! setup output grid:
  1087. call pa_SetShape( gg, ggi%np )
  1088. ! unpack and transform from rank2 to rank1 :
  1089. gg = transfer( ( idata(:,:,1) * scale_factor ) + add_offset , gg )
  1090. ! clear
  1091. deallocate( idata )
  1092. ! ok
  1093. status = 0
  1094. end subroutine Read_Gaussian_2d
  1095. ! ***
  1096. subroutine Read_LonLat_3d( hdf, sds_name, tstart, nlev, nw, lli, ll, status )
  1097. use parray , only : pa_SetShape
  1098. use file_hdf, only : THdfFile, TSds, Init, Done, ReadAttribute, ReadData, GetInfo
  1099. use grid , only : TllGridInfo, Init
  1100. ! --- in/out -------------------------------------
  1101. type(THdfFile), intent(inout) :: hdf
  1102. character(len=*), intent(in) :: sds_name
  1103. integer, intent(in) :: tstart
  1104. integer, intent(in) :: nlev
  1105. character(len=*), intent(in) :: nw
  1106. type(TllGridInfo), intent(out) :: lli
  1107. real, pointer :: ll(:,:,:)
  1108. integer, intent(out) :: status
  1109. ! --- const --------------------------------------
  1110. character(len=*), parameter :: rname = mname//'/Read_LonLat_3d'
  1111. ! --- local -------------------------------
  1112. integer :: j
  1113. type(TSds) :: sds
  1114. integer :: data_dims(4)
  1115. real :: add_offset
  1116. real :: scale_factor
  1117. integer, allocatable :: idata(:,:,:,:)
  1118. ! --- begin ---------------------------------
  1119. ! open data set:
  1120. call Init( sds, hdf, sds_name, status )
  1121. IF_NOTOK_RETURN(status=1)
  1122. ! extract grid size:
  1123. call GetInfo( sds, status, data_dims=data_dims )
  1124. IF_NOTOK_RETURN(status=1)
  1125. ! setup grid definition:
  1126. call Init( lli, 0.0, 360.0/ data_dims(1) , data_dims(1), &
  1127. -90.0, 180.0/(data_dims(2)-1), data_dims(2), status )
  1128. IF_NOTOK_RETURN(status=1)
  1129. ! data array:
  1130. allocate( idata(data_dims(1),data_dims(2),nlev,1) )
  1131. ! read packing:
  1132. call ReadAttribute( sds, 'add_offset', add_offset, status )
  1133. IF_NOTOK_RETURN(status=1)
  1134. call ReadAttribute( sds, 'scale_factor', scale_factor, status )
  1135. IF_NOTOK_RETURN(status=1)
  1136. ! read data:
  1137. call ReadData( sds, idata, status, start=(/0,0,0,tstart/) )
  1138. IF_NOTOK_RETURN(status=1)
  1139. ! close data set:
  1140. call Done( sds, status )
  1141. IF_NOTOK_RETURN(status=1)
  1142. ! setup output grid:
  1143. select case ( nw )
  1144. case ( 'n' )
  1145. call pa_SetShape( ll, lli%nlon, lli%nlat, nlev )
  1146. case ( 'w' )
  1147. call pa_SetShape( ll, lli%nlon, lli%nlat, nlev+1 )
  1148. case default
  1149. write (gol,'("unsupported nw : ",a)') nw; call goErr
  1150. write (gol,'("in ",a)') rname; call goErr; status=1; return
  1151. end select
  1152. ! initial zero:
  1153. ll = 0.0
  1154. ! unpack, and transform from north->south to south->north:
  1155. do j = 1, lli%nlat
  1156. ll(:,j,1:nlev) = real( ( idata(:,lli%nlat+1-j,:,1) * scale_factor ) + add_offset )
  1157. end do
  1158. ! clear
  1159. deallocate( idata )
  1160. ! ok
  1161. status = 0
  1162. end subroutine Read_LonLat_3d
  1163. end module tmm_mf_ncep_cdc
  1164. !program test
  1165. !
  1166. ! use file_hdf
  1167. ! use grid
  1168. !
  1169. ! ! --- const ---------------------------
  1170. !
  1171. ! integer, parameter :: T = 62
  1172. !
  1173. ! character(len=*), parameter :: fdir = '/misc/p71/co2/ncep.reanalysis/spectral/'
  1174. !
  1175. ! ! --- local ----------------------------------
  1176. !
  1177. ! type(THdfFile) :: nc, hdf
  1178. ! type(TSds) :: sds
  1179. ! integer :: status
  1180. !
  1181. ! real, allocatable :: rr(:)
  1182. ! real :: mean(2,1)
  1183. ! real :: add_offset(1)
  1184. ! real :: scale_factor(1)
  1185. ! real, allocatable :: idata(:,:)
  1186. !
  1187. ! type(TshGridInfo) :: shi
  1188. ! complex, allocatable :: cc(:)
  1189. ! type(TshGrid) :: shc
  1190. !
  1191. ! integer :: tstart
  1192. !
  1193. ! type(TllGridInfo) :: lli
  1194. ! real :: ll(120,90)
  1195. !
  1196. ! ! --- begin ------------------------------------
  1197. !
  1198. ! print *, ''
  1199. ! print *, 'test: start'
  1200. !
  1201. ! call Init( shi, T, status )
  1202. ! if (status/=0) stop 'error'
  1203. !
  1204. ! allocate( cc(shi%np) )
  1205. !
  1206. ! allocate( idata(shi%np*2,1) )
  1207. ! allocate( rr(shi%np*2) )
  1208. !
  1209. ! !
  1210. ! ! time
  1211. ! !
  1212. !
  1213. ! tstart = 0
  1214. !
  1215. ! !
  1216. ! ! read
  1217. ! !
  1218. !
  1219. ! call Init( nc, fdir//'pres.nlog.sfc.spec.2000.nc', 'read', status )
  1220. ! if (status/=0) stop 'error'
  1221. !
  1222. ! call Init( sds, nc, 'mean', status )
  1223. ! if (status/=0) stop 'error'
  1224. ! call ReadData( sds, mean, status, start=(/0,tstart/) )
  1225. ! if (status/=0) stop 'error'
  1226. ! call Done( sds, status )
  1227. ! if (status/=0) stop 'error'
  1228. !
  1229. ! call Init( sds, nc, 'add_offset', status )
  1230. ! if (status/=0) stop 'error'
  1231. ! call ReadData( sds, add_offset, status, start=(/tstart/) )
  1232. ! if (status/=0) stop 'error'
  1233. ! call Done( sds, status )
  1234. ! if (status/=0) stop 'error'
  1235. !
  1236. ! call Init( sds, nc, 'scale_factor', status )
  1237. ! if (status/=0) stop 'error'
  1238. ! call ReadData( sds, scale_factor, status, start=(/tstart/) )
  1239. ! if (status/=0) stop 'error'
  1240. ! call Done( sds, status )
  1241. ! if (status/=0) stop 'error'
  1242. !
  1243. ! call Init( sds, nc, 'pres', status )
  1244. ! if (status/=0) stop 'error'
  1245. ! call ReadData( sds, idata, status, start=(/0,tstart/) )
  1246. ! if (status/=0) stop 'error'
  1247. ! call Done( sds, status )
  1248. ! if (status/=0) stop 'error'
  1249. !
  1250. ! call Done( nc, status )
  1251. ! if (status/=0) stop 'error'
  1252. !
  1253. ! !
  1254. ! ! sh grid
  1255. ! !
  1256. !
  1257. ! ! From http://www.cdc.noaa.gov/PublicData/faq.html#12 :
  1258. ! !
  1259. ! ! Most of the data in our netCDF files are packed. That is to say they have been
  1260. ! ! transformed by a scale factor and an add offset to reduce the storage needed to
  1261. ! ! two bytes per value. When you extract the short integers, you must unpack the
  1262. ! ! data to recover the correct floating point data values. Data files that contain
  1263. ! ! packed data will have a non-zero add offset and/or a scale factor not equal to 1.
  1264. ! !
  1265. ! ! The transformation is:
  1266. ! ! float_value = (short_value * scale_factor) + add_offset
  1267. ! !
  1268. !
  1269. ! print *, mean(1,1)
  1270. ! print *, add_offset
  1271. ! print *, scale_factor
  1272. ! print *, sum(idata)/size(idata)
  1273. !
  1274. ! rr = ( idata(:,1) * scale_factor(1) ) + add_offset(1)
  1275. !
  1276. ! print *, minval(rr), maxval(rr)
  1277. ! print *, rr(1), exp(rr(1))
  1278. !
  1279. ! ! convert to complex coeff:
  1280. ! cc = transfer( rr, cc )
  1281. !
  1282. ! ! convert from NOAA spectral coeff to ECMWF spectral coeff:
  1283. ! cc = cc / sqrt(2.0)
  1284. !
  1285. ! !
  1286. ! ! convert units from nlog(bar) to nlog(Pa)
  1287. ! ! 1 bar = 1e5 Pa
  1288. ! ! sp_Pa = exp( sp_nlog_cbar ) * 1e5
  1289. ! ! = exp( sp_nlog_cbar + nlog(1e5) )
  1290. ! ! = exp( sum cnm pnm + nlog(1e5) )
  1291. ! !
  1292. ! ! add conversion offset to real part first complex coeff,
  1293. ! ! which represent the first global constant mode of lnsp :
  1294. ! cc(1) = cc(1) + cmplx(log(1.0e5),0.0)
  1295. !
  1296. ! call Init( shc )
  1297. ! call Set( shc, T, cc )
  1298. !
  1299. ! !
  1300. ! ! interpol
  1301. ! !
  1302. !
  1303. ! call Init( lli, -180.0+3.0/2, 3.0, 120, -90.0+2.0/2, 2.0, 90, status )
  1304. ! if (status/=0) stop 'error'
  1305. !
  1306. ! call Interpol( shc, lli, ll )
  1307. !
  1308. ! call Done( lli, status )
  1309. ! if (status/=0) stop 'error'
  1310. !
  1311. ! !
  1312. ! ! dump
  1313. ! !
  1314. !
  1315. ! call Init( hdf, 'lnsp.hdf', 'create', status )
  1316. ! if (status/=0) stop 'error'
  1317. ! call Init( sds, hdf, 'lnsp', shape(ll), 'real(4)', status )
  1318. ! if (status/=0) stop 'error'
  1319. ! call WriteData( sds, ll, status )
  1320. ! if (status/=0) stop 'error'
  1321. ! call Done( sds, status )
  1322. ! if (status/=0) stop 'error'
  1323. ! call Done( hdf, status )
  1324. ! if (status/=0) stop 'error'
  1325. !
  1326. ! !
  1327. ! ! done
  1328. ! !
  1329. !
  1330. ! deallocate( rr )
  1331. ! deallocate( idata )
  1332. !
  1333. ! deallocate( cc )
  1334. ! call Done( shc )
  1335. ! call Done( shi )
  1336. !
  1337. ! print *, 'test: end'
  1338. ! print *, ''
  1339. !
  1340. !end program test