Hello,
I am now writing Fortran code with I/O API to handle gridded emission netCDF files. It seems that using READ3() and WRITE3() to read and write data is not as fast as using netcdf.getVar() and ncwrite() in MATLAB. And at last it takes a few seconds to shut program down with M3EXIT(). So I wonder if this speed is normal for the I/O routines in module M3UTILIO. And is there some way to speed up the code with I/O API?
My gridded emission files has 184 columns, 124 rows, 13 layers and 69 variables.
Below is my code:
PROGRAM region_cut
! Purpose:
! To cut emission for specific regions.
!
! Record of the revisons:
! Date Programmer Description of change
! ==== ========== =====================
! 2021/06/11 Peng Zimu Original code
!
USE M3UTILIO
IMPLICIT NONE
! Data dictionary:
REAL, ALLOCATABLE, DIMENSION(:,:,:,:) :: indata, outdata
REAL, ALLOCATABLE, DIMENSION(:,:) :: ratiodata
CHARACTER(16) :: INPUTFILE = 'INPUTFILE'
CHARACTER(16) :: OUTPUTFILE = 'OUTPUTFILE'
CHARACTER(16) :: PGNAME = 'region_cut'
CHARACTER(256) :: XMSG, CUTORPRSV
INTEGER :: i, j, k
INTEGER :: istat, LOGDEV
INTEGER :: gdate, gtime
REAL :: start, finish
! Initialize I/O API
LOGDEV = INIT3()
! Open ratio file
IF (.NOT. OPEN3('ratiofile', FSREAD3, PGNAME)) THEN
XMSG = 'ERROR: Could not open ratio file'
CALL M3EXIT(PGNAME, 0, 0, XMSG, 2)
ENDIF
! Open netCDF input file
IF (.NOT. OPEN3(INPUTFILE, FSREAD3, PGNAME)) THEN
XMSG = 'ERROR: Could not open ' // INPUTFILE // ' for input'
CALL M3EXIT(PGNAME, 0, 0, XMSG, 2)
ENDIF
! Get the file description
IF (.NOT. DESC3(INPUTFILE)) THEN
XMSG = 'ERROR: Could not get ' // INPUTFILE // ' file description'
CALL M3EXIT(PGNAME, 0, 0, XMSG, 2)
ENDIF
! Allocate variables array dimensions
ALLOCATE( indata(NCOLS3D, NROWS3D, NLAYS3D, NVARS3D), STAT = istat)
ALLOCATE( outdata(NCOLS3D, NROWS3D, NLAYS3D, NVARS3D), STAT = istat)
ALLOCATE( ratiodata(NCOLS3D, NROWS3D), STAT = istat)
! Set date and time
gdate = SDATE3D
gtime = STIME3D
! Read in ratio
IF (.NOT. READ3('ratiofile', ALLVAR3, ALLAYS3, gdate, gtime, ratiodata)) THEN
XMSG = 'ERROR: Could not read ratio file'
CALL M3EXIT(PGNAME, 0, 0, XMSG, 2)
ENDIF
! Make sure ratiodata being perserving ratio
CALL GET_ENVIRONMENT_VARIABLE('CUT_RATIO',CUTORPRSV)
IF (CUTORPRSV == 'T') THEN
ratiodata = 1 - ratiodata
ENDIF
! Open Outputfile
IF (.NOT. OPEN3(OUTPUTFILE, FSCREA3, PGNAME)) THEN
XMSG = 'ERROR: Could not open ' // OUTPUTFILE // ' for output'
CALL M3EXIT(PGNAME, 0, 0, XMSG, 2)
ENDIF
! Create output file in loops
DO i = 1, MXREC3D
CALL CPU_TIME(start)
! Read in all vars data for a time
IF (.NOT. READ3(INPUTFILE, ALLVAR3, ALLAYS3, gdate, gtime, indata)) THEN
XMSG = 'ERROR: Could not read ' // INPUTFILE // ' for all vars input'
CALL M3EXIT(PGNAME, 0, 0, XMSG, 2)
ENDIF
CALL CPU_TIME(finish)
WRITE(*, 90) finish - start
90 FORMAT ("Time for READ3 = ",F6.3," seconds.")
CALL CPU_TIME(start)
DO k = 1, NVARS3D
DO j = 1, NLAYS3D
outdata(:,:,j,k) = ratiodata * indata(:,:,j,k)
END DO
END DO
CALL CPU_TIME(finish)
WRITE(*, 100) finish - start
100 FORMAT ("Time for calculating = ",F6.3," seconds.")
CALL CPU_TIME(start)
! Write output file
IF (.NOT. WRITE3(OUTPUTFILE, ALLVAR3, gdate, gtime, outdata)) THEN
XMSG = 'ERROR: Could not write all vars to ' // OUTPUTFILE // ' for output'
CALL M3EXIT(PGNAME, 0, 0, XMSG, 2)
ENDIF
CALL CPU_TIME(finish)
WRITE(*, 110) finish - start
110 FORMAT ("Time for WRITE3 = ",F6.3," seconds.")
CALL NEXTIME(gdate, gtime, 10000)
END DO
CALL CPU_TIME(start)
DEALLOCATE(indata, STAT = istat)
DEALLOCATE(outdata, STAT = istat)
DEALLOCATE(ratiodata, STAT = istat)
CALL CPU_TIME(finish)
WRITE(*, 120) finish - start
120 FORMAT ("Time for DEALLOCATE = ",F6.3," seconds.")
! Normal termination and exit I/O API
XMSG = 'I/O API normal termination'
CALL M3EXIT(PGNAME, 0, 0, XMSG, 0)
END PROGRAM region_cut
Thanks!