1 |
C $Header: /u/gcmpack/MITgcm/pkg/mdsio/mdsio_writevector.F,v 1.15 2013/01/13 22:43:53 jmc Exp $ |
2 |
C $Name: $ |
3 |
|
4 |
#include "MDSIO_OPTIONS.h" |
5 |
|
6 |
CBOP |
7 |
C !ROUTINE: MDS_WRITE_TAPE |
8 |
C !INTERFACE: |
9 |
SUBROUTINE MDS_WRITE_TAPE( |
10 |
I fName, |
11 |
I filePrec, |
12 |
I globalfile, |
13 |
I arrType, |
14 |
I nSize, |
15 |
I fldR8, fldR4, |
16 |
I singleCpuIO, |
17 |
I iRec, |
18 |
I myIter, |
19 |
I myThid ) |
20 |
|
21 |
C !DESCRIPTION: |
22 |
C MDS_WRITE_TAPE: write an array (treated as vector) to a tape-file |
23 |
C (renamed from MDSWRITEVECTOR with 2 explicit input array types) |
24 |
C |
25 |
C Arguments: |
26 |
C fName string :: base name for file to write |
27 |
C filePrec integer :: number of bits per word in file (32 or 64) |
28 |
C globalFile logical :: selects between writing a global or tiled file |
29 |
C arrType char(2) :: which array (fldR8/R4) to write, either "R8" or "R4" |
30 |
C nSize integer :: number of elements of input array "fldR8/R4" to write |
31 |
C fldR8 ( R8 ) :: array to write if arrType="R8", fldR8(nSize) |
32 |
C fldR4 ( R4 ) :: array to write if arrType="R4", fldR4(nSize) |
33 |
C bi,bj integer :: tile indices (if tiled array) |
34 |
C singleCpuIO ( L ) :: only proc 0 do IO and collect data from other procs |
35 |
C iRec integer :: record number to write |
36 |
C myIter integer :: time step number |
37 |
C myThid integer :: my Thread Id number |
38 |
|
39 |
C !USES: |
40 |
IMPLICIT NONE |
41 |
|
42 |
C-- Global variables -- |
43 |
#include "SIZE.h" |
44 |
#include "EEPARAMS.h" |
45 |
#include "PARAMS.h" |
46 |
|
47 |
C !INPUT/OUTPUT PARAMETERS: |
48 |
CHARACTER*(*) fName |
49 |
INTEGER filePrec |
50 |
LOGICAL globalfile |
51 |
CHARACTER*(2) arrType |
52 |
INTEGER nSize |
53 |
_R8 fldR8(*) |
54 |
_R4 fldR4(*) |
55 |
LOGICAL singleCpuIO |
56 |
INTEGER iRec |
57 |
INTEGER myIter |
58 |
INTEGER myThid |
59 |
|
60 |
#ifdef ALLOW_AUTODIFF |
61 |
|
62 |
C !FUNCTIONS: |
63 |
INTEGER ILNBLNK |
64 |
INTEGER MDS_RECLEN |
65 |
EXTERNAL ILNBLNK |
66 |
EXTERNAL MDS_RECLEN |
67 |
|
68 |
C !LOCAL VARIABLES: |
69 |
CHARACTER*(MAX_LEN_FNAM) dataFName, metaFName, pfName |
70 |
INTEGER iG, jG, jRec, dUnit, IL, pIL |
71 |
INTEGER dimList(3,1), nDims, map2gl(2) |
72 |
INTEGER length_of_rec |
73 |
CHARACTER*(MAX_LEN_MBUF) msgBuf |
74 |
|
75 |
C simple implementation of singleCpuIO without any specific EXCH2 |
76 |
C feature (should work as long as reading and writing match) |
77 |
INTEGER j |
78 |
INTEGER vec_size |
79 |
C Note: would be better to use explicit (allocate/delocate) dynamical |
80 |
C allocation instead of this implicit form: |
81 |
_R8 gl_buffer_r8(nSize*nPx*nPy) |
82 |
_R4 gl_buffer_r4(nSize*nPx*nPy) |
83 |
_R8 local_r8 (nSize) |
84 |
_R4 local_r4 (nSize) |
85 |
_RL dummyRL(1) |
86 |
CHARACTER*8 blank8c |
87 |
CEOP |
88 |
|
89 |
DATA dummyRL(1) / 0. _d 0 / |
90 |
DATA blank8c / ' ' / |
91 |
DATA map2gl / 0, 1 / |
92 |
|
93 |
vec_size = nSize*nPx*nPy |
94 |
|
95 |
C-- Copy input array to local buffer |
96 |
IF ( arrType.EQ.'R4' ) THEN |
97 |
IF ( filePrec.EQ.precFloat32 ) THEN |
98 |
DO j=1,nSize |
99 |
local_r4(j) = fldR4(j) |
100 |
ENDDO |
101 |
ELSE |
102 |
DO j=1,nSize |
103 |
local_r8(j) = fldR4(j) |
104 |
ENDDO |
105 |
ENDIF |
106 |
ELSEIF ( arrType.EQ.'R8' ) THEN |
107 |
IF ( filePrec.EQ.precFloat32 ) THEN |
108 |
DO j=1,nSize |
109 |
local_r4(j) = fldR8(j) |
110 |
ENDDO |
111 |
ELSE |
112 |
DO j=1,nSize |
113 |
local_r8(j) = fldR8(j) |
114 |
ENDDO |
115 |
ENDIF |
116 |
ELSE |
117 |
WRITE(msgBuf,'(A)') |
118 |
& ' MDS_WRITE_TAPE: illegal value for arrType' |
119 |
CALL PRINT_ERROR( msgBuf, myThid ) |
120 |
STOP 'ABNORMAL END: S/R MDS_WRITE_TAPE' |
121 |
ENDIF |
122 |
|
123 |
C---+----1----+----2----+----3----+----4----+----5----+----6----+----7-|--+----| |
124 |
|
125 |
C-- Only do I/O if I am the master thread |
126 |
_BEGIN_MASTER( myThid ) |
127 |
|
128 |
C- Record number must be >= 1 |
129 |
IF ( iRec.LT.1 ) THEN |
130 |
WRITE(msgBuf,'(A,I10)') |
131 |
& ' MDS_WRITE_TAPE: argument iRec =',iRec |
132 |
CALL PRINT_ERROR( msgBuf, myThid ) |
133 |
WRITE(msgBuf,'(A)') |
134 |
& ' MDS_WRITE_TAPE: invalid value for iRec' |
135 |
CALL PRINT_ERROR( msgBuf, myThid ) |
136 |
STOP 'ABNORMAL END: S/R MDS_WRITE_TAPE' |
137 |
ENDIF |
138 |
|
139 |
C- Assume nothing |
140 |
IL = ILNBLNK( fName ) |
141 |
pIL = ILNBLNK( mdsioLocalDir ) |
142 |
|
143 |
C- Assign special directory |
144 |
IF ( pIL.EQ.0 ) THEN |
145 |
pfName = fName |
146 |
ELSE |
147 |
WRITE(pfName,'(2A)') mdsioLocalDir(1:pIL), fName(1:IL) |
148 |
ENDIF |
149 |
pIL = ILNBLNK( pfName ) |
150 |
IF ( debugLevel.GE.debLevC .AND. |
151 |
& ( .NOT.singleCpuIO .OR. myProcId.EQ.0 ) ) THEN |
152 |
WRITE(msgBuf,'(A,I8,2A)') |
153 |
& ' MDS_WRITE_TAPE: iRec=', iRec, ', file=', pfName(1:pIL) |
154 |
CALL PRINT_MESSAGE( msgBuf, standardMessageUnit, |
155 |
& SQUEEZE_RIGHT, myThid ) |
156 |
ENDIF |
157 |
|
158 |
C- Assign a free unit number as the I/O channel for this routine |
159 |
CALL MDSFINDUNIT( dUnit, myThid ) |
160 |
|
161 |
C If option globalFile is desired but does not work or if |
162 |
C globalFile is too slow, then try using single-CPU I/O. |
163 |
IF ( singleCpuIO ) THEN |
164 |
|
165 |
C- Gather array from all procs |
166 |
IF ( filePrec.EQ.precFloat32 ) THEN |
167 |
CALL GATHER_VEC_R4( gl_buffer_r4, local_r4, nSize, myThid ) |
168 |
ELSEIF ( filePrec.EQ.precFloat64 ) THEN |
169 |
CALL GATHER_VEC_R8( gl_buffer_r8, local_r8, nSize, myThid ) |
170 |
ELSE |
171 |
WRITE(msgBuf,'(A)') |
172 |
& ' MDS_WRITE_TAPE: illegal value for filePrec' |
173 |
CALL PRINT_ERROR( msgBuf, myThid ) |
174 |
STOP 'ABNORMAL END: S/R MDS_WRITE_TAPE' |
175 |
ENDIF |
176 |
|
177 |
IF ( myProcId .EQ. 0 ) THEN |
178 |
C-- Master thread of process 0, only, opens a global file |
179 |
|
180 |
WRITE(dataFName,'(2a)') fName(1:IL),'.data' |
181 |
length_of_rec = MDS_RECLEN( filePrec, vec_size, myThid ) |
182 |
IF (iRec .EQ. 1) THEN |
183 |
OPEN( dUnit, file=dataFName, status=_NEW_STATUS, |
184 |
& access='direct', recl=length_of_rec ) |
185 |
ELSE |
186 |
OPEN( dUnit, file=dataFName, status=_OLD_STATUS, |
187 |
& access='direct', recl=length_of_rec ) |
188 |
ENDIF |
189 |
|
190 |
C- Write global buffer to file: |
191 |
IF ( filePrec.EQ.precFloat32 ) THEN |
192 |
#ifdef _BYTESWAPIO |
193 |
CALL MDS_BYTESWAPR4( vec_size, gl_buffer_r4 ) |
194 |
#endif |
195 |
WRITE(dUnit,rec=iRec) gl_buffer_r4 |
196 |
ELSEIF ( filePrec.EQ.precFloat64 ) THEN |
197 |
#ifdef _BYTESWAPIO |
198 |
CALL MDS_BYTESWAPR8( vec_size, gl_buffer_r8 ) |
199 |
#endif |
200 |
WRITE(dUnit,rec=iRec) gl_buffer_r8 |
201 |
ENDIF |
202 |
|
203 |
C- Close data-file and create meta-file |
204 |
CLOSE( dUnit ) |
205 |
WRITE(metaFName,'(2a)') fName(1:IL),'.meta' |
206 |
dimList(1,1) = vec_size |
207 |
dimList(2,1) = 1 |
208 |
dimList(3,1) = vec_size |
209 |
nDims = 1 |
210 |
CALL MDS_WRITE_META( |
211 |
I metaFName, dataFName, the_run_name, ' ', |
212 |
I filePrec, nDims, dimList, map2gl, 0, blank8c, |
213 |
I 0, dummyRL, oneRL, iRec, myIter, myThid ) |
214 |
|
215 |
C- end if myProcId=0 |
216 |
ENDIF |
217 |
|
218 |
C---+----1----+----2----+----3----+----4----+----5----+----6----+----7-|--+----| |
219 |
C if ( singleCpuIO ), else |
220 |
ELSEIF ( .NOT. singleCpuIO ) THEN |
221 |
|
222 |
IF ( globalFile ) THEN |
223 |
C- If we are writing to a global file then we open it here |
224 |
WRITE(dataFName,'(2A)') fName(1:IL),'.data' |
225 |
length_of_rec = MDS_RECLEN( filePrec, nSize, myThid ) |
226 |
IF ( iRec.EQ.1 ) THEN |
227 |
OPEN( dUnit, file=dataFName, status=_NEW_STATUS, |
228 |
& access='direct', recl=length_of_rec ) |
229 |
ELSE |
230 |
OPEN( dUnit, file=dataFName, status=_OLD_STATUS, |
231 |
& access='direct', recl=length_of_rec ) |
232 |
ENDIF |
233 |
|
234 |
ELSE |
235 |
C- If we are writing to a tiled MDS file then we open each one here |
236 |
iG = 1 + (myXGlobalLo-1)/sNx |
237 |
jG = 1 + (myYGlobalLo-1)/sNy |
238 |
WRITE(dataFName,'(2A,I3.3,A,I3.3,A)') |
239 |
& pfName(1:pIL),'.',iG,'.',jG,'.data' |
240 |
length_of_rec = MDS_RECLEN( filePrec, nSize, myThid ) |
241 |
IF (iRec .EQ. 1) THEN |
242 |
OPEN( dUnit, file=dataFName, status=_NEW_STATUS, |
243 |
& access='direct', recl=length_of_rec ) |
244 |
ELSE |
245 |
OPEN( dUnit, file=dataFName, status=_OLD_STATUS, |
246 |
& access='direct', recl=length_of_rec ) |
247 |
ENDIF |
248 |
ENDIF |
249 |
|
250 |
C- Write local buffer to file: |
251 |
IF (globalFile) THEN |
252 |
C-- Original: nPy=2, nSx=2 -> produces too large file (1.5 x normal size) |
253 |
c iG = myXGlobalLo-1+(bi-1)*sNx |
254 |
c jG = myYGlobalLo-1+(bj-1)*sNy |
255 |
c jRec = 1 + int(iG/sNx) + (jG/sNy)*nSx*nPx + |
256 |
c & (iRec-1)*nSx*nPx*nSy*nPy |
257 |
C-- Alternative: same layout as in scatter/gather_vector (for singleCpuIO) |
258 |
C problem: nPx=2, nSx=2, writing a global (i.e., with bi,bj dim); |
259 |
C- 2nd proc get iG=3 -> badly placed data over nPx*nPy*nSize range |
260 |
C that will be overwritten by next record |
261 |
c iG = 1 + (myXGlobalLo-1)/sNx |
262 |
c jG = 1 + (myYGlobalLo-1)/sNy |
263 |
c jRec = iG + (jG-1)*nPx + (iRec-1)*nPx*nPy |
264 |
C-- Simpler: should work (but hard to interpret the sequence of data in file) |
265 |
jRec = 1 + myProcId + (iRec-1)*nPx*nPy |
266 |
ELSE |
267 |
jRec = iRec |
268 |
ENDIF |
269 |
IF ( filePrec.EQ.precFloat32 ) THEN |
270 |
#ifdef _BYTESWAPIO |
271 |
CALL MDS_BYTESWAPR4( nSize, local_r4 ) |
272 |
#endif |
273 |
WRITE(dUnit,rec=jRec) local_r4 |
274 |
ELSEIF ( filePrec.EQ.precFloat64 ) THEN |
275 |
#ifdef _BYTESWAPIO |
276 |
CALL MDS_BYTESWAPR8( nSize, local_r8 ) |
277 |
#endif |
278 |
WRITE(dUnit,rec=jRec) local_r8 |
279 |
ELSE |
280 |
WRITE(msgBuf,'(A)') |
281 |
& ' MDS_WRITE_TAPE: illegal value for filePrec' |
282 |
CALL PRINT_ERROR( msgBuf, myThid ) |
283 |
STOP 'ABNORMAL END: S/R MDS_WRITE_TAPE' |
284 |
ENDIF |
285 |
|
286 |
C- Close data-file and create meta-file |
287 |
CLOSE( dUnit ) |
288 |
IF ( globalFile ) THEN |
289 |
C meta-file for global file |
290 |
WRITE(metaFName,'(2A)') fName(1:IL),'.meta' |
291 |
dimList(1,1) = vec_size |
292 |
dimList(2,1) = 1 |
293 |
dimList(3,1) = vec_size |
294 |
nDims = 1 |
295 |
ELSE |
296 |
C meta-file for tiled file |
297 |
iG = 1 + (myXGlobalLo-1)/sNx |
298 |
jG = 1 + (myYGlobalLo-1)/sNy |
299 |
WRITE(metaFName,'(2A,I3.3,A,I3.3,A)') |
300 |
& pfName(1:pIL),'.',iG,'.',jG,'.meta' |
301 |
dimList(1,1) = nPx*nPy*nSize |
302 |
dimList(2,1) = 1 + myProcId*nSize |
303 |
dimList(3,1) = (1+myProcId)*nSize |
304 |
nDims = 1 |
305 |
ENDIF |
306 |
C- write meta-file |
307 |
CALL MDS_WRITE_META( |
308 |
I metaFName, dataFName, the_run_name, ' ', |
309 |
I filePrec, nDims, dimList, map2gl, 0, blank8c, |
310 |
I 0, dummyRL, oneRL, iRec, myIter, myThid ) |
311 |
c I metaFName, dataFName, the_run_name, titleLine, |
312 |
c I filePrec, nDims, dimList, map2gl, nFlds, fldList, |
313 |
c I nTimRec, timList, misVal, iRec, myIter, myThid ) |
314 |
|
315 |
C end-if ( .not. singleCpuIO ) |
316 |
ENDIF |
317 |
|
318 |
_END_MASTER( myThid ) |
319 |
|
320 |
#else /* ALLOW_AUTODIFF */ |
321 |
STOP 'ABNORMAL END: S/R MDS_WRITE_TAPE is empty' |
322 |
#endif /* ALLOW_AUTODIFF */ |
323 |
|
324 |
RETURN |
325 |
END |