PageRenderTime 60ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/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

Large files files are truncated, but you can click here to view the full file

  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 buffe…

Large files files are truncated, but you can click here to view the full file