/[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.9 - (show annotations) (download)
Sat May 16 13:37:38 2009 UTC (16 years, 1 month ago) by jmc
Branch: MAIN
CVS Tags: checkpoint61o
Changes since 1.8: +55 -69 lines
- remove MISSING_TILE_IO (from MDSIO_OPTIONS.h), replaced by run-time
  parameter "W2_useE2ioLayOut" (read from file "data.exch2").
  Note: was not effective for globalFile & useSingleCpuIO=F; now fixed.
- move MDSIO_SCPU.h (pkg/mdsio) to EEBUFF_SCPU.h (eesupp/inc).

1 C $Header: /u/gcmpack/MITgcm/pkg/mdsio/mdsio_write_field.F,v 1.8 2009/05/12 19:56:36 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_SIZE.h"
75 #include "W2_EXCH2_TOPOLOGY.h"
76 #include "W2_EXCH2_PARAMS.h"
77 #endif /* ALLOW_EXCH2 */
78 #include "EEBUFF_SCPU.h"
79
80 C !INPUT PARAMETERS:
81 CHARACTER*(*) fName
82 INTEGER filePrec
83 LOGICAL globalFile
84 LOGICAL useCurrentDir
85 CHARACTER*(2) arrType
86 INTEGER kSize, kLo, kHi
87 cph(
88 cph Real arr(*)
89 _RL arr(1-oLx:sNx+oLx,1-oLy:sNy+oLy,kSize,nSx,nSy)
90 cph)
91 INTEGER jrecord
92 INTEGER myIter
93 INTEGER myThid
94 C !OUTPUT PARAMETERS:
95
96 C !FUNCTIONS
97 INTEGER ILNBLNK
98 INTEGER MDS_RECLEN
99 LOGICAL MASTER_CPU_IO
100 EXTERNAL ILNBLNK
101 EXTERNAL MDS_RECLEN
102 EXTERNAL MASTER_CPU_IO
103
104 C !LOCAL VARIABLES:
105 CHARACTER*(MAX_LEN_FNAM) dataFName,metaFName,pfName
106 CHARACTER*(MAX_LEN_MBUF) msgBuf
107 LOGICAL fileIsOpen
108 LOGICAL iAmDoingIO
109 LOGICAL writeMetaF
110 LOGICAL useExch2ioLayOut
111 LOGICAL zeroBuff
112 INTEGER xSize, ySize
113 INTEGER irecord
114 INTEGER iG,jG,bi,bj,i,j,k,nNz
115 INTEGER irec,dUnit,IL,pIL
116 INTEGER dimList(3,3), nDims, map2gl(2)
117 INTEGER length_of_rec
118 Real*4 r4seg(sNx)
119 Real*8 r8seg(sNx)
120 INTEGER tNx, tNy, global_nTx
121 INTEGER tBx, tBy, iGjLoc, jGjLoc
122 #ifdef ALLOW_EXCH2
123 INTEGER tN
124 #endif /* ALLOW_EXCH2 */
125
126 C---+----1----+----2----+----3----+----4----+----5----+----6----+----7-|--+----|
127 C Set dimensions:
128 xSize = Nx
129 ySize = Ny
130 useExch2ioLayOut = .FALSE.
131 #ifdef ALLOW_EXCH2
132 IF ( W2_useE2ioLayOut ) THEN
133 xSize = exch2_global_Nx
134 ySize = exch2_global_Ny
135 useExch2ioLayOut = .TRUE.
136 ENDIF
137 #endif /* ALLOW_EXCH2 */
138
139 C- default:
140 iGjLoc = 0
141 jGjLoc = 1
142
143 C Assume nothing
144 fileIsOpen = .FALSE.
145 IL = ILNBLNK( fName )
146 pIL = ILNBLNK( mdsioLocalDir )
147 nNz = 1 + kHi - kLo
148 irecord = ABS(jrecord)
149 writeMetaF = jrecord.GT.0
150
151 C Only do I/O if I am the master thread (and mpi process 0 IF useSingleCpuIO):
152 iAmDoingIO = MASTER_CPU_IO(myThid)
153
154 C Only do I/O if I am the master thread
155 IF ( iAmDoingIO ) THEN
156
157 C Record number must be >= 1
158 IF (irecord .LT. 1) THEN
159 WRITE(msgBuf,'(A,I9.8)')
160 & ' MDS_WRITE_FIELD: argument irecord = ',irecord
161 CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
162 & SQUEEZE_RIGHT , myThid)
163 WRITE(msgBuf,'(A)')
164 & ' MDS_WRITE_FIELD: invalid value for irecord'
165 CALL PRINT_ERROR( msgBuf, myThid )
166 STOP 'ABNORMAL END: S/R MDS_WRITE_FIELD'
167 ENDIF
168 C check for valid sub-set of levels:
169 IF ( kLo.LT.1 .OR. kHi.GT.kSize ) THEN
170 WRITE(msgBuf,'(3(A,I6))')
171 & ' MDS_WRITE_FIELD: arguments kSize=', kSize,
172 & ' , kLo=', kLo, ' , kHi=', kHi
173 CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
174 & SQUEEZE_RIGHT , myThid)
175 WRITE(msgBuf,'(A)')
176 & ' MDS_WRITE_FIELD: invalid sub-set of levels'
177 CALL PRINT_ERROR( msgBuf, myThid )
178 STOP 'ABNORMAL END: S/R MDS_WRITE_FIELD'
179 ENDIF
180
181 C Assign special directory
182 IF ( useCurrentDir .OR. pIL.EQ.0 ) THEN
183 pfName = fName
184 ELSE
185 WRITE(pfName,'(2A)') mdsioLocalDir(1:pIL), fName(1:IL)
186 ENDIF
187 pIL=ILNBLNK( pfName )
188
189 C Assign a free unit number as the I/O channel for this routine
190 CALL MDSFINDUNIT( dUnit, myThid )
191
192 C- endif iAmDoingIO
193 ENDIF
194
195 C If option globalFile is desired but does not work or if
196 C globalFile is too slow, then try using single-CPU I/O.
197 IF (useSingleCpuIO) THEN
198
199 C Master thread of process 0, only, opens a global file
200 IF ( iAmDoingIO ) THEN
201 WRITE(dataFName,'(2a)') fName(1:IL),'.data'
202 length_of_rec=MDS_RECLEN(filePrec,xSize*ySize,myThid)
203 IF (irecord .EQ. 1) THEN
204 OPEN( dUnit, file=dataFName, status=_NEW_STATUS,
205 & access='direct', recl=length_of_rec )
206 ELSE
207 OPEN( dUnit, file=dataFName, status=_OLD_STATUS,
208 & access='direct', recl=length_of_rec )
209 ENDIF
210 ENDIF
211
212 C Gather array and WRITE it to file, one vertical level at a time
213 DO k=kLo,kHi
214 zeroBuff = k.EQ.kLo
215 C- copy from arr(level=k) to 2-D "local":
216 IF ( filePrec.EQ.precFloat32 ) THEN
217 IF ( arrType.EQ.'RS' ) THEN
218 CALL MDS_PASS_R4toRS( sharedLocBuf_r4,
219 & arr, k, kSize, .FALSE., myThid )
220 ELSEIF ( arrType.EQ.'RL' ) THEN
221 CALL MDS_PASS_R4toRL( sharedLocBuf_r4,
222 & arr, k, kSize, .FALSE., myThid )
223 ELSE
224 WRITE(msgBuf,'(A)')
225 & ' MDS_WRITE_FIELD: illegal value for arrType'
226 CALL PRINT_ERROR( msgBuf, myThid )
227 STOP 'ABNORMAL END: S/R MDS_WRITE_FIELD'
228 ENDIF
229 CALL GATHER_2D_R4(
230 O xy_buffer_r4,
231 I sharedLocBuf_r4,
232 I xSize, ySize,
233 I useExch2ioLayOut, zeroBuff, myThid )
234 ELSEIF ( filePrec.EQ.precFloat64 ) THEN
235 IF ( arrType.EQ.'RS' ) THEN
236 CALL MDS_PASS_R8toRS( sharedLocBuf_r8,
237 & arr, k, kSize, .FALSE., myThid )
238 ELSEIF ( arrType.EQ.'RL' ) THEN
239 CALL MDS_PASS_R8toRL( sharedLocBuf_r8,
240 & arr, k, kSize, .FALSE., myThid )
241 ELSE
242 WRITE(msgBuf,'(A)')
243 & ' MDS_WRITE_FIELD: illegal value for arrType'
244 CALL PRINT_ERROR( msgBuf, myThid )
245 STOP 'ABNORMAL END: S/R MDS_WRITE_FIELD'
246 ENDIF
247 CALL GATHER_2D_R8(
248 O xy_buffer_r8,
249 I sharedLocBuf_r8,
250 I xSize, ySize,
251 I useExch2ioLayOut, zeroBuff, myThid )
252 ELSE
253 WRITE(msgBuf,'(A)')
254 & ' MDS_WRITE_FIELD: illegal value for filePrec'
255 CALL PRINT_ERROR( msgBuf, myThid )
256 STOP 'ABNORMAL END: S/R MDS_WRITE_FIELD'
257 ENDIF
258
259 IF ( iAmDoingIO ) THEN
260 irec=k+1-kLo+nNz*(irecord-1)
261 IF (filePrec .EQ. precFloat32) THEN
262 #ifdef _BYTESWAPIO
263 CALL MDS_BYTESWAPR4( xSize*ySize, xy_buffer_r4 )
264 #endif
265 WRITE(dUnit,rec=irec) ( xy_buffer_r4(i),i=1,xSize*ySize )
266 ELSEIF (filePrec .EQ. precFloat64) THEN
267 #ifdef _BYTESWAPIO
268 CALL MDS_BYTESWAPR8( xSize*ySize, xy_buffer_r8 )
269 #endif
270 WRITE(dUnit,rec=irec) ( xy_buffer_r8(i),i=1,xSize*ySize )
271 ELSE
272 WRITE(msgBuf,'(A)')
273 & ' MDS_WRITE_FIELD: illegal value for filePrec'
274 CALL PRINT_ERROR( msgBuf, myThid )
275 STOP 'ABNORMAL END: S/R MDS_WRITE_FIELD'
276 ENDIF
277 C- end if iAmDoingIO
278 ENDIF
279 C- end of k loop
280 ENDDO
281
282 C Close data-file
283 IF ( iAmDoingIO ) THEN
284 CLOSE( dUnit )
285 ENDIF
286
287 C---+----1----+----2----+----3----+----4----+----5----+----6----+----7-|--+----|
288 C--- else .NOT.useSingleCpuIO
289 ELSE
290
291 C Only do I/O if I am the master thread
292 IF ( iAmDoingIO ) THEN
293
294 C If we are writing to a global file then we open it here
295 IF (globalFile) THEN
296 WRITE(dataFName,'(2a)') fName(1:IL),'.data'
297 IF (irecord .EQ. 1) THEN
298 length_of_rec=MDS_RECLEN( filePrec, sNx, myThid )
299 OPEN( dUnit, file=dataFName, status=_NEW_STATUS,
300 & access='direct', recl=length_of_rec )
301 fileIsOpen=.TRUE.
302 ELSE
303 length_of_rec=MDS_RECLEN( filePrec, sNx, myThid )
304 OPEN( dUnit, file=dataFName, status=_OLD_STATUS,
305 & access='direct', recl=length_of_rec )
306 fileIsOpen=.TRUE.
307 ENDIF
308 ENDIF
309
310 C Loop over all tiles
311 DO bj=1,nSy
312 DO bi=1,nSx
313 C If we are writing to a tiled MDS file then we open each one here
314 IF (.NOT. globalFile) THEN
315 iG=bi+(myXGlobalLo-1)/sNx
316 jG=bj+(myYGlobalLo-1)/sNy
317 WRITE(dataFName,'(2A,I3.3,A,I3.3,A)')
318 & pfName(1:pIL),'.',iG,'.',jG,'.data'
319 IF (irecord .EQ. 1) THEN
320 length_of_rec=MDS_RECLEN( filePrec, sNx, myThid )
321 OPEN( dUnit, file=dataFName, status=_NEW_STATUS,
322 & access='direct', recl=length_of_rec )
323 fileIsOpen=.TRUE.
324 ELSE
325 length_of_rec=MDS_RECLEN( filePrec, sNx, myThid )
326 OPEN( dUnit, file=dataFName, status=_OLD_STATUS,
327 & access='direct', recl=length_of_rec )
328 fileIsOpen=.TRUE.
329 ENDIF
330 ENDIF
331
332 IF (fileIsOpen) THEN
333 tNx = sNx
334 tNy = sNy
335 global_nTx = xSize/sNx
336 tBx = myXGlobalLo-1 + (bi-1)*sNx
337 tBy = myYGlobalLo-1 + (bj-1)*sNy
338 #ifdef ALLOW_EXCH2
339 IF ( useExch2ioLayOut ) THEN
340 tN = W2_myTileList(bi)
341 c tNx = exch2_tNx(tN)
342 c tNy = exch2_tNy(tN)
343 c global_nTx = exch2_global_Nx/tNx
344 tBx = exch2_txGlobalo(tN) - 1
345 tBy = exch2_tyGlobalo(tN) - 1
346 IF ( exch2_mydNx(tN) .GT. xSize ) THEN
347 C- face x-size larger than glob-size : fold it
348 iGjLoc = 0
349 jGjLoc = exch2_mydNx(tN) / xSize
350 ELSEIF ( exch2_tNy(tN) .GT. ySize ) THEN
351 C- tile y-size larger than glob-size : make a long line
352 iGjLoc = exch2_mydNx(tN)
353 jGjLoc = 0
354 ELSE
355 C- default (face fit into global-IO-array)
356 iGjLoc = 0
357 jGjLoc = 1
358 ENDIF
359 ENDIF
360 #endif /* ALLOW_EXCH2 */
361 DO k=1,nNz
362 DO j=1,tNy
363 IF (globalFile) THEN
364 irec = 1 + ( tBx + (j-1)*iGjLoc )/tNx
365 & + ( tBy + (j-1)*jGjLoc )*global_nTx
366 & +( k-kLo + (irecord-1)*nNz )*global_nTx*ySize
367 ELSE
368 irec = j + ( k-kLo + (irecord-1)*nNz )*sNy
369 ENDIF
370 IF (filePrec .EQ. precFloat32) THEN
371 IF (arrType .EQ. 'RS') THEN
372 CALL MDS_SEG4toRS( j,bi,bj,k,kSize, r4seg,.FALSE.,arr )
373 ELSEIF (arrType .EQ. 'RL') THEN
374 CALL MDS_SEG4toRL( j,bi,bj,k,kSize, r4seg,.FALSE.,arr )
375 ELSE
376 WRITE(msgBuf,'(A)')
377 & ' MDS_WRITE_FIELD: illegal value for arrType'
378 CALL PRINT_ERROR( msgBuf, myThid )
379 STOP 'ABNORMAL END: S/R MDS_WRITE_FIELD'
380 ENDIF
381 #ifdef _BYTESWAPIO
382 CALL MDS_BYTESWAPR4( sNx, r4seg )
383 #endif
384 WRITE(dUnit,rec=irec) r4seg
385 ELSEIF (filePrec .EQ. precFloat64) THEN
386 IF (arrType .EQ. 'RS') THEN
387 CALL MDS_SEG8toRS( j,bi,bj,k,kSize, r8seg,.FALSE.,arr )
388 ELSEIF (arrType .EQ. 'RL') THEN
389 CALL MDS_SEG8toRL( j,bi,bj,k,kSize, r8seg,.FALSE.,arr )
390 ELSE
391 WRITE(msgBuf,'(A)')
392 & ' MDS_WRITE_FIELD: illegal value for arrType'
393 CALL PRINT_ERROR( msgBuf, myThid )
394 STOP 'ABNORMAL END: S/R MDS_WRITE_FIELD'
395 ENDIF
396 #ifdef _BYTESWAPIO
397 CALL MDS_BYTESWAPR8( sNx, r8seg )
398 #endif
399 WRITE(dUnit,rec=irec) r8seg
400 ELSE
401 WRITE(msgBuf,'(A)')
402 & ' MDS_WRITE_FIELD: illegal value for filePrec'
403 CALL PRINT_ERROR( msgBuf, myThid )
404 STOP 'ABNORMAL END: S/R MDS_WRITE_FIELD'
405 ENDIF
406 C End of j loop
407 ENDDO
408 C End of k loop
409 ENDDO
410 ELSE
411 C fileIsOpen=F
412 WRITE(msgBuf,'(A)')
413 & ' MDS_WRITE_FIELD: I should never get to this point'
414 CALL PRINT_ERROR( msgBuf, myThid )
415 STOP 'ABNORMAL END: S/R MDS_WRITE_FIELD'
416 ENDIF
417 C If we were writing to a tiled MDS file then we close it here
418 IF (fileIsOpen .AND. (.NOT. globalFile)) THEN
419 CLOSE( dUnit )
420 fileIsOpen = .FALSE.
421 ENDIF
422 C Create meta-file for each tile if we are tiling
423 IF ( .NOT.globalFile .AND. writeMetaF ) THEN
424 iG=bi+(myXGlobalLo-1)/sNx
425 jG=bj+(myYGlobalLo-1)/sNy
426 WRITE(metaFname,'(2A,I3.3,A,I3.3,A)')
427 & pfName(1:pIL),'.',iG,'.',jG,'.meta'
428 dimList(1,1) = xSize
429 dimList(2,1) = tBx + 1
430 dimList(3,1) = tBx + tNx
431 dimList(1,2) = ySize
432 dimList(2,2) = tBy + 1
433 dimList(3,2) = tBy + tNy
434 dimList(1,3) = nNz
435 dimList(2,3) = 1
436 dimList(3,3) = nNz
437 nDims = 3
438 IF ( nNz.EQ.1 ) nDims = 2
439 map2gl(1) = iGjLoc
440 map2gl(2) = jGjLoc
441 CALL MDS_WRITE_META(
442 I metaFName, dataFName, the_run_name, ' ',
443 I filePrec, nDims,dimList,map2gl, 0, ' ',
444 I 0, UNSET_RL, irecord, myIter, myThid )
445 ENDIF
446 C End of bi,bj loops
447 ENDDO
448 ENDDO
449
450 C If global file was opened then close it
451 IF (fileIsOpen .AND. globalFile) THEN
452 CLOSE( dUnit )
453 fileIsOpen = .FALSE.
454 ENDIF
455
456 C- endif iAmDoingIO
457 ENDIF
458
459 C if useSingleCpuIO / else / end
460 ENDIF
461
462 C Create meta-file for the global-file (also if useSingleCpuIO)
463 IF ( writeMetaF .AND. iAmDoingIO .AND.
464 & (globalFile .OR. useSingleCpuIO) ) THEN
465 WRITE(metaFName,'(2A)') fName(1:IL),'.meta'
466 dimList(1,1) = xSize
467 dimList(2,1) = 1
468 dimList(3,1) = xSize
469 dimList(1,2) = ySize
470 dimList(2,2) = 1
471 dimList(3,2) = ySize
472 dimList(1,3) = nNz
473 dimList(2,3) = 1
474 dimList(3,3) = nNz
475 nDims = 3
476 IF ( nNz.EQ.1 ) nDims = 2
477 map2gl(1) = 0
478 map2gl(2) = 1
479 CALL MDS_WRITE_META(
480 I metaFName, dataFName, the_run_name, ' ',
481 I filePrec, nDims,dimList,map2gl, 0, ' ',
482 I 0, UNSET_RL, irecord, myIter, myThid )
483 c I metaFName, dataFName, the_run_name, titleLine,
484 c I filePrec, nDims, dimList, map2gl, nFlds, fldList,
485 c I nTimRec, timList, irecord, myIter, myThid )
486 ENDIF
487
488 C To be safe, make other processes wait for I/O completion
489 _BARRIER
490
491 C---+----1----+----2----+----3----+----4----+----5----+----6----+----7-|--+----|
492 RETURN
493 END

  ViewVC Help
Powered by ViewVC 1.1.22