/[MITgcm]/MITgcm/pkg/mdsio/mdsio_write_field.F
ViewVC logotype

Contents of /MITgcm/pkg/mdsio/mdsio_write_field.F

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.7 - (show annotations) (download)
Mon May 11 02:20:48 2009 UTC (16 years, 1 month ago) by jmc
Branch: MAIN
CVS Tags: checkpoint61n
Changes since 1.6: +45 -18 lines
move mapping to global io-buffer inside gather_2d/scater_2d ; save memory
(1 less 2D global RL array) + only send/receive real*4 arr when 32.bit file

1 C $Header: /u/gcmpack/MITgcm/pkg/mdsio/mdsio_write_field.F,v 1.6 2009/05/06 02:42:49 jmc Exp $
2 C $Name: $
3
4 #include "MDSIO_OPTIONS.h"
5
6 CBOP
7 C !ROUTINE: MDS_WRITE_FIELD
8 C !INTERFACE:
9 SUBROUTINE MDS_WRITE_FIELD(
10 I fName,
11 I filePrec,
12 I globalFile,
13 I useCurrentDir,
14 I arrType,
15 I kSize,kLo,kHi,
16 I arr,
17 I jrecord,
18 I myIter,
19 I myThid )
20
21 C !DESCRIPTION:
22 C Arguments:
23 C
24 C fName (string) :: base name for file to write
25 C filePrec (integer) :: number of bits per word in file (32 or 64)
26 C globalFile (logical):: selects between writing a global or tiled file
27 C useCurrentDir(logic):: always write to the current directory (even if
28 C "mdsioLocalDir" is set)
29 C arrType (char(2)) :: declaration of "arr": either "RS" or "RL"
30 C kSize (integer) :: size of third dimension: normally either 1 or Nr
31 C kLo (integer) :: 1rst vertical level (of array "arr") to write
32 C kHi (integer) :: last vertical level (of array "arr") to write
33 C arr ( RS/RL ) :: array to write, arr(:,:,kSize,:,:)
34 C irecord (integer) :: record number to write
35 C myIter (integer) :: time step number
36 C myThid (integer) :: thread identifier
37 C
38 C MDS_WRITE_FIELD creates either a file of the form "fName.data" and
39 C "fName.meta" if the logical flag "globalFile" is set true. Otherwise
40 C it creates MDS tiled files of the form "fName.xxx.yyy.data" and
41 C "fName.xxx.yyy.meta". If jrecord > 0, a meta-file is created.
42 C Currently, the meta-files are not read because it is difficult
43 C to parse files in fortran. We should read meta information before
44 C adding records to an existing multi-record file.
45 C The precision of the file is decsribed by filePrec, set either
46 C to floatPrec32 or floatPrec64. The precision or declaration of
47 C the array argument must be consistently described by the char*(2)
48 C string arrType, either "RS" or "RL".
49 C (kSize,kLo,kHi) allows for both 2-D and 3-D arrays to be handled, with
50 C the option to only write a sub-set of consecutive vertical levels (from
51 C kLo to kHi); (kSize,kLo,kHi)=(1,1,1) implies a 2-D model field and
52 C (kSize,kLo,kHi)=(Nr,1,Nr) implies a 3-D model field.
53 C irecord=|jrecord| is the record number to be written and must be >= 1.
54 C NOTE: It is currently assumed that the highest record number in the file
55 C was the last record written. Nor is there a consistency check between the
56 C routine arguments and file, i.e., if you write record 2 after record 4
57 C the meta information will record the number of records to be 2. This,
58 C again, is because we have read the meta information. To be fixed.
59 C
60 C Created: 03/16/99 adcroft@mit.edu
61 C Changed: 01/06/02 menemenlis@jpl.nasa.gov
62 C added useSingleCpuIO hack
63 C changed: 1/23/04 afe@ocean.mit.edu
64 C added exch2 handling -- yes, the globalfile logic is nuts
65 CEOP
66
67 C !USES:
68 IMPLICIT NONE
69 C Global variables / common blocks
70 #include "SIZE.h"
71 #include "EEPARAMS.h"
72 #include "PARAMS.h"
73 #ifdef ALLOW_EXCH2
74 #include "W2_EXCH2_TOPOLOGY.h"
75 #include "W2_EXCH2_PARAMS.h"
76 #endif /* ALLOW_EXCH2 */
77 #include "MDSIO_SCPU.h"
78
79 C !INPUT PARAMETERS:
80 CHARACTER*(*) fName
81 INTEGER filePrec
82 LOGICAL globalFile
83 LOGICAL useCurrentDir
84 CHARACTER*(2) arrType
85 INTEGER kSize, kLo, kHi
86 cph(
87 cph Real arr(*)
88 _RL arr(1-oLx:sNx+oLx,1-oLy:sNy+oLy,kSize,nSx,nSy)
89 cph)
90 INTEGER jrecord
91 INTEGER myIter
92 INTEGER myThid
93 C !OUTPUT PARAMETERS:
94
95 C !FUNCTIONS
96 INTEGER ILNBLNK
97 INTEGER MDS_RECLEN
98 LOGICAL MASTER_CPU_IO
99 EXTERNAL ILNBLNK
100 EXTERNAL MDS_RECLEN
101 EXTERNAL MASTER_CPU_IO
102
103 C !LOCAL VARIABLES:
104 CHARACTER*(MAX_LEN_FNAM) dataFName,metaFName,pfName
105 CHARACTER*(MAX_LEN_MBUF) msgBuf
106 LOGICAL fileIsOpen
107 LOGICAL iAmDoingIO
108 LOGICAL writeMetaF
109 LOGICAL keepBlankTileIO
110 LOGICAL zeroBuff
111 INTEGER xSize, ySize
112 INTEGER irecord
113 INTEGER iG,jG,bi,bj,i,j,k,nNz
114 INTEGER irec,dUnit,IL,pIL
115 INTEGER dimList(3,3), nDims, map2gl(2)
116 INTEGER iGjLoc, jGjLoc
117 INTEGER length_of_rec
118 Real*4 r4seg(sNx)
119 Real*8 r8seg(sNx)
120 #ifdef ALLOW_EXCH2
121 c INTEGER tGy,tGx,tNy,tNx,tN
122 INTEGER tGy,tGx, tNx,tN
123 INTEGER global_nTx
124 #endif /* ALLOW_EXCH2 */
125 INTEGER tNy
126
127 C---+----1----+----2----+----3----+----4----+----5----+----6----+----7-|--+----|
128 C Set dimensions:
129 xSize = Nx
130 ySize = Ny
131 keepBlankTileIO = .FALSE.
132 #if defined(ALLOW_EXCH2) && !defined(MISSING_TILE_IO)
133 xSize = exch2_global_Nx
134 ySize = exch2_global_Ny
135 keepBlankTileIO = .TRUE.
136 #endif
137
138 C- default:
139 iGjLoc = 0
140 jGjLoc = 1
141
142 C Assume nothing
143 fileIsOpen = .FALSE.
144 IL = ILNBLNK( fName )
145 pIL = ILNBLNK( mdsioLocalDir )
146 nNz = 1 + kHi - kLo
147 irecord = ABS(jrecord)
148 writeMetaF = jrecord.GT.0
149
150 C Only do I/O if I am the master thread (and mpi process 0 IF useSingleCpuIO):
151 iAmDoingIO = MASTER_CPU_IO(myThid)
152
153 C Only do I/O if I am the master thread
154 IF ( iAmDoingIO ) THEN
155
156 C Record number must be >= 1
157 IF (irecord .LT. 1) THEN
158 WRITE(msgBuf,'(A,I9.8)')
159 & ' MDS_WRITE_FIELD: argument irecord = ',irecord
160 CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
161 & SQUEEZE_RIGHT , myThid)
162 WRITE(msgBuf,'(A)')
163 & ' MDS_WRITE_FIELD: invalid value for irecord'
164 CALL PRINT_ERROR( msgBuf, myThid )
165 STOP 'ABNORMAL END: S/R MDS_WRITE_FIELD'
166 ENDIF
167 C check for valid sub-set of levels:
168 IF ( kLo.LT.1 .OR. kHi.GT.kSize ) THEN
169 WRITE(msgBuf,'(3(A,I6))')
170 & ' MDS_WRITE_FIELD: arguments kSize=', kSize,
171 & ' , kLo=', kLo, ' , kHi=', kHi
172 CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
173 & SQUEEZE_RIGHT , myThid)
174 WRITE(msgBuf,'(A)')
175 & ' MDS_WRITE_FIELD: invalid sub-set of levels'
176 CALL PRINT_ERROR( msgBuf, myThid )
177 STOP 'ABNORMAL END: S/R MDS_WRITE_FIELD'
178 ENDIF
179
180 C Assign special directory
181 IF ( useCurrentDir .OR. pIL.EQ.0 ) THEN
182 pfName = fName
183 ELSE
184 WRITE(pfName,'(2A)') mdsioLocalDir(1:pIL), fName(1:IL)
185 ENDIF
186 pIL=ILNBLNK( pfName )
187
188 C Assign a free unit number as the I/O channel for this routine
189 CALL MDSFINDUNIT( dUnit, myThid )
190
191 C- endif iAmDoingIO
192 ENDIF
193
194 C If option globalFile is desired but does not work or if
195 C globalFile is too slow, then try using single-CPU I/O.
196 IF (useSingleCpuIO) THEN
197
198 C Master thread of process 0, only, opens a global file
199 IF ( iAmDoingIO ) THEN
200 WRITE(dataFName,'(2a)') fName(1:IL),'.data'
201 length_of_rec=MDS_RECLEN(filePrec,xSize*ySize,myThid)
202 IF (irecord .EQ. 1) THEN
203 OPEN( dUnit, file=dataFName, status=_NEW_STATUS,
204 & access='direct', recl=length_of_rec )
205 ELSE
206 OPEN( dUnit, file=dataFName, status=_OLD_STATUS,
207 & access='direct', recl=length_of_rec )
208 ENDIF
209 ENDIF
210
211 C Gather array and WRITE it to file, one vertical level at a time
212 DO k=kLo,kHi
213 zeroBuff = k.EQ.kLo
214 C- copy from arr(level=k) to 2-D "local":
215 IF ( filePrec.EQ.precFloat32 ) THEN
216 IF ( arrType.EQ.'RS' ) THEN
217 CALL MDS_PASS_R4toRS( sharedLocBuf_r4,
218 & arr, k, kSize, .FALSE., myThid )
219 ELSEIF ( arrType.EQ.'RL' ) THEN
220 CALL MDS_PASS_R4toRL( sharedLocBuf_r4,
221 & arr, k, kSize, .FALSE., myThid )
222 ELSE
223 WRITE(msgBuf,'(A)')
224 & ' MDS_WRITE_FIELD: illegal value for arrType'
225 CALL PRINT_ERROR( msgBuf, myThid )
226 STOP 'ABNORMAL END: S/R MDS_WRITE_FIELD'
227 ENDIF
228 CALL GATHER_2D_R4(
229 U xy_buffer_r4,
230 O sharedLocBuf_r4,
231 I xSize, ySize,
232 I keepBlankTileIO, zeroBuff, myThid )
233 ELSEIF ( filePrec.EQ.precFloat64 ) THEN
234 IF ( arrType.EQ.'RS' ) THEN
235 CALL MDS_PASS_R8toRS( sharedLocBuf_r8,
236 & arr, k, kSize, .FALSE., myThid )
237 ELSEIF ( arrType.EQ.'RL' ) THEN
238 CALL MDS_PASS_R8toRL( sharedLocBuf_r8,
239 & arr, k, kSize, .FALSE., myThid )
240 ELSE
241 WRITE(msgBuf,'(A)')
242 & ' MDS_WRITE_FIELD: illegal value for arrType'
243 CALL PRINT_ERROR( msgBuf, myThid )
244 STOP 'ABNORMAL END: S/R MDS_WRITE_FIELD'
245 ENDIF
246 CALL GATHER_2D_R8(
247 U xy_buffer_r8,
248 O sharedLocBuf_r8,
249 I xSize, ySize,
250 I keepBlankTileIO, zeroBuff, myThid )
251 ELSE
252 WRITE(msgBuf,'(A)')
253 & ' MDS_WRITE_FIELD: illegal value for filePrec'
254 CALL PRINT_ERROR( msgBuf, myThid )
255 STOP 'ABNORMAL END: S/R MDS_WRITE_FIELD'
256 ENDIF
257
258 IF ( iAmDoingIO ) THEN
259 irec=k+1-kLo+nNz*(irecord-1)
260 IF (filePrec .EQ. precFloat32) THEN
261 #ifdef _BYTESWAPIO
262 CALL MDS_BYTESWAPR4( xSize*ySize, xy_buffer_r4 )
263 #endif
264 WRITE(dUnit,rec=irec) ( xy_buffer_r4(i),i=1,xSize*ySize )
265 ELSEIF (filePrec .EQ. precFloat64) THEN
266 #ifdef _BYTESWAPIO
267 CALL MDS_BYTESWAPR8( xSize*ySize, xy_buffer_r8 )
268 #endif
269 WRITE(dUnit,rec=irec) ( xy_buffer_r8(i),i=1,xSize*ySize )
270 ELSE
271 WRITE(msgBuf,'(A)')
272 & ' MDS_WRITE_FIELD: illegal value for filePrec'
273 CALL PRINT_ERROR( msgBuf, myThid )
274 STOP 'ABNORMAL END: S/R MDS_WRITE_FIELD'
275 ENDIF
276 C- end if iAmDoingIO
277 ENDIF
278 C- end of k loop
279 ENDDO
280
281 C Close data-file
282 IF ( iAmDoingIO ) THEN
283 CLOSE( dUnit )
284 ENDIF
285
286 C---+----1----+----2----+----3----+----4----+----5----+----6----+----7-|--+----|
287 C--- else .NOT.useSingleCpuIO
288 ELSE
289
290 C Only do I/O if I am the master thread
291 IF ( iAmDoingIO ) THEN
292
293 C If we are writing to a global file then we open it here
294 IF (globalFile) THEN
295 WRITE(dataFName,'(2a)') fName(1:IL),'.data'
296 IF (irecord .EQ. 1) THEN
297 length_of_rec=MDS_RECLEN( filePrec, sNx, myThid )
298 OPEN( dUnit, file=dataFName, status=_NEW_STATUS,
299 & access='direct', recl=length_of_rec )
300 fileIsOpen=.TRUE.
301 ELSE
302 length_of_rec=MDS_RECLEN( filePrec, sNx, myThid )
303 OPEN( dUnit, file=dataFName, status=_OLD_STATUS,
304 & access='direct', recl=length_of_rec )
305 fileIsOpen=.TRUE.
306 ENDIF
307 ENDIF
308
309 C Loop over all tiles
310 DO bj=1,nSy
311 DO bi=1,nSx
312 C If we are writing to a tiled MDS file then we open each one here
313 IF (.NOT. globalFile) THEN
314 iG=bi+(myXGlobalLo-1)/sNx ! Kludge until unstructered tiles
315 jG=bj+(myYGlobalLo-1)/sNy ! Kludge until unstructered tiles
316 WRITE(dataFName,'(2A,I3.3,A,I3.3,A)')
317 & pfName(1:pIL),'.',iG,'.',jG,'.data'
318 IF (irecord .EQ. 1) THEN
319 length_of_rec=MDS_RECLEN( filePrec, sNx, myThid )
320 OPEN( dUnit, file=dataFName, status=_NEW_STATUS,
321 & access='direct', recl=length_of_rec )
322 fileIsOpen=.TRUE.
323 ELSE
324 length_of_rec=MDS_RECLEN( filePrec, sNx, myThid )
325 OPEN( dUnit, file=dataFName, status=_OLD_STATUS,
326 & access='direct', recl=length_of_rec )
327 fileIsOpen=.TRUE.
328 ENDIF
329 ENDIF
330
331 IF (fileIsOpen) THEN
332 tNy = sNy
333 #ifdef ALLOW_EXCH2
334 tN = W2_myTileList(bi)
335 tGy = exch2_tyGlobalo(tN)
336 tGx = exch2_txGlobalo(tN)
337 tNy = exch2_tNy(tN)
338 tNx = exch2_tNx(tN)
339 IF ( exch2_mydNx(tN) .GT. xSize ) THEN
340 C- face x-size larger than glob-size : fold it
341 iGjLoc = 0
342 jGjLoc = exch2_mydNx(tN) / xSize
343 ELSEIF ( exch2_tNy(tN) .GT. ySize ) THEN
344 C- tile y-size larger than glob-size : make a long line
345 iGjLoc = exch2_mydNx(tN)
346 jGjLoc = 0
347 ELSE
348 C- default (face fit into global-IO-array)
349 iGjLoc = 0
350 jGjLoc = 1
351 ENDIF
352 global_nTx = exch2_global_Nx/tNx
353 #endif /* ALLOW_EXCH2 */
354 DO k=1,nNz
355 DO j=1,tNy
356 IF (globalFile) THEN
357 #ifdef ALLOW_EXCH2
358 irec = 1 + ( tGx-1 + (j-1)*iGjLoc )/tNx
359 & + ( tGy-1 + (j-1)*jGjLoc )*global_nTx
360 & + ( k-kLo + (irecord-1)*nNz
361 & )*ySize*global_nTx
362 #else /* ALLOW_EXCH2 */
363 iG = myXGlobalLo-1 + (bi-1)*sNx
364 jG = myYGlobalLo-1 + (bj-1)*sNy
365 irec= 1 + INT(iG/sNx) + nSx*nPx*(jG+j-1)
366 & + nSx*nPx*Ny*(k-kLo)
367 & + nSx*nPx*Ny*nNz*(irecord-1)
368 #endif /* ALLOW_EXCH2 */
369 ELSE
370 irec=j + sNy*(k-kLo) + sNy*nNz*(irecord-1)
371 ENDIF
372 IF (filePrec .EQ. precFloat32) THEN
373 IF (arrType .EQ. 'RS') THEN
374 CALL MDS_SEG4toRS( j,bi,bj,k,kSize, r4seg,.FALSE.,arr )
375 ELSEIF (arrType .EQ. 'RL') THEN
376 CALL MDS_SEG4toRL( j,bi,bj,k,kSize, r4seg,.FALSE.,arr )
377 ELSE
378 WRITE(msgBuf,'(A)')
379 & ' MDS_WRITE_FIELD: illegal value for arrType'
380 CALL PRINT_ERROR( msgBuf, myThid )
381 STOP 'ABNORMAL END: S/R MDS_WRITE_FIELD'
382 ENDIF
383 #ifdef _BYTESWAPIO
384 CALL MDS_BYTESWAPR4( sNx, r4seg )
385 #endif
386 WRITE(dUnit,rec=irec) r4seg
387 ELSEIF (filePrec .EQ. precFloat64) THEN
388 IF (arrType .EQ. 'RS') THEN
389 CALL MDS_SEG8toRS( j,bi,bj,k,kSize, r8seg,.FALSE.,arr )
390 ELSEIF (arrType .EQ. 'RL') THEN
391 CALL MDS_SEG8toRL( j,bi,bj,k,kSize, r8seg,.FALSE.,arr )
392 ELSE
393 WRITE(msgBuf,'(A)')
394 & ' MDS_WRITE_FIELD: illegal value for arrType'
395 CALL PRINT_ERROR( msgBuf, myThid )
396 STOP 'ABNORMAL END: S/R MDS_WRITE_FIELD'
397 ENDIF
398 #ifdef _BYTESWAPIO
399 CALL MDS_BYTESWAPR8( sNx, r8seg )
400 #endif
401 WRITE(dUnit,rec=irec) r8seg
402 ELSE
403 WRITE(msgBuf,'(A)')
404 & ' MDS_WRITE_FIELD: illegal value for filePrec'
405 CALL PRINT_ERROR( msgBuf, myThid )
406 STOP 'ABNORMAL END: S/R MDS_WRITE_FIELD'
407 ENDIF
408 C End of j loop
409 ENDDO
410 C End of k loop
411 ENDDO
412 ELSE
413 C fileIsOpen=F
414 WRITE(msgBuf,'(A)')
415 & ' MDS_WRITE_FIELD: I should never get to this point'
416 CALL PRINT_ERROR( msgBuf, myThid )
417 STOP 'ABNORMAL END: S/R MDS_WRITE_FIELD'
418 ENDIF
419 C If we were writing to a tiled MDS file then we close it here
420 IF (fileIsOpen .AND. (.NOT. globalFile)) THEN
421 CLOSE( dUnit )
422 fileIsOpen = .FALSE.
423 ENDIF
424 C Create meta-file for each tile if we are tiling
425 IF ( .NOT.globalFile .AND. writeMetaF ) THEN
426 iG=bi+(myXGlobalLo-1)/sNx
427 jG=bj+(myYGlobalLo-1)/sNy
428 WRITE(metaFname,'(2A,I3.3,A,I3.3,A)')
429 & pfName(1:pIL),'.',iG,'.',jG,'.meta'
430 #if defined(ALLOW_EXCH2) && !defined(MISSING_TILE_IO)
431 tN = W2_myTileList(bi)
432 dimList(1,1) = xSize
433 dimList(2,1) = exch2_txGlobalo(tN)
434 dimList(3,1) = exch2_txGlobalo(tN)+sNx-1
435 dimList(1,2) = ySize
436 dimList(2,2) = exch2_tyGlobalo(tN)
437 dimList(3,2) = exch2_tyGlobalo(tN)+sNy-1
438 #else /* defined(ALLOW_EXCH2) && !defined(MISSING_TILE_IO) */
439 C- jmc: if MISSING_TILE_IO, keep meta files unchanged
440 C to stay consistent with global file structure
441 dimList(1,1) = Nx
442 dimList(2,1) = myXGlobalLo+(bi-1)*sNx
443 dimList(3,1) = myXGlobalLo+bi*sNx-1
444 dimList(1,2) = Ny
445 dimList(2,2) = myYGlobalLo+(bj-1)*sNy
446 dimList(3,2) = myYGlobalLo+bj*sNy-1
447 #endif /* defined(ALLOW_EXCH2) && !defined(MISSING_TILE_IO) */
448 dimList(1,3) = nNz
449 dimList(2,3) = 1
450 dimList(3,3) = nNz
451 nDims = 3
452 IF ( nNz.EQ.1 ) nDims = 2
453 map2gl(1) = iGjLoc
454 map2gl(2) = jGjLoc
455 CALL MDS_WRITE_META(
456 I metaFName, dataFName, the_run_name, ' ',
457 I filePrec, nDims,dimList,map2gl, 0, ' ',
458 I 0, UNSET_RL, irecord, myIter, myThid )
459 ENDIF
460 C End of bi,bj loops
461 ENDDO
462 ENDDO
463
464 C If global file was opened then close it
465 IF (fileIsOpen .AND. globalFile) THEN
466 CLOSE( dUnit )
467 fileIsOpen = .FALSE.
468 ENDIF
469
470 C- endif iAmDoingIO
471 ENDIF
472
473 C if useSingleCpuIO / else / end
474 ENDIF
475
476 C Create meta-file for the global-file (also if useSingleCpuIO)
477 IF ( writeMetaF .AND. iAmDoingIO .AND.
478 & (globalFile .OR. useSingleCpuIO) ) THEN
479 WRITE(metaFName,'(2A)') fName(1:IL),'.meta'
480 dimList(1,1) = xSize
481 dimList(2,1) = 1
482 dimList(3,1) = xSize
483 dimList(1,2) = ySize
484 dimList(2,2) = 1
485 dimList(3,2) = ySize
486 dimList(1,3) = nNz
487 dimList(2,3) = 1
488 dimList(3,3) = nNz
489 nDims = 3
490 IF ( nNz.EQ.1 ) nDims = 2
491 map2gl(1) = 0
492 map2gl(2) = 1
493 CALL MDS_WRITE_META(
494 I metaFName, dataFName, the_run_name, ' ',
495 I filePrec, nDims,dimList,map2gl, 0, ' ',
496 I 0, UNSET_RL, irecord, myIter, myThid )
497 c I metaFName, dataFName, the_run_name, titleLine,
498 c I filePrec, nDims, dimList, map2gl, nFlds, fldList,
499 c I nTimRec, timList, irecord, myIter, myThid )
500 ENDIF
501
502 C To be safe, make other processes wait for I/O completion
503 _BARRIER
504
505 C---+----1----+----2----+----3----+----4----+----5----+----6----+----7-|--+----|
506 RETURN
507 END

  ViewVC Help
Powered by ViewVC 1.1.22