m_ioutil.F90 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  3. !-----------------------------------------------------------------------
  4. ! CVS m_ioutil.F90,v 1.16 2006-07-06 22:06:25 jacob Exp
  5. ! CVS MCT_2_8_0
  6. !-----------------------------------------------------------------------
  7. !BOP
  8. !
  9. ! !MODULE: m_ioutil - a F90 module for several convenient I/O functions
  10. !
  11. ! !DESCRIPTION:
  12. !
  13. ! m\_ioutil is a module containing several portable interfaces for
  14. ! some highly system dependent, but frequently used I/O functions.
  15. !
  16. ! !INTERFACE:
  17. module m_ioutil
  18. implicit none
  19. private ! except
  20. public :: opntext,clstext ! open/close a text file
  21. public :: opnieee,clsieee ! open/close a binary sequential file
  22. public :: luavail ! return a free logical unit
  23. public :: luflush ! flush the buffer of a given unit
  24. !public :: MX_LU
  25. ! !REVISION HISTORY:
  26. ! 16Jul96 - J. Guo - (to do)
  27. ! 02Apr97 - Jing Guo <guo@eramus> - finished the coding
  28. ! 11Feb97 - Jing Guo <guo@thunder> - added luflush()
  29. ! 08Nov01 - Jace A Mogill <mogill@cray.com> FORTRAN only defines
  30. ! 99 units, three units below unit 10 are often used for
  31. ! stdin, stdout, and stderr. Be far more conservative
  32. ! and stay within FORTRAN standard.
  33. !
  34. !EOP
  35. !_______________________________________________________________________
  36. character(len=*),parameter :: myname="MCT(MPEU)::m_ioutil"
  37. integer,parameter :: MX_LU=99
  38. contains
  39. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  40. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  41. !-----------------------------------------------------------------------
  42. !BOP
  43. !
  44. ! !IROUTINE: opnieee - portablly open an IEEE format file
  45. !
  46. ! !DESCRIPTION:
  47. !
  48. ! Open a file in IEEE format.
  49. !
  50. ! IEEE format is refered as a FORTRAN "unformatted" file with
  51. ! "sequantial" access and variable record lengths. Under common
  52. ! Unix, it is only a file with records packed with a leading 4-
  53. ! byte word and a trailing 4-byte word indicating the size of
  54. ! the record in bytes. However, under UNICOS, it is also assumed
  55. ! to have numerical data representations represented according to
  56. ! the IEEE standard corresponding KIND conversions. Under a DEC
  57. ! machine, it means that compilations of the source code should
  58. ! have the "-bigendian" option specified.
  59. !
  60. ! !INTERFACE:
  61. subroutine opnieee(lu,fname,status,ier,recl)
  62. use m_stdio,only : stderr
  63. implicit none
  64. integer, intent(in) :: lu ! logical unit number
  65. character(len=*),intent(in) :: fname ! filename to be opended
  66. character(len=*),intent(in) :: status ! the value for STATUS=
  67. integer, intent(out):: ier ! the status
  68. integer,optional,intent(in) :: recl ! record length
  69. ! !REVISION HISTORY:
  70. ! 02Feb95 - Jing G. - First version included in PSAS. It is not
  71. ! used in the libpsas.a calls, since no binary data input/
  72. ! output is to be handled.
  73. !
  74. ! 09Oct96 - J. Guo - Check for any previous assign() call under
  75. ! UNICOS.
  76. !EOP
  77. !_______________________________________________________________________
  78. #ifdef _UNICOS
  79. character(len=128) :: attr
  80. #endif
  81. ! local parameter
  82. character(len=*),parameter :: myname_=myname//'::opnieee'
  83. integer,parameter :: iA=ichar('a')
  84. integer,parameter :: mA=ichar('A')
  85. integer,parameter :: iZ=ichar('z')
  86. logical :: direct
  87. character(len=16) :: clen
  88. character(len=len(status)) :: Ustat
  89. integer :: i,ic
  90. ! Work-around for absoft 9.0 f90, which has trouble understanding that
  91. ! ier is an output argument from the write() call below.
  92. ier = 0
  93. direct=.false.
  94. if(present(recl)) then
  95. if(recl<0) then
  96. clen='****************'
  97. write(clen,'(i16)',iostat=ier) recl
  98. write(stderr,'(3a)') myname_, &
  99. ': invalid recl, ',trim(adjustl(clen))
  100. ier=-1
  101. return
  102. endif
  103. direct = recl>0
  104. endif
  105. #ifdef _UNICOS
  106. call asnqunit(lu,attr,ier) ! test the unit
  107. if(ier.eq.-1) then ! the unit is not used
  108. if(direct) then
  109. call asnunit(lu,'-N ieee -F null',ier)
  110. else
  111. call asnunit(lu,'-N ieee -F f77',ier)
  112. endif
  113. ier=0
  114. elseif(ier.ge.0) then ! the unit is already assigned
  115. ier=-1
  116. endif
  117. if(ier.ne.0) return
  118. #endif
  119. do i=1,len(status)
  120. ic=ichar(status(i:i))
  121. if(ic >= iA .and. ic <= iZ) ic=ic+(mA-iA)
  122. Ustat(i:i)=char(ic)
  123. end do
  124. select case(Ustat)
  125. case ('APPEND')
  126. if(direct) then
  127. write(stderr,'(2a)') myname_, &
  128. ': invalid arguments, (status=="APPEND",recl>0)'
  129. ier=1
  130. return
  131. endif
  132. open( &
  133. unit =lu, &
  134. file =fname, &
  135. form ='unformatted', &
  136. access ='sequential', &
  137. status ='unknown', &
  138. position ='append', &
  139. iostat =ier )
  140. case default
  141. if(direct) then
  142. open( &
  143. unit =lu, &
  144. file =fname, &
  145. form ='unformatted', &
  146. access ='direct', &
  147. status =status, &
  148. recl =recl, &
  149. iostat =ier )
  150. else
  151. open( &
  152. unit =lu, &
  153. file =fname, &
  154. form ='unformatted', &
  155. access ='sequential', &
  156. status =status, &
  157. position ='asis', &
  158. iostat =ier )
  159. endif
  160. end select
  161. end subroutine opnieee
  162. !-----------------------------------------------------------------------
  163. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  164. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  165. !-----------------------------------------------------------------------
  166. !BOP
  167. !
  168. ! !IROUTINE: clsieee - Close a logical unit opened by opnieee()
  169. !
  170. ! !DESCRIPTION:
  171. !
  172. ! The reason for a paired clsieee() for opnieee() instead of a
  173. ! simple close(), is for the portability reason. For example,
  174. ! under UNICOS, special system calls may be need to set up the
  175. ! unit right, and the status of the unit should be restored upon
  176. ! close.
  177. !
  178. ! !INTERFACE:
  179. subroutine clsieee(lu,ier)
  180. implicit none
  181. integer, intent(in) :: lu ! the unit used by opnieee()
  182. integer, intent(out) :: ier ! the status
  183. ! !REVISION HISTORY:
  184. ! 10Oct96 - J. Guo - (to do)
  185. !EOP
  186. !_______________________________________________________________________
  187. close(lu,iostat=ier)
  188. #ifdef _UNICOS
  189. if(ier==0) call asnunit(lu,'-R',ier) ! remove attributes
  190. #endif
  191. end subroutine clsieee
  192. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  193. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  194. !-----------------------------------------------------------------------
  195. !BOP
  196. !
  197. ! !IROUTINE: opntext - portablly open a text file
  198. !
  199. ! !DESCRIPTION:
  200. !
  201. ! Open a text (ASCII) file. Under FORTRAN, it is defined as
  202. ! "formatted" with "sequential" access.
  203. !
  204. ! !INTERFACE:
  205. subroutine opntext(lu,fname,status,ier)
  206. implicit none
  207. integer, intent(in) :: lu ! logical unit number
  208. character(len=*),intent(in) :: fname ! filename to be opended
  209. character(len=*),intent(in) :: status ! the value for STATUS=<>
  210. integer, intent(out):: ier ! the status
  211. ! !REVISION HISTORY:
  212. !
  213. ! 02Feb95 - Jing G. - First version included in PSAS and libpsas.a
  214. ! 09Oct96 - J. Guo - modified to allow assign() call under UNICOS
  215. ! = and now, it is a module in Fortran 90.
  216. !EOP
  217. !_______________________________________________________________________
  218. ! local parameter
  219. character(len=*),parameter :: myname_=myname//'::opntext'
  220. integer,parameter :: iA=ichar('a')
  221. integer,parameter :: mA=ichar('A')
  222. integer,parameter :: iZ=ichar('z')
  223. character(len=len(status)) :: Ustat
  224. integer :: i,ic
  225. #ifdef _UNICOS
  226. call asnunit(lu,'-R',ier) ! remove any set attributes
  227. if(ier.ne.0) return ! let the parent handle it
  228. #endif
  229. do i=1,len(status)
  230. ic=ichar(status(i:i))
  231. if(ic >= iA .and. ic <= iZ) ic=ic+(mA-iA)
  232. Ustat(i:i)=char(ic)
  233. end do
  234. select case(Ustat)
  235. case ('APPEND')
  236. open( &
  237. unit =lu, &
  238. file =fname, &
  239. form ='formatted', &
  240. access ='sequential', &
  241. status ='unknown', &
  242. position ='append', &
  243. iostat =ier )
  244. case default
  245. open( &
  246. unit =lu, &
  247. file =fname, &
  248. form ='formatted', &
  249. access ='sequential', &
  250. status =status, &
  251. position ='asis', &
  252. iostat =ier )
  253. end select
  254. end subroutine opntext
  255. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  256. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  257. !-----------------------------------------------------------------------
  258. !BOP
  259. !
  260. ! !IROUTINE: clstext - close a text file opend with an opntext() call
  261. !
  262. ! !DESCRIPTION:
  263. !
  264. ! !INTERFACE:
  265. subroutine clstext(lu,ier)
  266. implicit none
  267. integer, intent(in) :: lu ! a logical unit to close
  268. integer, intent(out) :: ier ! the status
  269. ! !REVISION HISTORY:
  270. ! 09Oct96 - J. Guo - (to do)
  271. !EOP
  272. !_______________________________________________________________________
  273. close(lu,iostat=ier)
  274. #ifdef _UNICOS
  275. if(ier == 0) call asnunit(lu,'-R',ier) ! remove any attributes
  276. #endif
  277. end subroutine clstext
  278. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  279. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  280. !BOP -------------------------------------------------------------------
  281. !
  282. ! !IROUTINE: luavail - locate the next available unit
  283. !
  284. ! !DESCRIPTION:
  285. !
  286. ! luavail() Look for an available (not opened and not statically
  287. ! assigned to any I/O attributes to) logical unit.
  288. !
  289. ! !INTERFACE:
  290. function luavail()
  291. use m_stdio
  292. implicit none
  293. integer :: luavail ! result
  294. ! !REVISION HISTORY:
  295. ! 23Apr98 - Jing Guo <guo@thunder> - new prototype/prolog/code
  296. ! - with additional unit constraints for SunOS.
  297. !
  298. ! : Jing Guo, [09-Oct-96]
  299. ! + Checking also Cray assign() attributes, with some
  300. ! changes to the code. See also other routines.
  301. !
  302. ! : Jing Guo, [01-Apr-94]
  303. ! + Initial code.
  304. ! 2001-11-08 - Jace A Mogill <mogill@cray.com> clean up
  305. ! logic for finding lu.
  306. !
  307. !EOP ___________________________________________________________________
  308. character(len=*),parameter :: myname_=myname//'::luavail'
  309. integer lu,ios
  310. logical inuse
  311. lu=10
  312. ios=0
  313. inuse=.true.
  314. do while(ios.eq.0 .and. inuse .and. lu.le.MX_LU)
  315. lu=lu+1
  316. inquire(unit=lu,opened=inuse,iostat=ios)
  317. end do
  318. if(ios.ne.0) lu=-1
  319. luavail=lu
  320. end function luavail
  321. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  322. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  323. !-----------------------------------------------------------------------
  324. !BOP
  325. !
  326. ! !IROUTINE: luflush - a uniform interface of system flush()
  327. !
  328. ! !DESCRIPTION:
  329. !
  330. ! Flush() calls available on many systems are often implementation
  331. ! dependent. This subroutine provides a uniform interface. It
  332. ! also ignores invalid logical unit value.
  333. !
  334. ! !INTERFACE:
  335. subroutine luflush(unit)
  336. use m_stdio, only : stdout
  337. #ifdef CPRNAG
  338. use F90_UNIX_IO,only : flush
  339. #endif
  340. implicit none
  341. integer,optional,intent(in) :: unit
  342. ! !REVISION HISTORY:
  343. ! 13Mar98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
  344. ! 08Jul02 - E. Ong <eong@mcs.anl.gov> - added flush support for nag95
  345. ! 2001-11-08 Jace A Mogill <mogill@cray.com> - Flush is not part of
  346. ! the F90 standard. Default is NO unit flush.
  347. !EOP
  348. !_______________________________________________________________________
  349. character(len=*),parameter :: myname_=myname//'::luflush'
  350. integer :: ier
  351. integer :: lu
  352. ! Which logical unit number?
  353. lu=stdout
  354. if(present(unit)) lu=unit
  355. if(lu < 0) return
  356. ! The following call may be system dependent.
  357. #if SYSIRIX64 || CPRNAG || SYSUNICOS
  358. call flush(lu,ier)
  359. #elif SYSAIX || CPRXLF
  360. call flush_(lu) ! Function defined in xlf reference document.
  361. #elif SYSLINUX || SYSOSF1 || SYSSUNOS || SYST3E || SYSUNIXSYSTEMV || SYSSUPERUX
  362. call flush(lu)
  363. #endif
  364. end subroutine luflush
  365. !-----------------------------------------------------------------------
  366. end module m_ioutil
  367. !.