PageRenderTime 61ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/wrfv2_fire/frame/module_quilt_outbuf_ops.F

http://github.com/jbeezley/wrf-fire
FORTRAN Legacy | 1490 lines | 863 code | 215 blank | 412 comment | 0 complexity | cac9dffc68472591f2b81a9629add207 MD5 | raw file
Possible License(s): AGPL-1.0
  1. MODULE module_quilt_outbuf_ops
  2. !<DESCRIPTION>
  3. !<PRE>
  4. ! This module contains routines and data structures used by the I/O quilt
  5. ! servers to assemble fields ("quilting") and write them to disk.
  6. !</PRE>
  7. !</DESCRIPTION>
  8. INTEGER, PARAMETER :: tabsize = 5
  9. ! The number of entries in outpatch_table (up to a maximum of tabsize)
  10. INTEGER, SAVE :: num_entries
  11. ! ARP, for PNC-enabled quilting, 02/06/2010
  12. TYPE varpatch
  13. LOGICAL :: forDeletion ! TRUE if patch to be
  14. ! deleted
  15. INTEGER, DIMENSION(3) :: PatchStart, PatchEnd, PatchExtent
  16. REAL, POINTER, DIMENSION(:,:,:) :: rptr
  17. INTEGER, POINTER, DIMENSION(:,:,:) :: iptr
  18. END TYPE varpatch
  19. ! With PNC-enabled quilting, each table entry consists of a series of
  20. ! 'npatch' patches (one for each of the compute PEs that this IOServer has
  21. ! as clients). We attempt to stitch these together before finally
  22. ! writing the data to disk.
  23. TYPE outpatchlist
  24. CHARACTER*80 :: VarName, DateStr, MemoryOrder, &
  25. Stagger, DimNames(3)
  26. INTEGER, DIMENSION(3) :: DomainStart, DomainEnd
  27. INTEGER :: FieldType
  28. ! Total no. of patches in the list PatchList
  29. INTEGER :: nPatch
  30. ! How many of the patches remain active in PatchList
  31. INTEGER :: nActivePatch
  32. TYPE(varpatch), ALLOCATABLE, DIMENSION(:) :: PatchList
  33. ! TYPE(varpatch), DIMENSION(tabsize) :: PatchList
  34. END TYPE outpatchlist
  35. TYPE(outpatchlist), DIMENSION(tabsize), SAVE :: outpatch_table
  36. ! List of which of the initial set of patches saved by the IOServer have
  37. ! been successfully stitched together. Without any stitching, each patch's
  38. ! entry contains just itself:
  39. ! JoinedPatches(1,ipatch) = ipatch
  40. ! If jpatch is then stitched to ipatch then we do:
  41. ! JoinedPatches(2,ipatch) = jpatch
  42. ! and so on.
  43. INTEGER, ALLOCATABLE, DIMENSION(:,:), SAVE :: JoinedPatches
  44. ! The no. of original patches to be stitched together to make each new patch
  45. ! i.e. if the 2nd new patch consists of 4 of the original patches stitched
  46. ! together then:
  47. ! PatchCount(2) = 4
  48. INTEGER, ALLOCATABLE, DIMENSION(:), SAVE :: PatchCount
  49. ! endARP, for PNC-enabled quilting, 02/06/2010
  50. TYPE outrec
  51. CHARACTER*80 :: VarName, DateStr, MemoryOrder, &
  52. Stagger, DimNames(3)
  53. INTEGER :: ndim
  54. INTEGER, DIMENSION(3) :: DomainStart, DomainEnd
  55. INTEGER :: FieldType
  56. REAL, POINTER, DIMENSION(:,:,:) :: rptr
  57. INTEGER, POINTER, DIMENSION(:,:,:) :: iptr
  58. END TYPE outrec
  59. TYPE(outrec), DIMENSION(tabsize) :: outbuf_table
  60. CONTAINS
  61. SUBROUTINE init_outbuf
  62. !<DESCRIPTION>
  63. !<PRE>
  64. ! This routine re-initializes module data structures.
  65. !</PRE>
  66. !</DESCRIPTION>
  67. IMPLICIT NONE
  68. INTEGER :: i, j
  69. DO i = 1, tabsize
  70. #ifdef PNETCDF_QUILT
  71. ! This section for PNC-enabled IO quilting
  72. outpatch_table(i)%VarName = ""
  73. outpatch_table(i)%DateStr = ""
  74. outpatch_table(i)%MemoryOrder = ""
  75. outpatch_table(i)%Stagger = ""
  76. outpatch_table(i)%DimNames(1:3) = ""
  77. outpatch_table(i)%DomainStart(1:3) = 0
  78. outpatch_table(i)%DomainEnd(1:3) = 0
  79. ! We don't free any memory here - that is done immediately after the
  80. ! write of each patch is completed
  81. DO j = 1, outpatch_table(i)%npatch
  82. outpatch_table(i)%PatchList(j)%forDeletion = .FALSE.
  83. outpatch_table(i)%PatchList(j)%PatchStart(:) = 0
  84. outpatch_table(i)%PatchList(j)%PatchEnd(:) = 0
  85. outpatch_table(i)%PatchList(j)%PatchExtent(:)= 0
  86. IF (ALLOCATED(outpatch_table(i)%PatchList)) THEN
  87. IF (ASSOCIATED(outpatch_table(i)%PatchList(j)%rptr)) &
  88. NULLIFY( outpatch_table(i)%PatchList(j)%rptr )
  89. IF (ASSOCIATED(outpatch_table(i)%PatchList(j)%iptr)) &
  90. NULLIFY( outpatch_table(i)%PatchList(j)%iptr )
  91. DEALLOCATE(outpatch_table(i)%PatchList)
  92. ENDIF
  93. END DO
  94. outpatch_table(i)%npatch = 0
  95. outpatch_table(i)%nActivePatch = 0
  96. #else
  97. outbuf_table(i)%VarName = ""
  98. outbuf_table(i)%DateStr = ""
  99. outbuf_table(i)%MemoryOrder = ""
  100. outbuf_table(i)%Stagger = ""
  101. outbuf_table(i)%DimNames(1) = ""
  102. outbuf_table(i)%DimNames(2) = ""
  103. outbuf_table(i)%DimNames(3) = ""
  104. outbuf_table(i)%ndim = 0
  105. NULLIFY( outbuf_table(i)%rptr )
  106. NULLIFY( outbuf_table(i)%iptr )
  107. #endif
  108. ENDDO
  109. write(0,*)'initializing num_entries to 0 '
  110. num_entries = 0
  111. END SUBROUTINE init_outbuf
  112. #ifdef PNETCDF_QUILT
  113. SUBROUTINE write_outbuf_pnc ( DataHandle, io_form_arg, local_comm, &
  114. mytask, ntasks )
  115. !<DESCRIPTION>
  116. !<PRE>
  117. ! This routine writes all of the records stored in outpatch_table to the
  118. ! file referenced by DataHandle using pNetCDF. The patches constituting
  119. ! each record are stitched together as far as is possible before
  120. ! the pNetCDF I/O routines are called to accomplish the write.
  121. !
  122. ! It then re-initializes module data structures.
  123. !</PRE>
  124. !</DESCRIPTION>
  125. USE module_state_description
  126. IMPLICIT NONE
  127. INCLUDE 'mpif.h'
  128. #include "wrf_io_flags.h"
  129. INTEGER , INTENT(IN) :: DataHandle, io_form_arg, &
  130. local_comm, mytask, ntasks
  131. INTEGER :: ii, jj
  132. INTEGER :: DomainDesc ! dummy
  133. INTEGER :: Status
  134. INTEGER :: ipatch, icnt
  135. INTEGER, ALLOCATABLE, DIMENSION(:) :: count_buf
  136. INTEGER :: min_count
  137. LOGICAL :: do_indep_write ! If no. of patches differs between
  138. ! IO Servers then we will have to
  139. ! switch pnetcdf into
  140. ! independent-writes mode for some
  141. ! of them
  142. CHARACTER*256 :: mess
  143. DomainDesc = 0
  144. ALLOCATE(count_buf(ntasks), Stat=Status)
  145. IF(Status /= 0)THEN
  146. CALL wrf_error_fatal("write_outbuf_pnc: allocate failed")
  147. END IF
  148. WRITE(mess,"('write_outbuf_pnc: table has ', I3,' entries')") num_entries
  149. CALL wrf_message(mess)
  150. DO ii = 1, num_entries
  151. WRITE(mess,*)'write_outbuf_pnc: writing ', &
  152. TRIM(outpatch_table(ii)%DateStr)," ", &
  153. TRIM(outpatch_table(ii)%VarName)," ", &
  154. TRIM(outpatch_table(ii)%MemoryOrder)
  155. CALL wrf_message(mess)
  156. SELECT CASE ( io_form_arg )
  157. CASE ( IO_PNETCDF )
  158. ! Situation is more complicated in this case since field data stored
  159. ! as a list of patches rather than in one array of global-domain
  160. ! extent.
  161. ! PatchStart(1) - PatchEnd(1) is dimension with unit stride.
  162. ! Quilt patches back together where possible in order to minimise
  163. ! number of individual writes
  164. CALL stitch_outbuf_patches(ii)
  165. ! Check how many patches each of the other IO servers has - we can
  166. ! only use pNetCDF in collective mode for the same no. of writes
  167. ! on each IO server. Any other patches will have to be written in
  168. ! independent mode.
  169. do_indep_write = .FALSE.
  170. count_buf(:) = 0
  171. min_count = outpatch_table(ii)%nActivePatch
  172. CALL MPI_AllGather(min_count, 1, MPI_INTEGER, &
  173. count_buf, 1, MPI_INTEGER, &
  174. local_comm, Status)
  175. ! Work out the minimum no. of patches on any IO Server and whether
  176. ! or not we will have to enter independent IO mode.
  177. min_count = outpatch_table(ii)%nActivePatch
  178. DO jj=1,ntasks, 1
  179. IF(count_buf(jj) < min_count) min_count = count_buf(jj)
  180. IF(outpatch_table(ii)%nActivePatch /= count_buf(jj)) do_indep_write = .TRUE.
  181. END DO
  182. ! WRITE(mess,*) 'ARPDBG: Min. no. of patches is ', min_count
  183. ! CALL wrf_message(mess)
  184. ! WRITE(mess,*) 'ARPDBG: I have ',count_buf(mytask+1),' patches.'
  185. ! CALL wrf_message(mess)
  186. IF ( outpatch_table(ii)%FieldType .EQ. WRF_FLOAT ) THEN
  187. ! Loop over the patches in this field up to the number that
  188. ! every IO Server has. This is slightly tricky now
  189. ! that some of them may be 'deleted.'
  190. ipatch = 0
  191. icnt = 0
  192. DO WHILE ( icnt < min_count )
  193. ipatch = ipatch + 1
  194. IF(outpatch_table(ii)%PatchList(ipatch)%forDeletion) CYCLE
  195. icnt = icnt + 1
  196. WRITE (mess, "('Calling write for patch: ',I3, ' Start = ',3I4)") ipatch, outpatch_table(ii)%PatchList(ipatch)%PatchStart(1:3)
  197. CALL wrf_message(mess)
  198. WRITE (mess,"(29x,'End = ',3I4)") outpatch_table(ii)%PatchList(ipatch)%PatchEnd(1:3)
  199. CALL wrf_message(mess)
  200. CALL ext_pnc_write_field ( DataHandle , &
  201. TRIM(outpatch_table(ii)%DateStr), &
  202. TRIM(outpatch_table(ii)%VarName), &
  203. outpatch_table(ii)%PatchList(ipatch)%rptr, &
  204. outpatch_table(ii)%FieldType, &!*
  205. local_comm, local_comm, DomainDesc , &
  206. TRIM(outpatch_table(ii)%MemoryOrder), &
  207. TRIM(outpatch_table(ii)%Stagger), &!*
  208. outpatch_table(ii)%DimNames , &!*
  209. outpatch_table(ii)%DomainStart, &
  210. outpatch_table(ii)%DomainEnd, &
  211. ! ARP supply magic number as MemoryStart and
  212. ! MemoryEnd to signal that this routine is
  213. ! being called from quilting.
  214. -998899, &
  215. -998899, &
  216. outpatch_table(ii)%PatchList(ipatch)%PatchStart,&
  217. outpatch_table(ii)%PatchList(ipatch)%PatchEnd, &
  218. Status )
  219. ! Free memory associated with this patch
  220. DEALLOCATE(outpatch_table(ii)%PatchList(ipatch)%rptr)
  221. END DO
  222. IF( do_indep_write )THEN
  223. ! We must do the next few patches (if any) in independent IO
  224. ! mode as not all of the IO Servers have the same no. of
  225. ! patches.
  226. ! outpatch_table(ii)%nActivePatch holds the no. of live patches
  227. ! for this IO Server
  228. CALL ext_pnc_start_independent_mode(DataHandle, Status)
  229. DO WHILE ( icnt<outpatch_table(ii)%nActivePatch )
  230. ipatch = ipatch + 1
  231. IF(outpatch_table(ii)%PatchList(ipatch)%forDeletion) CYCLE
  232. icnt = icnt + 1
  233. CALL ext_pnc_write_field ( DataHandle , &
  234. TRIM(outpatch_table(ii)%DateStr), &
  235. TRIM(outpatch_table(ii)%VarName), &
  236. outpatch_table(ii)%PatchList(ipatch)%rptr, &
  237. outpatch_table(ii)%FieldType, &!*
  238. local_comm, local_comm, DomainDesc , &
  239. TRIM(outpatch_table(ii)%MemoryOrder), &
  240. TRIM(outpatch_table(ii)%Stagger), &!*
  241. outpatch_table(ii)%DimNames , &!*
  242. outpatch_table(ii)%DomainStart, &
  243. outpatch_table(ii)%DomainEnd, &
  244. ! ARP supply magic number as MemoryStart and
  245. ! MemoryEnd to signal that this routine is
  246. ! being called from quilting.
  247. -998899, &
  248. -998899, &
  249. outpatch_table(ii)%PatchList(ipatch)%PatchStart,&
  250. outpatch_table(ii)%PatchList(ipatch)%PatchEnd, &
  251. Status )
  252. ! Free memory associated with this patch
  253. DEALLOCATE(outpatch_table(ii)%PatchList(ipatch)%rptr)
  254. END DO
  255. ! End of patches that not every IO Server has so can switch
  256. ! back to collective mode.
  257. CALL ext_pnc_end_independent_mode(DataHandle, Status)
  258. END IF ! Additional patches
  259. ELSE IF ( outpatch_table(ii)%FieldType .EQ. WRF_INTEGER ) THEN
  260. ! Loop over the patches in this field up to the number that
  261. ! every IO Server has. This is slightly tricky now
  262. ! that some of them may be 'deleted.'
  263. ipatch = 0
  264. icnt = 0
  265. DO WHILE ( icnt < min_count )
  266. ipatch = ipatch + 1
  267. IF(outpatch_table(ii)%PatchList(ipatch)%forDeletion) CYCLE
  268. icnt = icnt + 1
  269. CALL ext_pnc_write_field ( DataHandle , &
  270. TRIM(outpatch_table(ii)%DateStr), &
  271. TRIM(outpatch_table(ii)%VarName), &
  272. outpatch_table(ii)%PatchList(ipatch)%iptr, &
  273. outpatch_table(ii)%FieldType, &!*
  274. local_comm, local_comm, DomainDesc, &
  275. TRIM(outpatch_table(ii)%MemoryOrder), &
  276. TRIM(outpatch_table(ii)%Stagger), &!*
  277. outpatch_table(ii)%DimNames , &!*
  278. outpatch_table(ii)%DomainStart, &
  279. outpatch_table(ii)%DomainEnd, &
  280. ! ARP supply magic number as MemoryStart and
  281. ! MemoryEnd to signal that this routine is
  282. ! being called from quilting.
  283. -998899, &
  284. -998899, &
  285. outpatch_table(ii)%PatchList(ipatch)%PatchStart, &
  286. outpatch_table(ii)%PatchList(ipatch)%PatchEnd, &
  287. Status )
  288. ! Free memory associated with this patch
  289. DEALLOCATE(outpatch_table(ii)%PatchList(ipatch)%iptr)
  290. END DO
  291. IF( do_indep_write )THEN
  292. ! We have to do the next few patches in independent IO mode as
  293. ! not all of the IO Servers have this many patches.
  294. ! outpatch_table(ii)%npatch holds the no. of live patches for
  295. ! this IO Server
  296. CALL ext_pnc_start_independent_mode(DataHandle, Status)
  297. DO WHILE ( icnt<outpatch_table(ii)%nActivePatch )
  298. ipatch = ipatch + 1
  299. IF(outpatch_table(ii)%PatchList(ipatch)%forDeletion) CYCLE
  300. icnt = icnt + 1
  301. CALL ext_pnc_write_field ( DataHandle , &
  302. TRIM(outpatch_table(ii)%DateStr), &
  303. TRIM(outpatch_table(ii)%VarName), &
  304. outpatch_table(ii)%PatchList(ipatch)%iptr, &
  305. outpatch_table(ii)%FieldType, &!*
  306. local_comm, local_comm, DomainDesc , &
  307. TRIM(outpatch_table(ii)%MemoryOrder), &
  308. TRIM(outpatch_table(ii)%Stagger), &!*
  309. outpatch_table(ii)%DimNames , &!*
  310. outpatch_table(ii)%DomainStart, &
  311. outpatch_table(ii)%DomainEnd, &
  312. ! ARP supply magic number as MemoryStart and
  313. ! MemoryEnd to signal that this routine is
  314. ! being called from quilting.
  315. -998899, &
  316. -998899, &
  317. outpatch_table(ii)%PatchList(ipatch)%PatchStart,&
  318. outpatch_table(ii)%PatchList(ipatch)%PatchEnd, &
  319. Status )
  320. ! Free memory associated with this patch
  321. DEALLOCATE(outpatch_table(ii)%PatchList(ipatch)%iptr)
  322. END DO
  323. ! End of patches that not every IO Server has so can switch
  324. ! back to collective mode.
  325. CALL ext_pnc_end_independent_mode(DataHandle, Status)
  326. ENDIF ! Have additional patches
  327. ENDIF
  328. CASE DEFAULT
  329. END SELECT
  330. ENDDO ! Loop over output buffers
  331. ! Reset the table of output buffers
  332. CALL init_outbuf()
  333. DEALLOCATE(count_buf)
  334. END SUBROUTINE write_outbuf_pnc
  335. #endif
  336. SUBROUTINE write_outbuf ( DataHandle , io_form_arg )
  337. !<DESCRIPTION>
  338. !<PRE>
  339. ! This routine writes all of the records stored in outbuf_table to the
  340. ! file referenced by DataHandle using format specified by io_form_arg.
  341. ! This routine calls the package-specific I/O routines to accomplish
  342. ! the write.
  343. ! It then re-initializes module data structures.
  344. !</PRE>
  345. !</DESCRIPTION>
  346. USE module_state_description
  347. IMPLICIT NONE
  348. #include "wrf_io_flags.h"
  349. INTEGER , INTENT(IN) :: DataHandle, io_form_arg
  350. INTEGER :: ii,ds1,de1,ds2,de2,ds3,de3
  351. INTEGER :: Comm, IOComm, DomainDesc ! dummy
  352. INTEGER :: Status
  353. CHARACTER*256 :: mess
  354. Comm = 0 ; IOComm = 0 ; DomainDesc = 0
  355. DO ii = 1, num_entries
  356. WRITE(mess,*)'writing ', &
  357. TRIM(outbuf_table(ii)%DateStr)," ", &
  358. TRIM(outbuf_table(ii)%VarName)," ", &
  359. TRIM(outbuf_table(ii)%MemoryOrder)
  360. ds1 = outbuf_table(ii)%DomainStart(1) ; de1 = outbuf_table(ii)%DomainEnd(1)
  361. ds2 = outbuf_table(ii)%DomainStart(2) ; de2 = outbuf_table(ii)%DomainEnd(2)
  362. ds3 = outbuf_table(ii)%DomainStart(3) ; de3 = outbuf_table(ii)%DomainEnd(3)
  363. SELECT CASE ( io_form_arg )
  364. #ifdef NETCDF
  365. CASE ( IO_NETCDF )
  366. IF ( outbuf_table(ii)%FieldType .EQ. WRF_FLOAT ) THEN
  367. CALL ext_ncd_write_field ( DataHandle , &
  368. TRIM(outbuf_table(ii)%DateStr), &
  369. TRIM(outbuf_table(ii)%VarName), &
  370. outbuf_table(ii)%rptr(ds1:de1,ds2:de2,ds3:de3), &
  371. outbuf_table(ii)%FieldType, & !*
  372. Comm, IOComm, DomainDesc , &
  373. TRIM(outbuf_table(ii)%MemoryOrder), &
  374. TRIM(outbuf_table(ii)%Stagger), & !*
  375. outbuf_table(ii)%DimNames , & !*
  376. outbuf_table(ii)%DomainStart, &
  377. outbuf_table(ii)%DomainEnd, &
  378. outbuf_table(ii)%DomainStart, &
  379. outbuf_table(ii)%DomainEnd, &
  380. outbuf_table(ii)%DomainStart, &
  381. outbuf_table(ii)%DomainEnd, &
  382. Status )
  383. ELSE IF ( outbuf_table(ii)%FieldType .EQ. WRF_INTEGER ) THEN
  384. CALL ext_ncd_write_field ( DataHandle , &
  385. TRIM(outbuf_table(ii)%DateStr), &
  386. TRIM(outbuf_table(ii)%VarName), &
  387. outbuf_table(ii)%iptr(ds1:de1,ds2:de2,ds3:de3), &
  388. outbuf_table(ii)%FieldType, & !*
  389. Comm, IOComm, DomainDesc , &
  390. TRIM(outbuf_table(ii)%MemoryOrder), &
  391. TRIM(outbuf_table(ii)%Stagger), & !*
  392. outbuf_table(ii)%DimNames , & !*
  393. outbuf_table(ii)%DomainStart, &
  394. outbuf_table(ii)%DomainEnd, &
  395. outbuf_table(ii)%DomainStart, &
  396. outbuf_table(ii)%DomainEnd, &
  397. outbuf_table(ii)%DomainStart, &
  398. outbuf_table(ii)%DomainEnd, &
  399. Status )
  400. ENDIF
  401. #endif
  402. #ifdef YYY
  403. CASE ( IO_YYY )
  404. IF ( outbuf_table(ii)%FieldType .EQ. WRF_FLOAT ) THEN
  405. CALL ext_yyy_write_field ( DataHandle , &
  406. TRIM(outbuf_table(ii)%DateStr), &
  407. TRIM(outbuf_table(ii)%VarName), &
  408. outbuf_table(ii)%rptr(ds1:de1,ds2:de2,ds3:de3), &
  409. outbuf_table(ii)%FieldType, & !*
  410. Comm, IOComm, DomainDesc , &
  411. TRIM(outbuf_table(ii)%MemoryOrder), &
  412. TRIM(outbuf_table(ii)%Stagger), & !*
  413. outbuf_table(ii)%DimNames , & !*
  414. outbuf_table(ii)%DomainStart, &
  415. outbuf_table(ii)%DomainEnd, &
  416. outbuf_table(ii)%DomainStart, &
  417. outbuf_table(ii)%DomainEnd, &
  418. outbuf_table(ii)%DomainStart, &
  419. outbuf_table(ii)%DomainEnd, &
  420. Status )
  421. ELSE IF ( outbuf_table(ii)%FieldType .EQ. WRF_INTEGER ) THEN
  422. CALL ext_yyy_write_field ( DataHandle , &
  423. TRIM(outbuf_table(ii)%DateStr), &
  424. TRIM(outbuf_table(ii)%VarName), &
  425. outbuf_table(ii)%iptr(ds1:de1,ds2:de2,ds3:de3), &
  426. outbuf_table(ii)%FieldType, & !*
  427. Comm, IOComm, DomainDesc , &
  428. TRIM(outbuf_table(ii)%MemoryOrder), &
  429. TRIM(outbuf_table(ii)%Stagger), & !*
  430. outbuf_table(ii)%DimNames , & !*
  431. outbuf_table(ii)%DomainStart, &
  432. outbuf_table(ii)%DomainEnd, &
  433. outbuf_table(ii)%DomainStart, &
  434. outbuf_table(ii)%DomainEnd, &
  435. outbuf_table(ii)%DomainStart, &
  436. outbuf_table(ii)%DomainEnd, &
  437. Status )
  438. ENDIF
  439. #endif
  440. #ifdef GRIB1
  441. CASE ( IO_GRIB1 )
  442. IF ( outbuf_table(ii)%FieldType .EQ. WRF_FLOAT ) THEN
  443. CALL ext_gr1_write_field ( DataHandle , &
  444. TRIM(outbuf_table(ii)%DateStr), &
  445. TRIM(outbuf_table(ii)%VarName), &
  446. outbuf_table(ii)%rptr(ds1:de1,ds2:de2,ds3:de3), &
  447. outbuf_table(ii)%FieldType, & !*
  448. Comm, IOComm, DomainDesc , &
  449. TRIM(outbuf_table(ii)%MemoryOrder), &
  450. TRIM(outbuf_table(ii)%Stagger), & !*
  451. outbuf_table(ii)%DimNames , & !*
  452. outbuf_table(ii)%DomainStart, &
  453. outbuf_table(ii)%DomainEnd, &
  454. outbuf_table(ii)%DomainStart, &
  455. outbuf_table(ii)%DomainEnd, &
  456. outbuf_table(ii)%DomainStart, &
  457. outbuf_table(ii)%DomainEnd, &
  458. Status )
  459. ELSE IF ( outbuf_table(ii)%FieldType .EQ. WRF_INTEGER ) THEN
  460. CALL ext_gr1_write_field ( DataHandle , &
  461. TRIM(outbuf_table(ii)%DateStr), &
  462. TRIM(outbuf_table(ii)%VarName), &
  463. outbuf_table(ii)%iptr(ds1:de1,ds2:de2,ds3:de3), &
  464. outbuf_table(ii)%FieldType, & !*
  465. Comm, IOComm, DomainDesc , &
  466. TRIM(outbuf_table(ii)%MemoryOrder), &
  467. TRIM(outbuf_table(ii)%Stagger), & !*
  468. outbuf_table(ii)%DimNames , & !*
  469. outbuf_table(ii)%DomainStart, &
  470. outbuf_table(ii)%DomainEnd, &
  471. outbuf_table(ii)%DomainStart, &
  472. outbuf_table(ii)%DomainEnd, &
  473. outbuf_table(ii)%DomainStart, &
  474. outbuf_table(ii)%DomainEnd, &
  475. Status )
  476. ENDIF
  477. #endif
  478. #ifdef GRIB2
  479. CASE ( IO_GRIB2 )
  480. IF ( outbuf_table(ii)%FieldType .EQ. WRF_FLOAT ) THEN
  481. CALL ext_gr2_write_field ( DataHandle , &
  482. TRIM(outbuf_table(ii)%DateStr), &
  483. TRIM(outbuf_table(ii)%VarName), &
  484. outbuf_table(ii)%rptr(ds1:de1,ds2:de2,ds3:de3), &
  485. outbuf_table(ii)%FieldType, & !*
  486. Comm, IOComm, DomainDesc , &
  487. TRIM(outbuf_table(ii)%MemoryOrder), &
  488. TRIM(outbuf_table(ii)%Stagger), & !*
  489. outbuf_table(ii)%DimNames , & !*
  490. outbuf_table(ii)%DomainStart, &
  491. outbuf_table(ii)%DomainEnd, &
  492. outbuf_table(ii)%DomainStart, &
  493. outbuf_table(ii)%DomainEnd, &
  494. outbuf_table(ii)%DomainStart, &
  495. outbuf_table(ii)%DomainEnd, &
  496. Status )
  497. ELSE IF ( outbuf_table(ii)%FieldType .EQ. WRF_INTEGER ) THEN
  498. CALL ext_gr2_write_field ( DataHandle , &
  499. TRIM(outbuf_table(ii)%DateStr), &
  500. TRIM(outbuf_table(ii)%VarName), &
  501. outbuf_table(ii)%iptr(ds1:de1,ds2:de2,ds3:de3), &
  502. outbuf_table(ii)%FieldType, & !*
  503. Comm, IOComm, DomainDesc , &
  504. TRIM(outbuf_table(ii)%MemoryOrder), &
  505. TRIM(outbuf_table(ii)%Stagger), & !*
  506. outbuf_table(ii)%DimNames , & !*
  507. outbuf_table(ii)%DomainStart, &
  508. outbuf_table(ii)%DomainEnd, &
  509. outbuf_table(ii)%DomainStart, &
  510. outbuf_table(ii)%DomainEnd, &
  511. outbuf_table(ii)%DomainStart, &
  512. outbuf_table(ii)%DomainEnd, &
  513. Status )
  514. ENDIF
  515. #endif
  516. #ifdef INTIO
  517. CASE ( IO_INTIO )
  518. IF ( outbuf_table(ii)%FieldType .EQ. WRF_FLOAT ) THEN
  519. CALL ext_int_write_field ( DataHandle , &
  520. TRIM(outbuf_table(ii)%DateStr), &
  521. TRIM(outbuf_table(ii)%VarName), &
  522. outbuf_table(ii)%rptr(ds1:de1,ds2:de2,ds3:de3), &
  523. outbuf_table(ii)%FieldType, & !*
  524. Comm, IOComm, DomainDesc , &
  525. TRIM(outbuf_table(ii)%MemoryOrder), &
  526. TRIM(outbuf_table(ii)%Stagger), & !*
  527. outbuf_table(ii)%DimNames , & !*
  528. outbuf_table(ii)%DomainStart, &
  529. outbuf_table(ii)%DomainEnd, &
  530. outbuf_table(ii)%DomainStart, &
  531. outbuf_table(ii)%DomainEnd, &
  532. outbuf_table(ii)%DomainStart, &
  533. outbuf_table(ii)%DomainEnd, &
  534. Status )
  535. ELSE IF ( outbuf_table(ii)%FieldType .EQ. WRF_INTEGER ) THEN
  536. CALL ext_int_write_field ( DataHandle , &
  537. TRIM(outbuf_table(ii)%DateStr), &
  538. TRIM(outbuf_table(ii)%VarName), &
  539. outbuf_table(ii)%iptr(ds1:de1,ds2:de2,ds3:de3), &
  540. outbuf_table(ii)%FieldType, & !*
  541. Comm, IOComm, DomainDesc , &
  542. TRIM(outbuf_table(ii)%MemoryOrder), &
  543. TRIM(outbuf_table(ii)%Stagger), & !*
  544. outbuf_table(ii)%DimNames , & !*
  545. outbuf_table(ii)%DomainStart, &
  546. outbuf_table(ii)%DomainEnd, &
  547. outbuf_table(ii)%DomainStart, &
  548. outbuf_table(ii)%DomainEnd, &
  549. outbuf_table(ii)%DomainStart, &
  550. outbuf_table(ii)%DomainEnd, &
  551. Status )
  552. ENDIF
  553. #endif
  554. CASE DEFAULT
  555. END SELECT
  556. IF ( ASSOCIATED( outbuf_table(ii)%rptr) ) DEALLOCATE(outbuf_table(ii)%rptr)
  557. IF ( ASSOCIATED( outbuf_table(ii)%iptr) ) DEALLOCATE(outbuf_table(ii)%iptr)
  558. NULLIFY( outbuf_table(ii)%rptr )
  559. NULLIFY( outbuf_table(ii)%iptr )
  560. ENDDO
  561. CALL init_outbuf
  562. END SUBROUTINE write_outbuf
  563. SUBROUTINE stitch_outbuf_patches(ibuf)
  564. USE module_timing
  565. IMPLICIT none
  566. INTEGER, INTENT(in) :: ibuf
  567. !<DESCRIPTION>
  568. !<PRE>
  569. ! This routine does the "output quilting" for the case where quilting has been
  570. ! built to use Parallel NetCDF. Unlike store_patch_in_outbuf() we do not have
  571. ! data for the whole domain --- instead we aim to quilt as much of the data as
  572. ! possible in order to reduce the number of separate writes that we must do.
  573. !</PRE>
  574. !</DESCRIPTION>
  575. #include "wrf_io_flags.h"
  576. INTEGER :: ipatch, jpatch, ii
  577. INTEGER :: ierr
  578. INTEGER :: npatches
  579. INTEGER, DIMENSION(3) :: newExtent, pos
  580. INTEGER, ALLOCATABLE, DIMENSION(:,:) :: OldPatchStart
  581. INTEGER, POINTER, DIMENSION(:,:,:) :: ibuffer
  582. REAL, POINTER, DIMENSION(:,:,:) :: rbuffer
  583. CHARACTER*256 :: mess
  584. integer i,j
  585. ! CALL start_timing()
  586. IF(LEN_TRIM(outpatch_table(ibuf)%MemoryOrder) < 2)THEN
  587. ! This field is a scalar or 1D array. Such quantities are replicated
  588. ! across compute nodes and therefore we need only keep a single
  589. ! patch - delete all but the first in the list
  590. IF ( outpatch_table(ibuf)%FieldType .EQ. WRF_FLOAT ) THEN
  591. DO jpatch=2,outpatch_table(ibuf)%npatch,1
  592. outpatch_table(ibuf)%PatchList(jpatch)%forDeletion = .TRUE.
  593. outpatch_table(ibuf)%nActivePatch = &
  594. outpatch_table(ibuf)%nActivePatch - 1
  595. DEALLOCATE(outpatch_table(ibuf)%PatchList(jpatch)%rptr)
  596. END DO
  597. ELSE IF ( outpatch_table(ibuf)%FieldType .EQ. WRF_INTEGER ) THEN
  598. DO jpatch=2,outpatch_table(ibuf)%npatch,1
  599. outpatch_table(ibuf)%PatchList(jpatch)%forDeletion = .TRUE.
  600. outpatch_table(ibuf)%nActivePatch = &
  601. outpatch_table(ibuf)%nActivePatch - 1
  602. DEALLOCATE(outpatch_table(ibuf)%PatchList(jpatch)%iptr)
  603. END DO
  604. ELSE
  605. CALL wrf_error_fatal("stitch_outbuf_patches: unrecognised Field Type")
  606. END IF
  607. ! CALL end_timing("stitch_outbuf_patches: deleting replicated patches")
  608. RETURN
  609. END IF ! Field is scalar or 1D
  610. ! Otherwise, this field _is_ distributed across compute PEs and therefore
  611. ! it's worth trying to stitch patches together...
  612. ALLOCATE(OldPatchStart(3,outpatch_table(ibuf)%npatch), &
  613. JoinedPatches(outpatch_table(ibuf)%npatch, &
  614. outpatch_table(ibuf)%npatch), &
  615. PatchCount(outpatch_table(ibuf)%npatch), &
  616. Stat=ierr)
  617. IF(ierr /= 0)THEN
  618. CALL wrf_message('stitch_outbuf_patches: unable to stitch patches as allocate failed.')
  619. RETURN
  620. END IF
  621. JoinedPatches(:,:) = -1
  622. ! Initialise these arrays to catch failures in the above allocate on
  623. ! linux-based systems (e.g. Cray XE) where allocation only actually
  624. ! performed when requested memory is touched.
  625. PatchCount(:) = 0
  626. OldPatchStart(:,:) = 0
  627. NULLIFY(ibuffer)
  628. NULLIFY(rbuffer)
  629. DO jpatch=1,outpatch_table(ibuf)%npatch,1
  630. ! Each patch consists of just itself initially
  631. JoinedPatches(1,jpatch) = jpatch
  632. PatchCount(jpatch) = 1
  633. ! Store the location of each patch for use after we've decided how to
  634. ! stitch them together
  635. OldPatchStart(:,jpatch) = outpatch_table(ibuf)%PatchList(jpatch)%PatchStart(:)
  636. END DO
  637. ! Search through patches to find pairs that we can stitch together
  638. ipatch = 1
  639. OUTER: DO WHILE(ipatch < outpatch_table(ibuf)%npatch)
  640. IF( outpatch_table(ibuf)%PatchList(ipatch)%forDeletion )THEN
  641. ipatch = ipatch + 1
  642. CYCLE OUTER
  643. END IF
  644. INNER: DO jpatch=ipatch+1,outpatch_table(ibuf)%npatch,1
  645. IF(outpatch_table(ibuf)%PatchList(jpatch)%forDeletion )THEN
  646. CYCLE INNER
  647. END IF
  648. ! Look for patches that can be concatenated with ipatch in the first
  649. ! dimension (preferred since that is contiguous in memory in F90)
  650. ! ________________ ____________
  651. ! | | | |
  652. ! Startx(j) Endx(j) Startx(i) Endx(i)
  653. !
  654. IF(outpatch_table(ibuf)%PatchList(jpatch)%PatchEnd(1) == &
  655. (outpatch_table(ibuf)%PatchList(ipatch)%PatchStart(1) - 1) )THEN
  656. ! Patches contiguous in first dimension - do they have the same
  657. ! extents in the other two dimensions?
  658. IF( (outpatch_table(ibuf)%PatchList(jpatch)%PatchStart(2)== &
  659. outpatch_table(ibuf)%PatchList(ipatch)%PatchStart(2) ) .AND.&
  660. (outpatch_table(ibuf)%PatchList(jpatch)%PatchEnd(2) == &
  661. outpatch_table(ibuf)%PatchList(ipatch)%PatchEnd(2) ) .AND.&
  662. (outpatch_table(ibuf)%PatchList(jpatch)%PatchStart(3)== &
  663. outpatch_table(ibuf)%PatchList(ipatch)%PatchStart(3) ) .AND.&
  664. (outpatch_table(ibuf)%PatchList(jpatch)%PatchEnd(3) == &
  665. outpatch_table(ibuf)%PatchList(ipatch)%PatchEnd(3)) )THEN
  666. ! We can concatenate these two patches in first dimension
  667. ! WRITE(mess,"('Can concatenate patches ',I3,' and ',I3,' in dim 1')") ipatch, jpatch
  668. ! CALL wrf_message(mess)
  669. ! Grow patch ipatch to include jpatch
  670. outpatch_table(ibuf)%PatchList(ipatch)%PatchStart(1) = &
  671. outpatch_table(ibuf)%PatchList(jpatch)%PatchStart(1)
  672. CALL merge_patches(ibuf, ipatch, jpatch)
  673. ! Go again...
  674. ipatch = 1
  675. CYCLE OUTER
  676. END IF
  677. END IF
  678. ! ______________ ____________
  679. ! | | | |
  680. ! Startx(i) Endx(i) Startx(j) Endx(j)
  681. !
  682. IF(outpatch_table(ibuf)%PatchList(jpatch)%PatchStart(1) == &
  683. (outpatch_table(ibuf)%PatchList(ipatch)%PatchEnd(1) + 1))THEN
  684. ! Patches contiguous in first dimension - do they have the same
  685. ! extents in the other two dimensions?
  686. IF( (outpatch_table(ibuf)%PatchList(jpatch)%PatchStart(2)== &
  687. outpatch_table(ibuf)%PatchList(ipatch)%PatchStart(2) ) .AND.&
  688. (outpatch_table(ibuf)%PatchList(jpatch)%PatchEnd(2) == &
  689. outpatch_table(ibuf)%PatchList(ipatch)%PatchEnd(2) ) .AND.&
  690. (outpatch_table(ibuf)%PatchList(jpatch)%PatchStart(3)== &
  691. outpatch_table(ibuf)%PatchList(ipatch)%PatchStart(3) ) .AND.&
  692. (outpatch_table(ibuf)%PatchList(jpatch)%PatchEnd(3) == &
  693. outpatch_table(ibuf)%PatchList(ipatch)%PatchEnd(3)) )THEN
  694. ! We can concatenate these two patches in first dimension
  695. ! WRITE(mess,"('Can concatenate patches ',I3,' and ',I3,' in dim 1')") ipatch, jpatch
  696. ! CALL wrf_message(mess)
  697. ! Grow patch ipatch to include jpatch
  698. outpatch_table(ibuf)%PatchList(ipatch)%PatchEnd(1) = &
  699. outpatch_table(ibuf)%PatchList(jpatch)%PatchEnd(1)
  700. CALL merge_patches(ibuf, ipatch, jpatch)
  701. ! Go again...
  702. ipatch = 1
  703. CYCLE OUTER
  704. END IF
  705. END IF
  706. ! Try the second dimension
  707. IF(outpatch_table(ibuf)%PatchList(jpatch)%PatchEnd(2) == &
  708. (outpatch_table(ibuf)%PatchList(ipatch)%PatchStart(2) - 1))THEN
  709. ! Patches contiguous in second dimension - do they have the same
  710. ! extents in the other two dimensions?
  711. IF( (outpatch_table(ibuf)%PatchList(jpatch)%PatchStart(1)== &
  712. outpatch_table(ibuf)%PatchList(ipatch)%PatchStart(1) ) .AND.&
  713. (outpatch_table(ibuf)%PatchList(jpatch)%PatchEnd(1) == &
  714. outpatch_table(ibuf)%PatchList(ipatch)%PatchEnd(1) ) .AND.&
  715. (outpatch_table(ibuf)%PatchList(jpatch)%PatchStart(3)== &
  716. outpatch_table(ibuf)%PatchList(ipatch)%PatchStart(3) ) .AND.&
  717. (outpatch_table(ibuf)%PatchList(jpatch)%PatchEnd(3) == &
  718. outpatch_table(ibuf)%PatchList(ipatch)%PatchEnd(3)) )THEN
  719. ! We can concatenate these two patches in second dimension
  720. ! WRITE(mess,"('Can concatenate patches ',I3,' and ',I3,' in dim 2')") ipatch, jpatch
  721. ! CALL wrf_message(mess)
  722. ! Grow patch ipatch to include jpatch
  723. outpatch_table(ibuf)%PatchList(ipatch)%PatchStart(2) = &
  724. outpatch_table(ibuf)%PatchList(jpatch)%PatchStart(2)
  725. CALL merge_patches(ibuf, ipatch, jpatch)
  726. ! Go again...
  727. ipatch = 1
  728. CYCLE OUTER
  729. END IF
  730. END IF
  731. IF(outpatch_table(ibuf)%PatchList(jpatch)%PatchStart(2) == &
  732. (outpatch_table(ibuf)%PatchList(ipatch)%PatchEnd(2) + 1) )THEN
  733. ! Patches contiguous in second dimension - do they have the same
  734. ! extents in the other two dimensions?
  735. IF( (outpatch_table(ibuf)%PatchList(jpatch)%PatchStart(1)== &
  736. outpatch_table(ibuf)%PatchList(ipatch)%PatchStart(1) ) .AND.&
  737. (outpatch_table(ibuf)%PatchList(jpatch)%PatchEnd(1) == &
  738. outpatch_table(ibuf)%PatchList(ipatch)%PatchEnd(1) ) .AND.&
  739. (outpatch_table(ibuf)%PatchList(jpatch)%PatchStart(3)== &
  740. outpatch_table(ibuf)%PatchList(ipatch)%PatchStart(3) ) .AND.&
  741. (outpatch_table(ibuf)%PatchList(jpatch)%PatchEnd(3) == &
  742. outpatch_table(ibuf)%PatchList(ipatch)%PatchEnd(3)) )THEN
  743. ! We can concatenate these two patches in second dimension
  744. ! WRITE(mess,"('Can concatenate patches ',I3,' and ',I3,' in dim 2')") ipatch, jpatch
  745. ! CALL wrf_message(mess)
  746. ! Grow patch ipatch to include jpatch
  747. outpatch_table(ibuf)%PatchList(ipatch)%PatchEnd(2) = &
  748. outpatch_table(ibuf)%PatchList(jpatch)%PatchEnd(2)
  749. CALL merge_patches(ibuf, ipatch, jpatch)
  750. ! Go again...
  751. ipatch = 1
  752. CYCLE OUTER
  753. END IF
  754. END IF
  755. ! Try the third dimension
  756. IF(outpatch_table(ibuf)%PatchList(jpatch)%PatchEnd(3) == &
  757. (outpatch_table(ibuf)%PatchList(ipatch)%PatchStart(3) - 1) )THEN
  758. ! Patches contiguous in second dimension - do they have the same
  759. ! extents in the other two dimensions?
  760. IF( (outpatch_table(ibuf)%PatchList(jpatch)%PatchStart(1)== &
  761. outpatch_table(ibuf)%PatchList(ipatch)%PatchStart(1) ) .AND.&
  762. (outpatch_table(ibuf)%PatchList(jpatch)%PatchEnd(1) == &
  763. outpatch_table(ibuf)%PatchList(ipatch)%PatchEnd(1) ) .AND.&
  764. (outpatch_table(ibuf)%PatchList(jpatch)%PatchStart(2)== &
  765. outpatch_table(ibuf)%PatchList(ipatch)%PatchStart(2) ) .AND.&
  766. (outpatch_table(ibuf)%PatchList(jpatch)%PatchEnd(2) == &
  767. outpatch_table(ibuf)%PatchList(ipatch)%PatchEnd(2)) )THEN
  768. ! We can concatenate these two patches in the third dimension
  769. ! WRITE(mess,"('Can concatenate patches ',I3,' and ',I3,' in dim 3')") ipatch, jpatch
  770. ! CALL wrf_message(mess)
  771. ! Grow patch ipatch to include jpatch
  772. outpatch_table(ibuf)%PatchList(ipatch)%PatchStart(3) = &
  773. outpatch_table(ibuf)%PatchList(jpatch)%PatchStart(3)
  774. CALL merge_patches(ibuf, ipatch, jpatch)
  775. ! Go again...
  776. ipatch = 1
  777. CYCLE OUTER
  778. END IF
  779. END IF
  780. IF(outpatch_table(ibuf)%PatchList(jpatch)%PatchStart(3) == &
  781. (outpatch_table(ibuf)%PatchList(ipatch)%PatchEnd(3) + 1))THEN
  782. ! Patches contiguous in second dimension - do they have the same
  783. ! extents in the other two dimensions?
  784. IF( (outpatch_table(ibuf)%PatchList(jpatch)%PatchStart(1)== &
  785. outpatch_table(ibuf)%PatchList(ipatch)%PatchStart(1) ) .AND.&
  786. (outpatch_table(ibuf)%PatchList(jpatch)%PatchEnd(1) == &
  787. outpatch_table(ibuf)%PatchList(ipatch)%PatchEnd(1) ) .AND.&
  788. (outpatch_table(ibuf)%PatchList(jpatch)%PatchStart(2)== &
  789. outpatch_table(ibuf)%PatchList(ipatch)%PatchStart(2) ) .AND.&
  790. (outpatch_table(ibuf)%PatchList(jpatch)%PatchEnd(2) == &
  791. outpatch_table(ibuf)%PatchList(ipatch)%PatchEnd(2)) )THEN
  792. ! We can concatenate these two patches in the third dimension
  793. ! WRITE(mess,"('Can concatenate patches ',I3,' and ',I3,' in dim 3')") ipatch, jpatch
  794. ! CALL wrf_message(mess)
  795. ! Grow patch ipatch to include jpatch
  796. outpatch_table(ibuf)%PatchList(ipatch)%PatchEnd(3) = &
  797. outpatch_table(ibuf)%PatchList(jpatch)%PatchEnd(3)
  798. CALL merge_patches(ibuf, ipatch, jpatch)
  799. ! Go again...
  800. ipatch = 1
  801. CYCLE OUTER
  802. END IF
  803. END IF
  804. END DO INNER
  805. ipatch = ipatch + 1
  806. END DO OUTER
  807. npatches = 0
  808. DO jpatch=1,outpatch_table(ibuf)%npatch,1
  809. IF ( outpatch_table(ibuf)%PatchList(jpatch)%forDeletion ) CYCLE
  810. ! WRITE(mess,"('Patch ',I3,': [',I3,': ',I3,'],[',I3,':',I3,'],[',I3,':',I3,']')") jpatch, outpatch_table(ibuf)%PatchList(jpatch)%PatchStart(1), &
  811. ! outpatch_table(ibuf)%PatchList(jpatch)%PatchEnd(1), &
  812. ! outpatch_table(ibuf)%PatchList(jpatch)%PatchStart(2), &
  813. ! outpatch_table(ibuf)%PatchList(jpatch)%PatchEnd(2), &
  814. ! outpatch_table(ibuf)%PatchList(jpatch)%PatchStart(3), &
  815. ! outpatch_table(ibuf)%PatchList(jpatch)%PatchEnd(3)
  816. ! CALL wrf_message(mess)
  817. ! Count how many patches we're left with
  818. npatches = npatches + 1
  819. ! If no patches have been merged together to make this patch then we
  820. ! don't have to do any more with it
  821. IF(PatchCount(jpatch) == 1) CYCLE
  822. ! Get the extent of this patch
  823. newExtent(:) = outpatch_table(ibuf)%PatchList(jpatch)%PatchEnd(:) - &
  824. outpatch_table(ibuf)%PatchList(jpatch)%PatchStart(:) + 1
  825. ! Allocate a buffer to hold all of its data
  826. IF ( outpatch_table(ibuf)%FieldType .EQ. WRF_FLOAT ) THEN
  827. ALLOCATE(rbuffer(newExtent(1), newExtent(2), newExtent(3)), &
  828. Stat=ierr)
  829. ELSE IF ( outpatch_table(ibuf)%FieldType .EQ. WRF_INTEGER ) THEN
  830. ALLOCATE(ibuffer(newExtent(1), newExtent(2), newExtent(3)), &
  831. Stat=ierr)
  832. END IF
  833. IF(ierr /= 0)THEN
  834. CALL wrf_error_fatal('stitch_outbuf_patches: unable to stitch patches as allocate for merge buffer failed.')
  835. RETURN
  836. END IF
  837. ! Copy data into this buffer from each of the patches that are being
  838. ! stitched together
  839. IF( ASSOCIATED(rbuffer) )THEN
  840. ! CALL start_timing()
  841. DO ipatch=1,PatchCount(jpatch),1
  842. ii = JoinedPatches(ipatch, jpatch)
  843. ! Work out where to put it - the PatchList(i)%PatchStart() has been
  844. ! updated to hold the start of the newly quilted patch i. It will
  845. ! therefore be less than or equal to the starts of each of the
  846. ! constituent patches.
  847. pos(:) = OldPatchStart(:,ii) - &
  848. outpatch_table(ibuf)%PatchList(jpatch)%PatchStart(:) + 1
  849. ! Do the copy - can use the PatchExtent data here because that
  850. ! wasn't modified during the stitching of the patches.
  851. rbuffer(pos(1): pos(1)+outpatch_table(ibuf)%PatchList(ii)%PatchExtent(1)-1, &
  852. pos(2): pos(2)+outpatch_table(ibuf)%PatchList(ii)%PatchExtent(2)-1, &
  853. pos(3): pos(3)+outpatch_table(ibuf)%PatchList(ii)%PatchExtent(3)-1 ) &
  854. = &
  855. outpatch_table(ibuf)%PatchList(ii)%rptr(:, :, :)
  856. ! Having copied the data from this patch, we can free-up the
  857. ! associated buffer
  858. DEALLOCATE(outpatch_table(ibuf)%PatchList(ii)%rptr)
  859. END DO
  860. ! CALL end_timing("Data copy into new real patch")
  861. ! Re-assign the pointer associated with this patch to the new,
  862. ! larger, buffer containing the quilted patches
  863. outpatch_table(ibuf)%PatchList(jpatch)%rptr => rbuffer
  864. ! Unset the original pointer to this buffer
  865. NULLIFY(rbuffer)
  866. ELSE IF( ASSOCIATED(ibuffer) )THEN
  867. ! CALL start_timing()
  868. DO ipatch=1,PatchCount(jpatch),1
  869. ii = JoinedPatches(ipatch, jpatch)
  870. ! Work out where to put it
  871. pos(:) = OldPatchStart(:,ii) - &
  872. outpatch_table(ibuf)%PatchList(jpatch)%PatchStart(:) + 1
  873. ! Do the copy - can use the PatchExtent data here because that
  874. ! wasn't modified during the stitching of the patches.
  875. ibuffer(pos(1): &
  876. pos(1)+outpatch_table(ibuf)%PatchList(ii)%PatchExtent(1)-1, &
  877. pos(2): &
  878. pos(2)+outpatch_table(ibuf)%PatchList(ii)%PatchExtent(2)-1, &
  879. pos(3): &
  880. pos(3)+outpatch_table(ibuf)%PatchList(ii)%PatchExtent(3)-1 ) = &
  881. outpatch_table(ibuf)%PatchList(ii)%iptr(:, :, :)
  882. DEALLOCATE(outpatch_table(ibuf)%PatchList(ii)%iptr)
  883. END DO
  884. ! CALL end_timing("Data copy into new integer patch")
  885. ! Re-assign the pointer associated with this patch to the new,
  886. ! larger, buffer containing the quilted patches
  887. outpatch_table(ibuf)%PatchList(jpatch)%iptr => ibuffer
  888. NULLIFY(ibuffer)
  889. END IF
  890. END DO
  891. WRITE(mess,*) "--------------------------"
  892. CALL wrf_message(mess)
  893. ! Record how many patches we're left with
  894. outpatch_table(ibuf)%nPatch = npatches
  895. DEALLOCATE(OldPatchStart, JoinedPatches, PatchCount)
  896. ! CALL end_timing("stitch patches")
  897. END SUBROUTINE stitch_outbuf_patches
  898. !-------------------------------------------------------------------------
  899. SUBROUTINE merge_patches(itab, ipatch, jpatch)
  900. INTEGER, INTENT(in) :: itab, ipatch, jpatch
  901. ! Merge patch jpatch into patch ipatch and then 'delete' jpatch
  902. INTEGER :: ii
  903. ! Keep track of which patches we've merged: ipatch takes
  904. ! on all of the original patches which currently make up
  905. ! jpatch.
  906. DO ii=1,PatchCount(jpatch),1
  907. PatchCount(ipatch) = PatchCount(ipatch) + 1
  908. JoinedPatches(PatchCount(ipatch),ipatch) = JoinedPatches(ii,jpatch)
  909. END DO
  910. ! and mark patch jpatch for deletion
  911. outpatch_table(itab)%PatchList(jpatch)%forDeletion = .TRUE.
  912. ! decrement the count of active patches
  913. outpatch_table(itab)%nActivePatch = outpatch_table(itab)%nActivePatch - 1
  914. END SUBROUTINE merge_patches
  915. END MODULE module_quilt_outbuf_ops
  916. ! don't let other programs see the definition of this; type mismatches
  917. ! on inbuf will result; may want to make a module program at some point
  918. SUBROUTINE store_patch_in_outbuf( inbuf_r, inbuf_i, DateStr, VarName , FieldType, MemoryOrder, Stagger, DimNames, &
  919. DomainStart , DomainEnd , &
  920. MemoryStart , MemoryEnd , &
  921. PatchStart , PatchEnd )
  922. !<DESCRIPTION>
  923. !<PRE>
  924. ! This routine does the "output quilting".
  925. !
  926. ! It stores a patch in the appropriate location in a domain-sized array
  927. ! within an element of the outbuf_table data structure. DateStr, VarName, and
  928. ! MemoryOrder are used to uniquely identify which element of outbuf_table is
  929. ! associated with this array. If no element is associated, then this routine
  930. ! first assigns an unused element and allocates space within that element for
  931. ! the globally-sized array. This routine also stores DateStr, VarName,
  932. ! FieldType, MemoryOrder, Stagger, DimNames, DomainStart, and DomainEnd within
  933. ! the same element of outbuf.
  934. !</PRE>
  935. !</DESCRIPTION>
  936. USE module_quilt_outbuf_ops
  937. IMPLICIT NONE
  938. #include "wrf_io_flags.h"
  939. INTEGER , INTENT(IN) :: FieldType
  940. REAL , DIMENSION(*) , INTENT(IN) :: inbuf_r
  941. INTEGER , DIMENSION(*) , INTENT(IN) :: inbuf_i
  942. INTEGER , DIMENSION(3) , INTENT(IN) :: DomainStart , DomainEnd , MemoryStart , MemoryEnd , PatchStart , PatchEnd
  943. CHARACTER*(*) , INTENT(IN) :: DateStr , VarName, MemoryOrder , Stagger, DimNames(3)
  944. ! Local
  945. CHARACTER*256 :: mess
  946. INTEGER :: l,m,n,ii,jj
  947. LOGICAL :: found
  948. ! Find the VarName if it's in the buffer already
  949. ii = 1
  950. found = .false.
  951. DO WHILE ( .NOT. found .AND. ii .LE. num_entries )
  952. !TBH: need to test other attributes too!
  953. IF ( TRIM(VarName) .EQ. TRIM(outbuf_table(ii)%VarName) ) THEN
  954. IF ( TRIM(DateStr) .EQ. TRIM(outbuf_table(ii)%DateStr) ) THEN
  955. IF ( TRIM(MemoryOrder) .EQ. TRIM(outbuf_table(ii)%MemoryOrder) ) THEN
  956. found = .true.
  957. ELSE
  958. CALL wrf_error_fatal("store_patch_in_outbuf: memory order disagreement")
  959. ENDIF
  960. ELSE
  961. CALL wrf_error_fatal("store_patch_in_outbuf: multiple dates in buffer")
  962. ENDIF
  963. ELSE
  964. ii = ii + 1
  965. ENDIF
  966. ENDDO
  967. IF ( .NOT. found ) THEN
  968. num_entries = num_entries + 1
  969. IF ( FieldType .EQ. WRF_FLOAT ) THEN
  970. ALLOCATE( outbuf_table(num_entries)%rptr(DomainStart(1):DomainEnd(1), &
  971. DomainStart(2):DomainEnd(2),DomainStart(3):DomainEnd(3)) )
  972. ELSE IF ( FieldType .EQ. WRF_INTEGER ) THEN
  973. ALLOCATE( outbuf_table(num_entries)%iptr(DomainStart(1):DomainEnd(1), &
  974. DomainStart(2):DomainEnd(2),DomainStart(3):DomainEnd(3)) )
  975. ELSE
  976. write(mess,*)"store_patch_in_outbuf: unsupported type ", FieldType
  977. CALL wrf_error_fatal(mess)
  978. ENDIF
  979. outbuf_table(num_entries)%VarName = TRIM(VarName)
  980. outbuf_table(num_entries)%DateStr = TRIM(DateStr)
  981. outbuf_table(num_entries)%MemoryOrder = TRIM(MemoryOrder)
  982. outbuf_table(num_entries)%Stagger = TRIM(Stagger)
  983. outbuf_table(num_entries)%DimNames(1) = TRIM(DimNames(1))
  984. outbuf_table(num_entries)%DimNames(2) = TRIM(DimNames(2))
  985. outbuf_table(num_entries)%DimNames(3) = TRIM(DimNames(3))
  986. outbuf_table(num_entries)%DomainStart = DomainStart
  987. outbuf_table(num_entries)%DomainEnd = DomainEnd
  988. outbuf_table(num_entries)%FieldType = FieldType
  989. ii = num_entries
  990. ENDIF
  991. jj = 1
  992. IF ( FieldType .EQ. WRF_FLOAT ) THEN
  993. DO n = PatchStart(3),PatchEnd(3)
  994. DO m = PatchStart(2),PatchEnd(2)
  995. DO l = PatchStart(1),PatchEnd(1)
  996. outbuf_table(ii)%rptr(l,m,n) = inbuf_r(jj)
  997. jj = jj + 1
  998. ENDDO
  999. ENDDO
  1000. ENDDO
  1001. ENDIF
  1002. IF ( FieldType .EQ. WRF_INTEGER ) THEN
  1003. DO n = PatchStart(3),PatchEnd(3)
  1004. DO m = PatchStart(2),PatchEnd(2)
  1005. DO l = PatchStart(1),PatchEnd(1)
  1006. outbuf_table(ii)%iptr(l,m,n) = inbuf_i(jj)
  1007. jj = jj + 1
  1008. ENDDO
  1009. ENDDO
  1010. ENDDO
  1011. ENDIF
  1012. RETURN
  1013. END SUBROUTINE store_patch_in_outbuf
  1014. ! don't let other programs see the definition of this; type mismatches
  1015. ! on inbuf will result; may want to make a module program at some point
  1016. SUBROUTINE store_patch_in_outbuf_pnc( inbuf_r, inbuf_i, DateStr, VarName , &
  1017. FieldType, MemoryOrder, Stagger, &
  1018. DimNames , &
  1019. DomainStart , DomainEnd , &
  1020. MemoryStart , MemoryEnd , &
  1021. PatchStart , PatchEnd , &
  1022. ntasks )
  1023. !<DESCRIPTION>
  1024. !<PRE>
  1025. ! This routine stores a patch in an array within an element of the
  1026. ! outpatch_table%PatchList data structure. DateStr, VarName, and
  1027. ! MemoryOrder are used to uniquely identify which element of outpatch_table is
  1028. ! associated with this array. If no element is associated, then this routine
  1029. ! first assigns an unused element and allocates space within that element.
  1030. ! This routine also stores DateStr, VarName,
  1031. ! FieldType, MemoryOrder, Stagger, DimNames, DomainStart, and DomainEnd within
  1032. ! the same element of outpatch.
  1033. !</PRE>
  1034. !</DESCRIPTION>
  1035. USE module_quilt_outbuf_ops, Only: outpatch_table, tabsize, num_entries
  1036. USE module_timing
  1037. IMPLICIT NONE
  1038. #include "wrf_io_flags.h"
  1039. INTEGER , INTENT(IN) :: FieldType
  1040. REAL , DIMENSION(*), INTENT(IN) :: inbuf_r
  1041. INTEGER , DIMENSION(*), INTENT(IN) :: inbuf_i
  1042. INTEGER , DIMENSION(3), INTENT(IN) :: DomainStart, DomainEnd, MemoryStart,&
  1043. MemoryEnd , PatchStart , PatchEnd
  1044. CHARACTER*(*) , INTENT(IN) :: DateStr , VarName, MemoryOrder , &
  1045. Stagger, DimNames(3)
  1046. INTEGER, INTENT(IN) :: ntasks ! Number of compute tasks associated with
  1047. ! this IO server
  1048. ! Local
  1049. CHARACTER*256 :: mess
  1050. INTEGER :: l,m,n,ii,jj,ipatch,ierr
  1051. LOGICAL :: found
  1052. ! CALL start_timing()
  1053. ! Find the VarName if it's in the buffer already
  1054. ii = 1
  1055. found = .false.
  1056. DO WHILE ( .NOT. found .AND. ii .LE. num_entries )
  1057. !TBH: need to test other attributes too!
  1058. IF ( TRIM(VarName) .EQ. TRIM(outpatch_table(ii)%VarName) ) THEN
  1059. IF ( TRIM(DateStr) .EQ. TRIM(outpatch_table(ii)%DateStr) ) THEN
  1060. IF ( TRIM(MemoryOrder) .EQ. TRIM(outpatch_table(ii)%MemoryOrder) ) THEN
  1061. found = .true.
  1062. ELSE
  1063. CALL wrf_error_fatal("store_patch_in_outbuf_pnc: memory order disagreement")
  1064. ENDIF
  1065. ELSE
  1066. CALL wrf_error_fatal("store_patch_in_outbuf_pnc: multiple dates in buffer")
  1067. ENDIF
  1068. ELSE
  1069. ii = ii + 1
  1070. ENDIF
  1071. ENDDO
  1072. IF ( .NOT. found ) THEN
  1073. num_entries = num_entries + 1
  1074. IF(num_entries > tabsize)THEN
  1075. WRITE(mess,*) 'Number of entries in outpatch_table has exceeded tabsize (',tabsize,') in module_quilt_outbuf_ops::store_patch_in_outbuf_pnc'
  1076. CALL wrf_error_fatal(mess)
  1077. END IF
  1078. outpatch_table(num_entries)%npatch = 0
  1079. outpatch_table(num_entries)%VarName = TRIM(VarName)
  1080. outpatch_table(num_entries)%DateStr = TRIM(DateStr)
  1081. outpatch_table(num_entries)%MemoryOrder = TRIM(MemoryOrder)
  1082. outpatch_table(num_entries)%Stagger = TRIM(Stagger)
  1083. outpatch_table(num_entries)%DimNames(1) = TRIM(DimNames(1))
  1084. outpatch_table(num_entries)%DimNames(2) = TRIM(DimNames(2))
  1085. outpatch_table(num_entries)%DimNames(3) = TRIM(DimNames(3))
  1086. outpatch_table(num_entries)%DomainStart = DomainStart
  1087. outpatch_table(num_entries)%DomainEnd = DomainEnd
  1088. outpatch_table(num_entries)%FieldType = FieldType
  1089. ! Allocate the table for the list of patches for this output - it
  1090. ! will have as many entries as there are compute tasks associated with
  1091. ! this IO server.
  1092. IF ( ALLOCATED(outpatch_table(num_entries)%PatchList) ) &
  1093. DEALLOCATE(outpatch_table(num_entries)%PatchList)
  1094. ALLOCATE(outpatch_table(num_entries)%PatchList(ntasks), Stat=ierr)
  1095. IF(ierr /= 0)THEN
  1096. WRITE(mess,*)'num_entries ',num_entries,' ntasks ',ntasks,' ierr ',ierr
  1097. CALL wrf_message(mess)
  1098. WRITE(mess,*)'Allocation for ',ntasks, &
  1099. ' patches in store_patch_in_outbuf_pnc() failed.'
  1100. CALL wrf_error_fatal( mess )
  1101. ENDIF
  1102. ! Initialise the list of patches
  1103. DO ii=1, ntasks, 1
  1104. outpatch_table(num_entries)%PatchList(ii)%forDeletion = .FALSE.
  1105. NULLIFY(outpatch_table(num_entries)%PatchList(ii)%rptr)
  1106. NULLIFY(outpatch_table(num_entries)%PatchList(ii)%iptr)
  1107. outpatch_table(num_entries)%PatchList(ii)%PatchStart(:) = 0
  1108. outpatch_table(num_entries)%PatchList(ii)%PatchEnd(:) = 0
  1109. outpatch_table(num_entries)%PatchList(ii)%PatchExtent(:) = 0
  1110. END DO
  1111. ii = num_entries
  1112. WRITE(mess,*)'Adding field entry no. ',num_entries
  1113. CALL wrf_message(mess)
  1114. WRITE(mess,*)'Variable = ',TRIM(VarName)
  1115. CALL wrf_message(mess)
  1116. WRITE(mess,*)'Domain start = ',DomainStart(:)
  1117. CALL wrf_message(mess)
  1118. WRITE(mess,*)'Domain end = ',DomainEnd(:)
  1119. CALL wrf_message(mess)
  1120. ENDIF
  1121. ! We only store > 1 patch if the field has two or more dimensions. Scalars
  1122. ! and 1D arrays are replicated across compute nodes and therefore we only
  1123. ! need keep a single patch.
  1124. IF(LEN_TRIM(outpatch_table(ii)%MemoryOrder) >= 2 .OR. &
  1125. outpatch_table(ii)%npatch < 1)THEN
  1126. ! Add another patch
  1127. outpatch_table(ii)%npatch = outpatch_table(ii)%npatch + 1
  1128. outpatch_table(ii)%nActivePatch = outpatch_table(ii)%npatch
  1129. ipatch = outpatch_table(ii)%npatch
  1130. outpatch_table(ii)%PatchList(ipatch)%PatchStart(:) = PatchStart(:)
  1131. outpatch_table(ii)%PatchList(ipatch)%PatchEnd(:) = PatchEnd(:)
  1132. outpatch_table(ii)%PatchList(ipatch)%PatchExtent(:)= PatchEnd(:) - PatchStart(:) + 1
  1133. ierr = 0
  1134. IF ( FieldType .EQ. WRF_FLOAT ) THEN
  1135. ALLOCATE( outpatch_table(ii)%PatchList(ipatch)%rptr( &
  1136. outpatch_table(ii)%PatchList(ipatch)%PatchExtent(1), &
  1137. outpatch_table(ii)%PatchList(ipatch)%PatchExtent(2), &
  1138. outpatch_table(ii)%PatchList(ipatch)%PatchExtent(3)),&
  1139. Stat=ierr)
  1140. ELSE IF ( FieldType .EQ. WRF_INTEGER ) THEN
  1141. ALLOCATE( outpatch_table(ii)%PatchList(ipatch)%iptr( &
  1142. outpatch_table(ii)%PatchList(ipatch)%PatchExtent(1), &
  1143. outpatch_table(ii)%PatchList(ipatch)%PatchExtent(2), &
  1144. outpatch_table(ii)%PatchList(ipatch)%PatchExtent(3)),&
  1145. Stat=ierr)
  1146. ELSE
  1147. WRITE(mess,*)"store_patch_in_outbuf_pnc: unsupported type ", FieldType
  1148. CALL wrf_error_fatal(mess)
  1149. ENDIF
  1150. IF(ierr /= 0)THEN
  1151. WRITE(mess,*)"store_patch_in_outbuf_pnc: failed to allocate memory to hold patch for var. ", TRIM(VarName)
  1152. CALL wrf_error_fatal(mess)
  1153. END IF
  1154. jj = 1
  1155. WRITE(mess,"('Variable ',(A),', patch ',I3,': (',I3,':',I3,',',I3,':',I3,',',I3,':',I3,')')")&
  1156. TRIM(outpatch_table(ii)%VarName), &
  1157. ipatch, &
  1158. PatchStart(1),PatchEnd(1), &
  1159. PatchStart(2),PatchEnd(2), &
  1160. PatchStart(3),PatchEnd(3)
  1161. CALL wrf_message(mess)
  1162. IF ( FieldType .EQ. WRF_FLOAT ) THEN
  1163. DO n = 1,outpatch_table(ii)%PatchList(ipatch)%PatchExtent(3),1
  1164. DO m = 1,outpatch_table(ii)%PatchList(ipatch)%PatchExtent(2),1
  1165. DO l = 1,outpatch_table(ii)%PatchList(ipatch)%PatchExtent(1),1
  1166. outpatch_table(ii)%PatchList(ipatch)%rptr(l,m,n) = inbuf_r(jj)
  1167. jj = jj + 1
  1168. ENDDO
  1169. ENDDO
  1170. ENDDO
  1171. ENDIF
  1172. IF ( FieldType .EQ. WRF_INTEGER ) THEN
  1173. DO n = 1,outpatch_table(ii)%PatchList(ipatch)%PatchExtent(3),1
  1174. DO m = 1,outpatch_table(ii)%PatchList(ipatch)%PatchExtent(2),1
  1175. DO l = 1,outpatch_table(ii)%PatchList(ipatch)%PatchExtent(1),1
  1176. outpatch_table(ii)%PatchList(ipatch)%iptr(l,m,n) = inbuf_i(jj)
  1177. jj = jj + 1
  1178. ENDDO
  1179. ENDDO
  1180. ENDDO
  1181. ENDIF
  1182. END IF ! We need to add another patch
  1183. ! CALL end_timing("store patch in outbuf")
  1184. RETURN
  1185. END SUBROUTINE store_patch_in_outbuf_pnc
  1186. !call add_to_bufsize_for_field( VarName, hdrbufsize+chunksize )
  1187. SUBROUTINE add_to_bufsize_for_field( VarName, Nbytes )
  1188. !<DESCRIPTION>
  1189. !<PRE>
  1190. ! This routine is a wrapper for C routine add_to_bufsize_for_field_c() that
  1191. ! is used to accumulate buffer sizes. Buffer size Nbytes is added to the
  1192. ! curent buffer size for the buffer named VarName. Any buffer space
  1193. ! associated with VarName is freed. If a buffer named VarName does not exist,
  1194. ! a new one is assigned and its size is set to Nbytes.
  1195. !</PRE>
  1196. !</DESCRIPTION>
  1197. USE module_quilt_outbuf_ops
  1198. IMPLICIT NONE
  1199. CHARACTER*(*) , INTENT(IN) :: VarName
  1200. INTEGER , INTENT(IN) :: Nbytes
  1201. ! Local
  1202. CHARACTER*256 :: mess
  1203. INTEGER :: i, ierr
  1204. INTEGER :: VarNameAsInts( 256 )
  1205. VarNameAsInts( 1 ) = len(trim(VarName))
  1206. DO i = 2, len(trim(VarName)) + 1
  1207. VarNameAsInts( i ) = ICHAR( VarName(i-1:i-1) )
  1208. ENDDO
  1209. CALL add_to_bufsize_for_field_c ( VarNameAsInts, Nbytes )
  1210. RETURN
  1211. END SUBROUTINE add_to_bufsize_for_field
  1212. SUBROUTINE store_piece_of_field( inbuf, VarName, Nbytes )
  1213. !<DESCRIPTION>
  1214. !<PRE>
  1215. ! This routine is a wrapper for C routine store_piece_of_field_c() that
  1216. ! is used to store pieces of a field in an internal buffer. Nbytes bytes of
  1217. ! buffer inbuf are appended to the end of the internal buffer named VarName.
  1218. ! An error occurs if either an internal buffer named VarName does not exist or
  1219. ! if there are fewer than Nbytes bytes left in the internal buffer.
  1220. !</PRE>
  1221. !</DESCRIPTION>
  1222. USE module_quilt_outbuf_ops
  1223. IMPLICIT NONE
  1224. INTEGER , INTENT(IN) :: Nbytes
  1225. INTEGER , DIMENSION(*) , INTENT(IN) :: inbuf
  1226. CHARACTER*(*) , INTENT(IN) :: VarName
  1227. ! Local
  1228. CHARACTER*256 :: mess
  1229. INTEGER :: i, ierr
  1230. INTEGER :: VarNameAsInts( 256 )
  1231. VarNameAsInts( 1 ) = len(trim(VarName))
  1232. DO i = 2, len(trim(VarName)) + 1
  1233. VarNameAsInts( i ) = ICHAR( VarName(i-1:i-1) )
  1234. ENDDO
  1235. CALL store_piece_of_field_c ( inbuf, VarNameAsInts, Nbytes, ierr )
  1236. IF ( ierr .NE. 0 ) CALL wrf_error_fatal ( "store_piece_of_field" )
  1237. RETURN
  1238. END SUBROUTINE store_piece_of_field
  1239. SUBROUTINE retrieve_pieces_of_field( outbuf, VarName, obufsz, Nbytes_tot, lret )
  1240. !<DESCRIPTION>
  1241. !<PRE>
  1242. ! This routine is a wrapper for C routine retrieve_pieces_of_field_c() that
  1243. ! is used to extract the entire contents (i.e. all previously stored pieces of
  1244. ! fields) of the next internal buffer. The name associated with this internal
  1245. ! buffer is returned in VarName. The number of bytes read is returned in
  1246. ! Nbytes_tot. Bytes are stored in outbuf whose size (in bytes) is obufsz.
  1247. ! If there are more than obufsz bytes left in the next internal buffer, then
  1248. ! only obufsz bytes are returned and the rest are discarded (probably an error
  1249. ! in the making!). The internal buffer is then freed. Flag lret is set to
  1250. ! .TRUE. iff there are more fields left to extract.
  1251. !</PRE>
  1252. !</DESCRIPTION>
  1253. USE module_quilt_outbuf_ops
  1254. IMPLICIT NONE
  1255. INTEGER , INTENT(IN) :: obufsz
  1256. INTEGER , INTENT(OUT) :: Nbytes_tot
  1257. INTEGER , DIMENSION(*) , INTENT(OUT) :: outbuf
  1258. CHARACTER*(*) , INTENT(OUT) :: VarName
  1259. LOGICAL :: lret ! true if more, false if not
  1260. ! Local
  1261. CHARACTER*256 :: mess
  1262. INTEGER :: i, iret
  1263. INTEGER :: VarNameAsInts( 256 )
  1264. CALL retrieve_pieces_of_field_c ( outbuf, VarNameAsInts, obufsz, Nbytes_tot, iret )
  1265. IF ( iret .NE. 0 ) THEN
  1266. lret = .FALSE.
  1267. ELSE
  1268. lret = .TRUE.
  1269. VarName = ' '
  1270. DO i = 2, VarNameAsInts(1) + 1
  1271. VarName(i-1:i-1) = CHAR(VarNameAsInts( i ))
  1272. ENDDO
  1273. ENDIF
  1274. RETURN
  1275. END SUBROUTINE retrieve_pieces_of_field