C $Header: /u/gcmpack/MITgcm/pkg/mdsio/mdsio_writevector.F,v 1.14 2009/09/01 19:00:15 jmc Exp $ C $Name: $ #include "MDSIO_OPTIONS.h" SUBROUTINE MDSWRITEVECTOR( I fName, I filePrec, I globalfile, I arrType, I narr, I arr, I bi, I bj, I irecord, I myIter, I myThid ) C Arguments: C C fName string :: base name for file to written C filePrec integer :: number of bits per word in file (32 or 64) C globalFile logical :: selects between writing a global or tiled file C arrType char(2) :: declaration of "arr": either "RS" or "RL" C narr integer :: size of third dimension: normally either 1 or Nr C arr RS/RL :: array to write, arr(narr) C bi integer :: x tile index C bj integer :: y tile index C irecord integer :: record number to read C myIter integer :: time step number C myThid integer :: thread identifier C C Created: 03/26/99 eckert@mit.edu C Modified: 03/29/99 adcroft@mit.edu + eckert@mit.edu C Fixed to work work with _RS and _RL declarations C Modified: 07/27/99 eckert@mit.edu C Customized for state estimation (--> active_file_control.F) C Changed: 05/31/00 heimbach@mit.edu C open(dUnit, ..., status='old', ... -> status='unknown' IMPLICIT NONE C Global variables / common blocks #include "SIZE.h" #include "EEPARAMS.h" #include "PARAMS.h" #include "EESUPPORT.h" C Routine arguments CHARACTER*(*) fName INTEGER filePrec LOGICAL globalfile CHARACTER*(2) arrType INTEGER narr _RL arr(narr) INTEGER bi,bj INTEGER irecord INTEGER myIter INTEGER myThid #ifdef ALLOW_AUTODIFF C Functions INTEGER ILNBLNK INTEGER MDS_RECLEN EXTERNAL EXTERNAL C Local variables CHARACTER*(MAX_LEN_FNAM) dataFName,metaFName,pfName INTEGER iG,jG,irec,dUnit,IL,pIL LOGICAL fileIsOpen INTEGER dimList(3,3), nDims, map2gl(2) INTEGER length_of_rec CHARACTER*(MAX_LEN_MBUF) msgBuf cph( cph Deal with useSingleCpuIO cph Not implemented here for EXCH2 INTEGER vec_size #ifdef ALLOW_USE_MPI LOGICAL lprint INTEGER K,L c INTEGER iG_IO,jG_IO,npe Real*8 global(narr*nPx*nPy) _RL local(narr) #endif cph) Real*4 xy_buffer_r4(narr*nPx*nPy) Real*8 xy_buffer_r8(narr*nPx*nPy) _RL dummyRL(1) CHARACTER*8 blank8c DATA dummyRL(1) / 0. _d 0 / DATA blank8c / ' ' / DATA map2gl / 0, 1 / C ------------------------------------------------------------------ vec_size = narr*nPx*nPy C Only do I/O if I am the master thread _BEGIN_MASTER( myThid ) C Record number must be >= 1 IF (irecord .LT. 1) THEN WRITE(msgBuf,'(A,I9.8)') & ' MDSWRITEVECTOR: argument irecord = ',irecord CALL PRINT_ERROR( msgBuf, myThid ) WRITE(msgBuf,'(A)') & ' MDSWRITEVECTOR: invalid value for irecord' CALL PRINT_ERROR( msgBuf, myThid ) STOP 'ABNORMAL END: S/R MDSWRITEVECTOR' ENDIF C Assume nothing fileIsOpen = .FALSE. IL = ILNBLNK( fName ) pIL = ILNBLNK( mdsioLocalDir ) C Assign special directory IF ( mdsioLocalDir .NE. ' ' ) THEN WRITE(pfName,'(2A)') & mdsioLocalDir(1:pIL), fName(1:IL) ELSE pfName= fName ENDIF pIL=ILNBLNK( pfName ) C Assign a free unit number as the I/O channel for this routine CALL MDSFINDUNIT( dUnit, myThid ) #ifdef ALLOW_USE_MPI _END_MASTER( myThid ) C If option globalFile is desired but does not work or if C globalFile is too slow, then try using single-CPU I/O. IF (useSingleCpuIO) THEN C Master thread of process 0, only, opens a global file _BEGIN_MASTER( myThid ) IF( mpiMyId .EQ. 0 ) THEN WRITE(dataFName,'(2a)') fName(1:IL),'.data' length_of_rec=MDS_RECLEN(filePrec,vec_size,myThid) IF (irecord .EQ. 1) THEN OPEN( dUnit, file=dataFName, status=_NEW_STATUS, & access='direct', recl=length_of_rec ) ELSE OPEN( dUnit, file=dataFName, status=_OLD_STATUS, & access='direct', recl=length_of_rec ) ENDIF ENDIF _END_MASTER( myThid ) C Gather array and write it to file, one vertical level at a time DO k=1,1 IF ( arrType.EQ.'RS' ) THEN CALL MDS_BUFFERTORS( local, arr, narr, .FALSE., myThid ) ELSEIF ( arrType.EQ.'RL' ) THEN CALL MDS_BUFFERTORL( local, arr, narr, .FALSE., myThid ) ELSE WRITE(msgBuf,'(A)') & ' MDSWRITEVECTOR: illegal value for arrType' CALL PRINT_ERROR( msgBuf, myThid ) STOP 'ABNORMAL END: S/R MDSWRITEVECTOR' ENDIF cph( cph IF ( irecord .EQ. 1 .AND. fName(1:IL) .EQ. cph & 'tapelev2_7_the_main_loop_theta.it0000' ) THEN cph lprint = .TRUE. cph ELSE lprint = .FALSE. cph ENDIF cph) CALL GATHER_VECTOR( lprint, narr, global, local, myThid ) _BEGIN_MASTER( myThid ) IF( mpiMyId .EQ. 0 ) THEN irec=irecord IF (filePrec .EQ. precFloat32) THEN cph#if defined(ALLOW_EXCH2) && !defined(MISSING_TILE_IO) c cph#else /* defined(ALLOW_EXCH2) && !defined(MISSING_TILE_IO) */ DO L=1,narr*nPx*nPy xy_buffer_r4(L) = global(L) ENDDO cph#endif /* defined(ALLOW_EXCH2) && !defined(MISSING_TILE_IO) */ #ifdef _BYTESWAPIO CALL MDS_BYTESWAPR4( vec_size, xy_buffer_r4 ) #endif WRITE(dUnit,rec=irec) xy_buffer_r4 ELSEIF (filePrec .EQ. precFloat64) THEN cph#if defined(ALLOW_EXCH2) && !defined(MISSING_TILE_IO) c cph#else /* defined(ALLOW_EXCH2) && !defined(MISSING_TILE_IO) */ DO L=1,narr*nPx*nPy xy_buffer_r8(L) = global(L) ENDDO cph#endif /* defined(ALLOW_EXCH2) && !defined(MISSING_TILE_IO) */ #ifdef _BYTESWAPIO CALL MDS_BYTESWAPR8( vec_size, xy_buffer_r8 ) #endif WRITE(dUnit,rec=irec) xy_buffer_r8 ELSE WRITE(msgBuf,'(A)') & ' MDSWRITEVECTOR: illegal value for filePrec' CALL PRINT_ERROR( msgBuf, myThid ) STOP 'ABNORMAL END: S/R MDSWRITEVECTOR' ENDIF ENDIF _END_MASTER( myThid ) C End k loop ENDDO C Close data-file and create meta-file _BEGIN_MASTER( myThid ) IF( mpiMyId .EQ. 0 ) THEN CLOSE( dUnit ) WRITE(metaFName,'(2a)') fName(1:IL),'.meta' dimList(1,1)=vec_size dimList(2,1)=1 dimList(3,1)=vec_size dimList(1,2)=vec_size dimList(2,2)=1 dimList(3,2)=vec_size dimList(1,3)=1 dimList(2,3)=1 dimList(3,3)=1 nDims = 1 CALL MDS_WRITE_META( I metaFName, dataFName, the_run_name, ' ', I filePrec, nDims, dimList, map2gl, 0, blank8c, I 0, dummyRL, irecord, myIter, myThid ) ENDIF _END_MASTER( myThid ) C To be safe, make other processes wait for I/O completion _BARRIER ELSEIF ( .NOT. useSingleCpuIO ) THEN _BEGIN_MASTER( myThid ) #endif /* ALLOW_USE_MPI */ C If we are writing to a global file then we open it here IF (globalFile) THEN WRITE(dataFName,'(2A)') fName(1:IL),'.data' IF (irecord .EQ. 1) THEN length_of_rec = MDS_RECLEN( filePrec, narr, myThid ) OPEN( dUnit, file=dataFName, status=_NEW_STATUS, & access='direct', recl=length_of_rec ) fileIsOpen=.TRUE. ELSE length_of_rec = MDS_RECLEN( filePrec, narr, myThid ) OPEN( dUnit, file=dataFName, status=_OLD_STATUS, & access='direct', recl=length_of_rec ) fileIsOpen=.TRUE. ENDIF ENDIF C Loop over all tiles c DO bj=1,nSy c DO bi=1,nSx C If we are writing to a tiled MDS file then we open each one here IF (.NOT. globalFile) THEN iG=bi+(myXGlobalLo-1)/sNx ! Kludge until unstructered tiles jG=bj+(myYGlobalLo-1)/sNy ! Kludge until unstructered tiles WRITE(dataFName,'(2A,I3.3,A,I3.3,A)') & pfName(1:pIL),'.',iG,'.',jG,'.data' IF (irecord .EQ. 1) THEN length_of_rec = MDS_RECLEN( filePrec, narr, myThid ) OPEN( dUnit, file=dataFName, status=_NEW_STATUS, & access='direct', recl=length_of_rec ) fileIsOpen=.TRUE. ELSE length_of_rec = MDS_RECLEN( filePrec, narr, myThid ) OPEN( dUnit, file=dataFName, status=_OLD_STATUS, & access='direct', recl=length_of_rec ) fileIsOpen=.TRUE. ENDIF ENDIF IF (fileIsOpen) THEN IF (globalFile) THEN iG = myXGlobalLo-1+(bi-1)*sNx jG = myYGlobalLo-1+(bj-1)*sNy irec = 1 + int(iG/sNx) + (jG/sNy)*nSx*nPx + & (irecord-1)*nSx*nPx*nSy*nPy ELSE iG = 0 jG = 0 irec = irecord ENDIF IF ( arrType.EQ.'RS' ) THEN CALL MDS_WR_REC_RS( arr, xy_buffer_r4, xy_buffer_r8, I filePrec, dUnit, irec, narr, myThid ) ELSEIF ( arrType.EQ.'RL' ) THEN CALL MDS_WR_REC_RL( arr, xy_buffer_r4, xy_buffer_r8, I filePrec, dUnit, irec, narr, myThid ) ELSE WRITE(msgBuf,'(A)') & ' MDSWRITEVECTOR: illegal value for arrType' CALL PRINT_ERROR( msgBuf, myThid ) STOP 'ABNORMAL END: S/R MDSWRITEVECTOR' ENDIF ELSE WRITE(msgBuf,'(A)') & ' MDSWRITEVECTOR: I should never get to this point' CALL PRINT_ERROR( msgBuf, myThid ) STOP 'ABNORMAL END: S/R MDSWRITEVECTOR' ENDIF C If we were writing to a tiled MDS file then we close it here IF (fileIsOpen .AND. (.NOT. globalFile)) THEN CLOSE( dUnit ) fileIsOpen = .FALSE. ENDIF C Create meta-file for each tile file IF (.NOT. globalFile) THEN iG=bi+(myXGlobalLo-1)/sNx ! Kludge until unstructered tiles jG=bj+(myYGlobalLo-1)/sNy ! Kludge until unstructered tiles WRITE(metaFName,'(2a,i3.3,a,i3.3,a)') & pfName(1:pIL),'.',iG,'.',jG,'.meta' dimList(1,1) = nPx*nSx*narr dimList(2,1) = ((myXGlobalLo-1)/sNx + (bi-1))*narr + 1 dimList(3,1) = ((myXGlobalLo-1)/sNx + bi )*narr dimList(1,2) = nPy*nSy dimList(2,2) = (myYGlobalLo-1)/sNy + bj dimList(3,2) = (myYGlobalLo-1)/sNy + bj dimList(1,3) = 1 dimList(2,3) = 1 dimList(3,3) = 1 nDims = 1 CALL MDS_WRITE_META( I metaFName, dataFName, the_run_name, ' ', I filePrec, nDims, dimList, map2gl, 0, blank8c, I 0, dummyRL, irecord, myIter, myThid ) ENDIF C End of bi,bj loops c ENDDO c ENDDO C If global file was opened then close it IF (fileIsOpen .AND. globalFile) THEN CLOSE( dUnit ) fileIsOpen = .FALSE. ENDIF C Create meta-file for global file IF (globalFile) THEN WRITE(metaFName,'(2A)') fName(1:IL),'.meta' dimList(1,1) = nPx*nSx*narr dimList(2,1) = 1 dimList(3,1) = nPx*nSx*narr dimList(1,2) = nPy*nSy dimList(2,2) = 1 dimList(3,2) = nPy*nSy dimList(1,3) = 1 dimList(2,3) = 1 dimList(3,3) = 1 nDims = 1 CALL MDS_WRITE_META( I metaFName, dataFName, the_run_name, ' ', I filePrec, nDims, dimList, map2gl, 0, blank8c, I 0, dummyRL, irecord, myIter, myThid ) c I metaFName, dataFName, the_run_name, titleLine, c I filePrec, nDims, dimList, map2gl, nFlds, fldList, c I nTimRec, timList, irecord, myIter, myThid ) ENDIF _END_MASTER( myThid ) #ifdef ALLOW_USE_MPI C End-if useSingleCpuIO ENDIF #endif /* ALLOW_USE_MPI */ #else /* ALLOW_AUTODIFF */ STOP 'ABNORMAL END: S/R MDSWRITEVECTOR is empty' #endif /* ALLOW_AUTODIFF */ C ------------------------------------------------------------------ RETURN END