iom_rstdimg.F90 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  1. MODULE iom_rstdimg
  2. !!=====================================================================
  3. !! *** MODULE iom_rstdimg ***
  4. !! Input/Output manager : Library to read input rstdimg files
  5. !!====================================================================
  6. !! History : 9.0 ! 06 09 (S. Masson) Original code
  7. !!--------------------------------------------------------------------
  8. !!--------------------------------------------------------------------
  9. !! iom_open : open a file read only
  10. !! iom_close : close a file or all files opened by iom
  11. !! iom_get : read a field (interfaced to several routines)
  12. !! iom_gettime : read the time axis kvid in the file
  13. !! iom_varid : get the id of a variable in a file
  14. !! iom_rstput : write a field in a restart file (interfaced to several routines)
  15. !!--------------------------------------------------------------------
  16. USE in_out_manager ! I/O manager
  17. USE lib_mpp ! MPP library
  18. USE dom_oce ! ocean space and time domain
  19. USE lbclnk ! lateal boundary condition / mpp exchanges
  20. USE iom_def ! iom variables definitions
  21. IMPLICIT NONE
  22. PRIVATE
  23. PUBLIC iom_rstdimg_open, iom_rstdimg_close, iom_rstdimg_get, iom_rstdimg_rstput
  24. INTERFACE iom_rstdimg_get
  25. MODULE PROCEDURE iom_rstdimg_g0d, iom_rstdimg_g123d
  26. END INTERFACE
  27. INTERFACE iom_rstdimg_rstput
  28. MODULE PROCEDURE iom_rstdimg_rp0d, iom_rstdimg_rp123d
  29. END INTERFACE
  30. INTEGER, PARAMETER :: jpvnl = 32 ! variable name length
  31. !!----------------------------------------------------------------------
  32. !! NEMO/OPA 3.3 , NEMO Consortium (2010)
  33. !! $Id: iom_rstdimg.F90 2715 2011-03-30 15:58:35Z rblod $
  34. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  35. !!----------------------------------------------------------------------
  36. CONTAINS
  37. SUBROUTINE iom_rstdimg_open( cdname, kiomid, ldwrt, ldok, kdompar )
  38. !!---------------------------------------------------------------------
  39. !! *** SUBROUTINE iom_open ***
  40. !!
  41. !! ** Purpose : open an input file read only (return 0 if not found)
  42. !!---------------------------------------------------------------------
  43. CHARACTER(len=*) , INTENT(inout) :: cdname ! File name
  44. INTEGER , INTENT( out) :: kiomid ! iom identifier of the opened file
  45. LOGICAL , INTENT(in ) :: ldwrt ! read or write the file?
  46. LOGICAL , INTENT(in ) :: ldok ! check the existence
  47. INTEGER, DIMENSION(2,5), INTENT(in ), OPTIONAL :: kdompar ! domain parameters:
  48. CHARACTER(LEN=100) :: clinfo ! info character
  49. CHARACTER(LEN=100) :: cltmp ! temporary character
  50. CHARACTER(LEN=10 ) :: clstatus ! status of opened file (REPLACE or NEW)
  51. INTEGER :: jv ! loop counter
  52. INTEGER :: istop ! temporary storage of nstop
  53. INTEGER :: idrst ! logical unit of the restart file
  54. INTEGER :: iln ! lengths of character
  55. INTEGER :: irecl8 ! record length
  56. INTEGER :: ios ! IO status
  57. INTEGER :: irhd ! record of the header infos
  58. INTEGER :: ivnum ! number of variables
  59. INTEGER :: ishft ! counter shift
  60. INTEGER :: inx, iny, inz ! x,y,z dimension of the variable
  61. INTEGER :: in0d, in1d, in2d, in3d ! number of 0/1/2/3D variables
  62. INTEGER :: ipni, ipnj, ipnij, iarea ! domain decomposition
  63. INTEGER :: iiglo, ijglo ! domain global size
  64. INTEGER :: jl ! loop variable
  65. LOGICAL :: llclobber ! local definition of ln_clobber
  66. CHARACTER(LEN=jpvnl), DIMENSION(jpmax_vars) :: clna0d, clna1d, clna2d, clna3d ! name of 0/1/2/3D variables
  67. REAL(wp), DIMENSION(jpmax_vars) :: zval0d, zval1d, zval2d, zval3d ! value of 0d variables or record
  68. ! ! position for 1/2/3D variables
  69. !---------------------------------------------------------------------
  70. clinfo = ' iom_rstdimg_open ~~~ '
  71. istop = nstop ! store the actual value of nstop
  72. ios = 0 ! default definition
  73. kiomid = 0 ! default definition
  74. llclobber = ldwrt .AND. ln_clobber
  75. ! get a free unit
  76. idrst = get_unit() ! get a free logical unit for the restart file
  77. !!$#if defined key_agrif
  78. !!$ idrst = Agrif_Get_Unit()
  79. !!$#endif
  80. ! Open the file...
  81. ! =============
  82. IF( ldok .AND. .NOT. llclobber ) THEN ! Open existing file...
  83. ! find the record length
  84. OPEN( idrst, FILE = TRIM(cdname), FORM = 'unformatted', ACCESS = 'direct' &
  85. & , RECL = 8, STATUS = 'old', ACTION = 'read', IOSTAT = ios, ERR = 987 )
  86. READ( idrst, REC = 1, IOSTAT = ios, ERR = 987 ) irecl8
  87. CLOSE( idrst )
  88. ! Open the file with the appropriate record length and parameters
  89. IF( ldwrt ) THEN ! ... in readwrite mode
  90. IF(lwp) WRITE(numout,*) TRIM(clinfo)//' open existing file: '//TRIM(cdname)//' in READWRITE mode'
  91. OPEN( idrst, FILE = TRIM(cdname), FORM = 'unformatted', ACCESS = 'direct' &
  92. & , RECL = irecl8, STATUS = 'old', ACTION = 'readwrite', IOSTAT = ios, ERR = 987 )
  93. ELSE ! ... in read mode
  94. IF(lwp) WRITE(numout,*) TRIM(clinfo)//' open existing file: '//TRIM(cdname)//' in READ mode'
  95. OPEN( idrst, FILE = TRIM(cdname), FORM = 'unformatted', ACCESS = 'direct' &
  96. & , RECL = irecl8, STATUS = 'old', ACTION = 'read' , IOSTAT = ios, ERR = 987 )
  97. ENDIF
  98. ELSE ! the file does not exist (or we overwrite it)
  99. iln = INDEX( cdname, '.dimg' )
  100. IF( ldwrt ) THEN ! the file should be open in readwrite mode so we create it...
  101. irecl8= MAX( kdompar(1,1) * kdompar(2,1) * wp, ( 8*jpnij + 15 ) * 4 )
  102. IF( jpnij > 1 ) THEN
  103. WRITE(cltmp,'(a,a,i4.4,a)') cdname(1:iln-1), '_', narea, '.dimg'
  104. cdname = TRIM(cltmp)
  105. ENDIF
  106. IF(lwp) WRITE(numout,*) TRIM(clinfo)//' create new file: '//TRIM(cdname)//' in READWRITE mode'
  107. IF( llclobber ) THEN ; clstatus = 'REPLACE'
  108. ELSE ; clstatus = 'NEW'
  109. ENDIF
  110. OPEN( idrst, FILE = TRIM(cdname), FORM = 'UNFORMATTED', ACCESS = 'DIRECT' &
  111. & , RECL = irecl8, STATUS = TRIM(clstatus), ACTION = 'readwrite', IOSTAT = ios, ERR = 987 )
  112. ELSE ! the file should be open for read mode so it must exist...
  113. CALL ctl_stop( TRIM(clinfo), ' should be impossible case...' )
  114. ENDIF
  115. ENDIF
  116. ! Performs checks on the file
  117. ! =============
  118. IF( ldok .AND. .NOT. llclobber ) THEN ! old file
  119. READ( idrst, REC = 1 , IOSTAT = ios, ERR = 987 ) &
  120. & irecl8, inx, iny, inz, in0d, in1d, in2d, in3d, irhd, &
  121. & ipni, ipnj, ipnij, iarea, iiglo, ijglo
  122. READ( idrst, REC = irhd, IOSTAT = ios, ERR = 987 ) &
  123. & clna0d(1:in0d), zval0d(1:in0d), clna1d(1:in1d), zval1d(1:in1d), &
  124. & clna2d(1:in2d), zval2d(1:in2d), clna3d(1:in3d), zval3d(1:in3d)
  125. clinfo = TRIM(clinfo)//' file '//TRIM(cdname)
  126. IF( iiglo /= jpiglo ) CALL ctl_stop( TRIM(clinfo), 'Mismatch in global domain size in i direction' )
  127. IF( ijglo /= jpjglo ) CALL ctl_stop( TRIM(clinfo), 'Mismatch in global domain size in j direction' )
  128. IF( ldwrt ) THEN
  129. IF( inx /= kdompar(1,1) ) CALL ctl_stop( TRIM(clinfo), 'Mismatch in local domain size in i direction' )
  130. IF( iny /= kdompar(2,1) ) CALL ctl_stop( TRIM(clinfo), 'Mismatch in local domain size in j direction' )
  131. ENDIF
  132. IF( inz /= jpk ) CALL ctl_stop( TRIM(clinfo), 'Mismatch in domain size in k direction' )
  133. IF( ipni /= jpni ) CALL ctl_stop( TRIM(clinfo), 'Processor splitting changed along I' )
  134. IF( ipnj /= jpnj ) CALL ctl_stop( TRIM(clinfo), 'Processor splitting changed along J' )
  135. IF( ipnij /= jpnij ) CALL ctl_stop( TRIM(clinfo), 'Total number of processors changed' )
  136. IF( iarea /= narea ) CALL ctl_stop( TRIM(clinfo), 'Mismatch in area numbering ...' )
  137. ENDIF
  138. ! fill file informations
  139. ! =============
  140. IF( istop == nstop ) THEN ! no error within this routine
  141. !does not work with some compilers kiomid = MINLOC(iom_file(:)%nfid, dim = 1)
  142. kiomid = 0
  143. DO jl = jpmax_files, 1, -1
  144. IF( iom_file(jl)%nfid == 0 ) kiomid = jl
  145. ENDDO
  146. iom_file(kiomid)%name = TRIM(cdname)
  147. iom_file(kiomid)%nfid = idrst
  148. iom_file(kiomid)%iolib = jprstdimg
  149. iom_file(kiomid)%iduld = -1
  150. IF( ldok ) THEN ! old file
  151. ! read variables informations from the file header
  152. IF( TRIM(clna0d(1)) == 'no0d' ) in0d = 0
  153. IF( TRIM(clna1d(1)) == 'no1d' ) in1d = 0
  154. IF( TRIM(clna2d(1)) == 'no2d' ) in2d = 0
  155. IF( TRIM(clna3d(1)) == 'no3d' ) in3d = 0
  156. ivnum = in0d + in1d + in2d + in3d
  157. iom_file(kiomid)%nvars = ivnum
  158. iom_file(kiomid)%irec = 2 + in1d + in2d + inz * in3d
  159. iom_file(kiomid)%luld( 1:ivnum) = .FALSE.
  160. iom_file(kiomid)%scf( 1:ivnum) = 1.
  161. ! scalar variable
  162. DO jv = 1, in0d
  163. iom_file(kiomid)%cn_var(jv) = TRIM(clna0d(jv))
  164. iom_file(kiomid)%nvid( jv) = 1
  165. iom_file(kiomid)%ndims( jv) = 0
  166. iom_file(kiomid)%ofs( jv) = zval0d(jv) ! warning: trick... we use ofs to store the value
  167. END DO
  168. ! 1d variable
  169. ishft = in0d
  170. DO jv = 1, in1d
  171. iom_file(kiomid)%cn_var( ishft + jv) = TRIM(clna1d(jv))
  172. iom_file(kiomid)%nvid( ishft + jv) = zval1d(jv)
  173. iom_file(kiomid)%ndims( ishft + jv) = 1
  174. iom_file(kiomid)%dimsz(1 , ishft + jv) = jpk
  175. iom_file(kiomid)%ofs( ishft + jv) = 0.
  176. END DO
  177. ! 2d variable
  178. ishft = in0d + in1d
  179. DO jv = 1, in2d
  180. iom_file(kiomid)%cn_var( ishft + jv) = TRIM(clna2d(jv))
  181. iom_file(kiomid)%nvid( ishft + jv) = zval2d(jv)
  182. iom_file(kiomid)%ndims( ishft + jv) = 2
  183. iom_file(kiomid)%dimsz(1:2, ishft + jv) = (/ inx, iny /)
  184. iom_file(kiomid)%ofs( ishft + jv) = 0.
  185. END DO
  186. ! 3d variable
  187. ishft = in0d + in1d + in2d
  188. DO jv = 1, in3d
  189. iom_file(kiomid)%cn_var( ishft + jv) = TRIM(clna3d(jv))
  190. iom_file(kiomid)%nvid( ishft + jv) = zval3d(jv)
  191. iom_file(kiomid)%ndims( ishft + jv) = 3
  192. iom_file(kiomid)%dimsz(1:3, ishft + jv) = (/ inx, iny, jpk /)
  193. iom_file(kiomid)%ofs( ishft + jv) = 0.
  194. END DO
  195. ELSE ! new file
  196. iom_file(kiomid)%nvars = 0
  197. iom_file(kiomid)%irec = 2
  198. ! store file informations
  199. WRITE( idrst, REC = 1, IOSTAT = ios, ERR = 987 ) irecl8, kdompar(:,1), jpk ! store domain size
  200. ENDIF
  201. ENDIF
  202. 987 CONTINUE
  203. IF( ios /= 0 ) THEN
  204. WRITE(ctmp1,*) ' iostat = ', ios
  205. CALL ctl_stop( TRIM(clinfo), ' error in opening file '//TRIM(cdname), ctmp1 )
  206. ENDIF
  207. !
  208. END SUBROUTINE iom_rstdimg_open
  209. SUBROUTINE iom_rstdimg_close( kiomid )
  210. !!--------------------------------------------------------------------
  211. !! *** SUBROUTINE iom_rstdimg_close ***
  212. !!
  213. !! ** Purpose : close an input file
  214. !!--------------------------------------------------------------------
  215. INTEGER, INTENT(in) :: kiomid ! iom identifier of the file to be closed
  216. !
  217. CHARACTER(LEN=100) :: clinfo ! info character
  218. INTEGER :: jv ! loop counter
  219. INTEGER :: irecl8 ! record length
  220. INTEGER :: ios ! IO status
  221. INTEGER :: irhd ! record of the header infos
  222. INTEGER :: ivnum ! number of variables
  223. INTEGER :: idrst ! file logical unit
  224. INTEGER :: inx, iny, inz ! x,y,z dimension of the variable
  225. INTEGER :: in0d, in1d, in2d, in3d ! number of 0/1/2/3D variables
  226. CHARACTER(LEN=jpvnl), DIMENSION(jpmax_vars) :: clna0d, clna1d, clna2d, clna3d ! name of 0/1/2/3D variables
  227. REAL(wp), DIMENSION(jpmax_vars) :: zval0d, zval1d, zval2d, zval3d ! value of 0d variables or record
  228. ! ! position for 1/2/3D variables
  229. !---------------------------------------------------------------------
  230. !
  231. clinfo = ' iom_rstdimg_close ~~~ '
  232. idrst = iom_file(kiomid)%nfid ! get back the logical unit of the restart file
  233. ! test if we can write in the file (test with INQUIRE gives alsways YES even with read only files...)
  234. READ( idrst, REC = 1, IOSTAT = ios, ERR = 987 ) irecl8, inx, iny, inz
  235. WRITE( idrst, REC = 1, IOSTAT = ios ) irecl8, inx, iny, inz
  236. ! We can write in the file => we update its header before closing
  237. IF( ios == 0 ) THEN
  238. READ( idrst, REC = 1, IOSTAT = ios, ERR = 987 ) irecl8, inx, iny, inz ! get back domain size
  239. irhd = iom_file(kiomid)%irec
  240. ivnum = iom_file(kiomid)%nvars
  241. in0d = 0 ; in1d = 0 ; in2d = 0 ; in3d = 0
  242. DO jv = 1, ivnum ! loop on each variable to get its name and value/record position
  243. SELECT CASE (iom_file(kiomid)%ndims(jv))
  244. CASE (0) ! scalar variable
  245. in0d = in0d + 1
  246. clna0d(in0d) = TRIM(iom_file(kiomid)%cn_var(jv))
  247. zval0d(in0d) = iom_file(kiomid)%ofs(jv) ! warning: trick... we use ofs to store the value
  248. CASE (1) ! 1d variable
  249. in1d = in1d + 1
  250. clna1d(in1d) = TRIM(iom_file(kiomid)%cn_var(jv))
  251. zval1d(in1d) = iom_file(kiomid)%nvid(jv)
  252. CASE (2) ! 2d variable
  253. in2d = in2d + 1
  254. clna2d(in2d) = TRIM(iom_file(kiomid)%cn_var(jv))
  255. zval2d(in2d) = iom_file(kiomid)%nvid(jv)
  256. CASE (3) ! 3d variable
  257. in3d = in3d + 1
  258. clna3d(in3d) = TRIM(iom_file(kiomid)%cn_var(jv))
  259. zval3d(in3d) = iom_file(kiomid)%nvid(jv)
  260. CASE DEFAULT ; CALL ctl_stop( TRIM(clinfo), 'Should not ne there...' )
  261. END SELECT
  262. END DO
  263. ! force to have at least 1 variable in each list (not necessary (?), but safer...)
  264. IF( in0d == 0 ) THEN ; in0d = 1 ; clna0d(1) = 'no0d' ; zval0d(1) = -1. ; ENDIF
  265. IF( in1d == 0 ) THEN ; in1d = 1 ; clna1d(1) = 'no1d' ; zval1d(1) = -1. ; ENDIF
  266. IF( in2d == 0 ) THEN ; in2d = 1 ; clna2d(1) = 'no2d' ; zval2d(1) = -1. ; ENDIF
  267. IF( in3d == 0 ) THEN ; in3d = 1 ; clna3d(1) = 'no3d' ; zval3d(1) = -1. ; ENDIF
  268. ! update the file header before closing it
  269. WRITE( idrst, REC = 1, IOSTAT = ios, ERR = 987 ) &
  270. & irecl8, inx, iny, inz, in0d, in1d, in2d, in3d, irhd, &
  271. & jpni, jpnj, jpnij, narea, jpiglo, jpjglo, &
  272. & nlcit, nlcjt, nldit, nldjt, nleit, nlejt, nimppt, njmppt
  273. IF( (ivnum * (jpvnl + wp)) > irecl8 ) THEN
  274. CALL ctl_stop( TRIM(clinfo), &
  275. & 'Last record size is too big... You could reduce the value of jpvnl' )
  276. ELSE
  277. WRITE( idrst, REC = irhd, IOSTAT = ios, ERR = 987 ) &
  278. & clna0d(1:in0d), zval0d(1:in0d), clna1d(1:in1d), zval1d(1:in1d), &
  279. & clna2d(1:in2d), zval2d(1:in2d), clna3d(1:in3d), zval3d(1:in3d)
  280. ENDIF
  281. ELSE
  282. ios = 0 ! we cannot write in the file
  283. ENDIF
  284. !
  285. CLOSE( idrst, IOSTAT = ios, ERR = 987 )
  286. 987 CONTINUE
  287. IF( ios /= 0 ) THEN
  288. WRITE(ctmp1,*) ' iostat = ', ios
  289. CALL ctl_stop( TRIM(clinfo), &
  290. & ' error when updating the header of '//TRIM(iom_file(kiomid)%name), ctmp1 )
  291. ENDIF
  292. !
  293. END SUBROUTINE iom_rstdimg_close
  294. SUBROUTINE iom_rstdimg_g0d( kiomid, kvid, pvar )
  295. !!-----------------------------------------------------------------------
  296. !! *** ROUTINE iom_rstdimg_g0d ***
  297. !!
  298. !! ** Purpose : read a scalar with RSTDIMG
  299. !!-----------------------------------------------------------------------
  300. INTEGER, INTENT(in ) :: kiomid ! Identifier of the file
  301. INTEGER, INTENT(in ) :: kvid ! variable id
  302. REAL(wp), INTENT( out) :: pvar ! read field
  303. !---------------------------------------------------------------------
  304. !
  305. pvar = iom_file(kiomid)%ofs(kvid) ! warning: trick... we use ofs to store the value
  306. !
  307. END SUBROUTINE iom_rstdimg_g0d
  308. SUBROUTINE iom_rstdimg_rp0d( kiomid, cdvar, kvid, pv_r0d )
  309. !!--------------------------------------------------------------------
  310. !! *** SUBROUTINE iom_rstdimg_rstput ***
  311. !!
  312. !! ** Purpose : write a scalar with RSTDIMG
  313. !!--------------------------------------------------------------------
  314. INTEGER , INTENT(in) :: kiomid ! Identifier of the file
  315. CHARACTER(len=*) , INTENT(in) :: cdvar ! time axis name
  316. INTEGER , INTENT(in) :: kvid ! variable id
  317. REAL(wp) , INTENT(in) :: pv_r0d ! written 0d field
  318. !
  319. CHARACTER(LEN=100) :: clinfo ! info character
  320. INTEGER :: idvar ! variable id
  321. !---------------------------------------------------------------------
  322. !
  323. clinfo = ' iom_rstdimg_rp0d ~~~ '
  324. IF( kvid <= 0 ) THEN ! new variable
  325. idvar = iom_file(kiomid)%nvars + 1
  326. ELSE ! the variable already exists in the file
  327. idvar = kvid
  328. ENDIF
  329. IF( idvar <= jpmax_vars ) THEN
  330. iom_file(kiomid)%nvars = idvar
  331. iom_file(kiomid)%cn_var(idvar) = TRIM(cdvar)
  332. iom_file(kiomid)%nvid( idvar) = 1 ! useless, Od variables a strored in record 1
  333. iom_file(kiomid)%ndims( idvar) = 0
  334. iom_file(kiomid)%luld( idvar) = .FALSE.
  335. iom_file(kiomid)%scf( idvar) = 1.
  336. iom_file(kiomid)%ofs( idvar) = pv_r0d ! warning: trick... we use ofs to store the value
  337. ELSE
  338. CALL ctl_stop( TRIM(clinfo), 'increase the value of jpmax_vars' )
  339. ENDIF
  340. END SUBROUTINE iom_rstdimg_rp0d
  341. SUBROUTINE iom_rstdimg_g123d( kiomid, kdom , kvid, kx1, kx2, ky1, ky2, &
  342. & pv_r1d, pv_r2d, pv_r3d )
  343. !!-----------------------------------------------------------------------
  344. !! *** ROUTINE iom_rstdimg_g123d ***
  345. !!
  346. !! ** Purpose : read a 1D/2D/3D variable with RSTDIMG
  347. !!
  348. !! ** Method : read ONE record at each CALL
  349. !!-----------------------------------------------------------------------
  350. INTEGER , INTENT(in ) :: kiomid ! iom identifier of the file
  351. INTEGER , INTENT(in ) :: kdom ! Type of domain to be read
  352. INTEGER , INTENT(in ) :: kvid ! variable id
  353. INTEGER , INTENT(inout) :: kx1, kx2, ky1, ky2 ! subdomain indexes
  354. REAL(wp), DIMENSION(:) , INTENT( out), OPTIONAL :: pv_r1d ! read field (1D case)
  355. REAL(wp), DIMENSION(:,:) , INTENT( out), OPTIONAL :: pv_r2d ! read field (2D case)
  356. REAL(wp), DIMENSION(:,:,:) , INTENT( out), OPTIONAL :: pv_r3d ! read field (3D case)
  357. CHARACTER(LEN=100) :: clinfo ! info character
  358. INTEGER :: ios ! IO status
  359. INTEGER :: jk ! loop counter
  360. INTEGER :: idrst ! logical unit of the restart file
  361. !---------------------------------------------------------------------
  362. clinfo = ' iom_rstdimg_g123d ~~~ '
  363. !
  364. IF( kdom == jpdom_data .OR. kdom == jpdom_global ) THEN
  365. CALL ctl_stop( TRIM(clinfo), TRIM(iom_file(kiomid)%cn_var(kvid))//': case not coded for rstdimg files' )
  366. ELSE
  367. !
  368. idrst = iom_file(kiomid)%nfid ! get back the logical unit of the restart file
  369. ! modify the subdomain indexes because we cannot directly extract the appropriate subdomaine
  370. IF( kdom == jpdom_local_full ) THEN ; kx1 = 1 ; kx2 = jpi ; ky1 = 1
  371. ELSEIF( kdom == jpdom_local_noextra ) THEN ; kx1 = 1 ; kx2 = nlci ; ky1 = 1
  372. ENDIF
  373. !
  374. IF( PRESENT(pv_r1d) ) THEN ! read 1D variables
  375. READ( idrst, REC = iom_file(kiomid)%nvid(kvid) , IOSTAT = ios, ERR = 987 ) pv_r1d(:)
  376. ELSEIF( PRESENT(pv_r2d) ) THEN ! read 2D variables
  377. READ( idrst, REC = iom_file(kiomid)%nvid(kvid) , IOSTAT = ios, ERR = 987 ) pv_r2d(kx1:kx2, ky1:ky2 )
  378. ELSEIF( PRESENT(pv_r3d) ) THEN ! read 3D variables
  379. DO jk = 1, iom_file(kiomid)%dimsz(3,kvid) ! do loop on each level
  380. READ( idrst, REC = iom_file(kiomid)%nvid(kvid) + jk - 1, IOSTAT = ios, ERR = 987 ) pv_r3d(kx1:kx2, ky1:ky2, jk)
  381. END DO
  382. ENDIF
  383. 987 CONTINUE
  384. IF( ios /= 0 ) THEN
  385. WRITE(ctmp1,*) ' iostat = ', ios
  386. CALL ctl_stop( TRIM(clinfo), ' IO error with file '//TRIM(iom_file(kiomid)%name), ctmp1 )
  387. ENDIF
  388. ENDIF
  389. !
  390. END SUBROUTINE iom_rstdimg_g123d
  391. SUBROUTINE iom_rstdimg_rp123d( kiomid, cdvar, kvid, pv_r1d, pv_r2d, pv_r3d )
  392. !!--------------------------------------------------------------------
  393. !! *** SUBROUTINE iom_rstdimg_rstput ***
  394. !!
  395. !! ** Purpose : write a 2D/3D variable with RSTDIMG
  396. !!--------------------------------------------------------------------
  397. INTEGER , INTENT(in) :: kiomid ! Identifier of the file
  398. CHARACTER(len=*) , INTENT(in) :: cdvar ! time axis name
  399. INTEGER , INTENT(in) :: kvid ! variable id
  400. REAL(wp), DIMENSION( :), INTENT(in), OPTIONAL :: pv_r1d ! written 1d field
  401. REAL(wp), DIMENSION(: ,: ), INTENT(in), OPTIONAL :: pv_r2d ! written 2d field
  402. REAL(wp), DIMENSION(: ,: ,: ), INTENT(in), OPTIONAL :: pv_r3d ! written 3d field
  403. !
  404. CHARACTER(LEN=100) :: clinfo ! info character
  405. INTEGER :: irecl8 ! reacord length
  406. INTEGER :: ios ! IO status
  407. INTEGER :: idrst ! reacord length
  408. INTEGER :: inx, iny, inz ! x,y,z dimension of the variable
  409. INTEGER :: idvar ! variable id
  410. INTEGER :: istop ! temporary storage of nstop
  411. INTEGER :: irec ! record number
  412. INTEGER :: ix1, ix2, iy1, iy2 ! subdomain indexes
  413. INTEGER :: jk ! loop counter
  414. !---------------------------------------------------------------------
  415. !
  416. clinfo = ' iom_rstdimg_rp123d, file: '//TRIM(iom_file(kiomid)%name)//', var: '//TRIM(cdvar)
  417. istop = nstop ! store the actual value of nstop
  418. irec = iom_file(kiomid)%irec ! get back the record number of the variable
  419. idrst = iom_file(kiomid)%nfid ! get back the logical unit of the restart file
  420. IF( kvid <= 0 ) THEN ! new variable
  421. idvar = iom_file(kiomid)%nvars + 1
  422. ELSE ! the variable already exists in the file
  423. idvar = kvid
  424. ENDIF
  425. IF( idvar > jpmax_vars ) CALL ctl_stop( TRIM(clinfo), 'increase the value of jpmax_vars' )
  426. IF( .NOT. PRESENT(pv_r1d) ) THEN
  427. ! find which part of data must be written
  428. READ( idrst, REC = 1, IOSTAT = ios, ERR = 987 ) irecl8, inx, iny, inz
  429. IF( inx == (nlei - nldi + 1) .AND. iny == (nlej - nldj + 1) ) THEN
  430. ix1 = nldi ; ix2 = nlei ; iy1 = nldj ; iy2 = nlej
  431. ELSEIF( inx == nlci .AND. iny == nlcj ) THEN
  432. ix1 = 1 ; ix2 = nlci ; iy1 = 1 ; iy2 = nlcj
  433. ELSEIF( inx == jpi .AND. iny == jpj ) THEN
  434. ix1 = 1 ; ix2 = jpi ; iy1 = 1 ; iy2 = jpj
  435. ELSE
  436. CALL ctl_stop( clinfo, 'should have been an impossible case...' )
  437. ENDIF
  438. ENDIF
  439. IF( istop == nstop ) THEN
  440. ! write the data
  441. IF( PRESENT(pv_r1d) ) THEN ! 1D variable
  442. WRITE( idrst, REC = irec , IOSTAT = ios, ERR = 987 ) pv_r1d(:)
  443. ELSEIF( PRESENT(pv_r2d) ) THEN ! 2D variable
  444. WRITE( idrst, REC = irec , IOSTAT = ios, ERR = 987 ) pv_r2d(ix1:ix2, iy1:iy2 )
  445. ELSEIF( PRESENT(pv_r3d) ) THEN ! 3D variable
  446. DO jk = 1, jpk ! do loop on each level
  447. WRITE( idrst, REC = irec + jk - 1, IOSTAT = ios, ERR = 987 ) pv_r3d(ix1:ix2, iy1:iy2, jk)
  448. END DO
  449. ENDIF
  450. ! fill the file informations
  451. iom_file(kiomid)%nvars = idvar
  452. IF( PRESENT(pv_r1d) ) THEN
  453. iom_file(kiomid)%irec = irec + 1
  454. iom_file(kiomid)%ndims( idvar) = 1
  455. iom_file(kiomid)%dimsz(1 , idvar) = inz
  456. ELSEIF( PRESENT(pv_r2d) ) THEN
  457. iom_file(kiomid)%irec = irec + 1
  458. iom_file(kiomid)%ndims( idvar) = 2
  459. iom_file(kiomid)%dimsz(1:2, idvar) = (/ inx, iny /)
  460. ELSEIF( PRESENT(pv_r3d) ) THEN
  461. iom_file(kiomid)%irec = irec + inz
  462. iom_file(kiomid)%ndims( idvar) = 3
  463. iom_file(kiomid)%dimsz(1:3, idvar) = (/ inx, iny, inz /)
  464. ENDIF
  465. iom_file(kiomid)%cn_var(idvar) = TRIM(cdvar)
  466. iom_file(kiomid)%nvid( idvar) = irec
  467. iom_file(kiomid)%luld( idvar) = .FALSE.
  468. iom_file(kiomid)%scf( idvar) = 1.
  469. iom_file(kiomid)%ofs( idvar) = 0.
  470. ENDIF
  471. 987 CONTINUE
  472. IF( ios /= 0 ) THEN
  473. WRITE(ctmp1,*) ' iostat = ', ios
  474. CALL ctl_stop( TRIM(clinfo), ' IO error with file '//TRIM(iom_file(kiomid)%name), ctmp1 )
  475. ELSE
  476. IF(lwp) WRITE(numout,*) TRIM(clinfo)//' written ok'
  477. ENDIF
  478. !
  479. END SUBROUTINE iom_rstdimg_rp123d
  480. !!======================================================================
  481. END MODULE iom_rstdimg