file_ncb.F90 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. !
  2. ! Interface to NCEP Cray Binary file
  3. !
  4. module file_ncb
  5. implicit none
  6. ! --- in/out ----------------------------------------------
  7. private
  8. public :: TNcepCrayBin
  9. public :: Init, Done
  10. public :: ReadRecord
  11. ! --- const -----------------------------------------------
  12. character(len=*), parameter :: mname = 'file_ncb'
  13. ! data kinds
  14. integer, parameter :: ncb_ikind = 4
  15. integer, parameter :: ncb_rkind = 4
  16. ! header length (chars)
  17. integer, parameter :: ncb_lhead = 32
  18. ! length of rec2 in 4-bytes real:
  19. integer, parameter :: lrec2 = 250
  20. ! max levels
  21. integer, parameter :: maxlev = 100
  22. ! --- types --------------------------------------------
  23. type TNcepCrayBin
  24. ! file unit and name:
  25. integer :: fu
  26. character(len=256) :: fname
  27. ! header
  28. character(len=ncb_lhead) :: head
  29. ! time etc
  30. integer :: fcst_hr
  31. integer :: idate(4)
  32. ! levels
  33. integer :: nlev
  34. real, pointer :: sigma_half(:)
  35. real, pointer :: sigma_full(:)
  36. ! spectral fields:
  37. integer :: shT, shn
  38. end type TNcepCrayBin
  39. ! --- interfaces ----------------------------------------
  40. interface Init
  41. module procedure ncb_Init
  42. end interface
  43. interface Done
  44. module procedure ncb_Done
  45. end interface
  46. interface ReadRecord
  47. module procedure ncb_ReadRecord_2d
  48. module procedure ncb_ReadRecord_3d
  49. end interface
  50. contains
  51. ! =======================================================================
  52. subroutine ncb_Init( ncb, fname, status )
  53. ! --- in/out ----------------------------------------
  54. type(TNcepCrayBin), intent(out) :: ncb
  55. character(len=*), intent(in) :: fname
  56. integer, intent(out) :: status
  57. ! --- const ------------------------------------------
  58. character(len=*), parameter :: rname = mname//'/ncb_Init'
  59. ! --- local ------------------------------------------
  60. logical :: exist, opened
  61. integer :: i, sig0, ext0
  62. integer(ncb_ikind) :: idum
  63. real(ncb_rkind) :: rec2(lrec2)
  64. ! --- begin ------------------------------------------
  65. ! store file name:
  66. ncb%fname = fname
  67. ! file exist ?
  68. inquire( file=trim(ncb%fname), exist=exist )
  69. if ( .not. exist ) then
  70. write (*,'("ERROR - file not found :")')
  71. write (*,'("ERROR - ",a)') trim(ncb%fname)
  72. write (*,'("ERROR in ",a)') rname; status=1; return
  73. end if
  74. ! select free file unit:
  75. ncb%fu = 1234
  76. do
  77. inquire( unit=ncb%fu, opened=opened )
  78. if ( .not. opened ) exit
  79. ncb%fu = ncb%fu + 1
  80. end do
  81. ! open file:
  82. #ifdef ifort
  83. open( ncb%fu, file=trim(ncb%fname), status='old', action='read', &
  84. form='unformatted', convert='big_endian', iostat=status )
  85. #else
  86. open( ncb%fu, file=trim(ncb%fname), status='old', action='read', &
  87. form='unformatted', iostat=status )
  88. #endif
  89. if ( status /= 0 ) then
  90. write (*,'("ERROR - opening file :")')
  91. write (*,'("ERROR - ",a)') trim(ncb%fname)
  92. write (*,'("ERROR in ",a)') rname; status=1; return
  93. end if
  94. ! read header:
  95. read (ncb%fu,iostat=status) ncb%head
  96. if ( status /= 0 ) then
  97. write (*,'("ERROR - reading header from file :")')
  98. write (*,'("ERROR - ",a)') trim(ncb%fname)
  99. write (*,'("ERROR in ",a)') rname; status=1; return
  100. end if
  101. ! read record 2:
  102. read (ncb%fu,iostat=status) rec2
  103. if ( status /= 0 ) then
  104. write (*,'("ERROR - reading record 2 from file :")')
  105. write (*,'("ERROR - ",a)') trim(ncb%fname)
  106. write (*,'("ERROR in ",a)') rname; status=1; return
  107. end if
  108. ! base indices of sigma info and extra info:
  109. sig0 = 5
  110. ext0 = sig0 + maxlev+1 + maxlev
  111. ! number of levels:
  112. ncb%nlev = int(rec2(ext0+2))
  113. ! extract times
  114. ncb%fcst_hr = nint(rec2(1))
  115. ncb%idate(4) = transfer(rec2(2),idum) ! hour
  116. ncb%idate(2) = transfer(rec2(3),idum) ! month
  117. ncb%idate(3) = transfer(rec2(4),idum) ! day
  118. ncb%idate(1) = transfer(rec2(5),idum) ! year
  119. ! extract sigma half levels
  120. allocate( ncb%sigma_half(ncb%nlev+1) )
  121. ncb%sigma_half = rec2(sig0+1:sig0+ncb%nlev+1)
  122. ! extract sigma full levels:
  123. allocate( ncb%sigma_full(ncb%nlev) )
  124. ncb%sigma_full = rec2(sig0+(ncb%nlev+1)+1:sig0+(ncb%nlev+1)+ncb%nlev)
  125. ! extract spectral truncation; compute number of complex coeff:
  126. ncb%shT = int(rec2(ext0+1))
  127. ncb%shn = ( ncb%shT + 1 ) * ( ncb%shT + 2 ) / 2
  128. ! ok
  129. status = 0
  130. end subroutine ncb_Init
  131. ! ***
  132. subroutine ncb_Done( ncb, status )
  133. ! --- in/out ----------------------------------------
  134. type(TNcepCrayBin), intent(inout) :: ncb
  135. integer, intent(out) :: status
  136. ! --- const ------------------------------------------
  137. character(len=*), parameter :: rname = mname//'/ncb_Done'
  138. ! --- begin ------------------------------------------
  139. ! clear
  140. deallocate( ncb%sigma_half )
  141. deallocate( ncb%sigma_full )
  142. ! close file:
  143. close( ncb%fu, iostat=status )
  144. if ( status /= 0 ) then
  145. write (*,'("ERROR - closing file :")')
  146. write (*,'("ERROR - ",a)') trim(ncb%fname)
  147. write (*,'("ERROR in ",a)') rname; status=1; return
  148. end if
  149. ! ok
  150. status = 0
  151. end subroutine ncb_Done
  152. ! ***
  153. subroutine ncb_ReadRecord_2d( ncb, paramkey, sh, status )
  154. ! --- in/out ----------------------------------------
  155. type(TNcepCrayBin), intent(inout) :: ncb
  156. character(len=*), intent(in) :: paramkey
  157. complex, intent(out) :: sh(:)
  158. integer, intent(out) :: status
  159. ! --- const ------------------------------------------
  160. character(len=*), parameter :: rname = mname//'/ncb_ReadRecord_2d'
  161. ! --- local ------------------------------------------
  162. integer :: irec
  163. integer :: i
  164. complex(ncb_rkind), allocatable :: rec_c(:)
  165. ! --- begin ------------------------------------------
  166. ! record 2 has been read
  167. ! setup record buffer:
  168. allocate( rec_c(ncb%shn ) )
  169. ! determine record number:
  170. select case ( paramkey )
  171. case ( 'oro' ) ; irec = 3
  172. case ( 'LNSP' ) ; irec = 4
  173. case default
  174. write (*,'("ERROR - do not know record number for param ",a)') paramkey
  175. write (*,'("ERROR in ",a)') rname; status=1; return
  176. end select
  177. ! loop over records, last read record is target:
  178. do i = 3, irec
  179. ! read coeff:
  180. read (ncb%fu,iostat=status) rec_c
  181. if ( status /= 0 ) then
  182. write (*,'("ERROR - reading record from file :")')
  183. write (*,'("ERROR - file : ",a )') trim(ncb%fname)
  184. write (*,'("ERROR - record : ",i4)') i
  185. write (*,'("ERROR in ",a)') rname; status=1; return
  186. end if
  187. end do
  188. ! set output array (kind conversion ?)
  189. sh = rec_c
  190. ! clear
  191. deallocate( rec_c )
  192. ! ok
  193. status = 0
  194. end subroutine ncb_ReadRecord_2d
  195. ! ***
  196. subroutine ncb_ReadRecord_3d( ncb, paramkey, sh, status )
  197. ! --- in/out ----------------------------------------
  198. type(TNcepCrayBin), intent(inout) :: ncb
  199. character(len=*), intent(in) :: paramkey
  200. complex, intent(out) :: sh(:,:)
  201. integer, intent(out) :: status
  202. ! --- const ------------------------------------------
  203. character(len=*), parameter :: rname = mname//'/ncb_ReadRecord_3d'
  204. ! --- local ------------------------------------------
  205. integer :: irec
  206. integer :: i
  207. complex(ncb_rkind), allocatable :: rec_c(:)
  208. ! --- begin ------------------------------------------
  209. ! record 2 has been read
  210. ! setup record buffer:
  211. allocate( rec_c(ncb%shn ) )
  212. ! different level ordering:
  213. ! D, VO : D1, VO1, D2, VO2, ...
  214. ! other : T1, T2, ...
  215. !
  216. select case ( paramkey )
  217. case ( 'Tv' )
  218. ! skip oro, lnsp
  219. irec = 2
  220. do i = 1, 2
  221. irec = irec + 1
  222. ! read coeff:
  223. read (ncb%fu,iostat=status) rec_c
  224. if ( status /= 0 ) then
  225. write (*,'("ERROR - reading record from file :")')
  226. write (*,'("ERROR - file : ",a )') trim(ncb%fname)
  227. write (*,'("ERROR - record : ",i4)') irec
  228. write (*,'("ERROR in ",a)') rname; status=1; return
  229. end if
  230. end do
  231. ! read virtual temperature
  232. do i = 1, ncb%nlev
  233. ! read coeff:
  234. irec = irec + 1
  235. read (ncb%fu,iostat=status) rec_c
  236. if ( status /= 0 ) then
  237. write (*,'("ERROR - reading record from file :")')
  238. write (*,'("ERROR - file : ",a )') trim(ncb%fname)
  239. write (*,'("ERROR - record : ",i4)') irec
  240. write (*,'("ERROR in ",a)') rname; status=1; return
  241. end if
  242. ! store:
  243. sh(:,i) = rec_c
  244. end do
  245. case ( 'D', 'VO' )
  246. ! skip oro, lnsp, temperature
  247. irec = 2
  248. do i = 1, 2+ncb%nlev
  249. irec = irec + 1
  250. ! read coeff:
  251. read (ncb%fu,iostat=status) rec_c
  252. if ( status /= 0 ) then
  253. write (*,'("ERROR - reading record from file :")')
  254. write (*,'("ERROR - file : ",a )') trim(ncb%fname)
  255. write (*,'("ERROR - record : ",i4)') irec
  256. write (*,'("ERROR in ",a)') rname; status=1; return
  257. end if
  258. end do
  259. ! read pairs D/VO
  260. do i = 1, ncb%nlev
  261. ! read coeff D:
  262. irec = irec + 1
  263. read (ncb%fu,iostat=status) rec_c
  264. if ( status /= 0 ) then
  265. write (*,'("ERROR - reading record from file :")')
  266. write (*,'("ERROR - file : ",a )') trim(ncb%fname)
  267. write (*,'("ERROR - record : ",i4)') irec
  268. write (*,'("ERROR in ",a)') rname; status=1; return
  269. end if
  270. ! store ?
  271. if ( paramkey == 'D' ) sh(:,i) = rec_c
  272. ! read coeff VO:
  273. irec = irec + 1
  274. read (ncb%fu,iostat=status) rec_c
  275. if ( status /= 0 ) then
  276. write (*,'("ERROR - reading record from file :")')
  277. write (*,'("ERROR - file : ",a )') trim(ncb%fname)
  278. write (*,'("ERROR - record : ",i4)') irec
  279. write (*,'("ERROR in ",a)') rname; status=1; return
  280. end if
  281. ! store ?
  282. if ( paramkey == 'VO' ) sh(:,i) = rec_c
  283. end do
  284. case ( 'Q' )
  285. ! skip oro, lnsp, Tv, VO/D
  286. irec = 2
  287. do i = 1, 2 + 3*ncb%nlev
  288. irec = irec + 1
  289. ! read coeff:
  290. read (ncb%fu,iostat=status) rec_c
  291. if ( status /= 0 ) then
  292. write (*,'("ERROR - reading record from file :")')
  293. write (*,'("ERROR - file : ",a )') trim(ncb%fname)
  294. write (*,'("ERROR - record : ",i4)') irec
  295. write (*,'("ERROR in ",a)') rname; status=1; return
  296. end if
  297. end do
  298. ! read humid:
  299. do i = 1, ncb%nlev
  300. ! read coeff:
  301. irec = irec + 1
  302. read (ncb%fu,iostat=status) rec_c
  303. if ( status /= 0 ) then
  304. write (*,'("ERROR - reading record from file :")')
  305. write (*,'("ERROR - file : ",a )') trim(ncb%fname)
  306. write (*,'("ERROR - record : ",i4)') irec
  307. write (*,'("ERROR in ",a)') rname; status=1; return
  308. end if
  309. ! store:
  310. sh(:,i) = rec_c
  311. end do
  312. case default
  313. write (*,'("ERROR - unsupported param ",a)') paramkey
  314. write (*,'("ERROR in ",a)') rname; status=1; return
  315. end select
  316. ! clear
  317. deallocate( rec_c )
  318. ! ok
  319. status = 0
  320. end subroutine ncb_ReadRecord_3d
  321. end module file_ncb