diff --git a/model/src/w3gridmd.F90 b/model/src/w3gridmd.F90 index ecf2726a0..8bfc6521a 100644 --- a/model/src/w3gridmd.F90 +++ b/model/src/w3gridmd.F90 @@ -845,7 +845,7 @@ MODULE W3GRIDMD #ifdef W3_ST4 INTEGER :: SWELLFPAR, SDSISO, SDSBRFDF, SINTABLE,& TAUWBUG - REAL :: SDSBCHOICE + REAL :: SDSBCHOICE REAL :: ZWND, ALPHA0, Z0MAX, BETAMAX, SINTHP,& ZALP, Z0RAT, TAUWSHELTER, SWELLF, & SWELLF2,SWELLF3,SWELLF4, SWELLF5, & diff --git a/model/src/w3initmd.F90 b/model/src/w3initmd.F90 index 4badbcb1a..fbefffc84 100644 --- a/model/src/w3initmd.F90 +++ b/model/src/w3initmd.F90 @@ -658,7 +658,6 @@ SUBROUTINE W3INIT ( IMOD, IsMulti, FEXT, MDS, MTRACE, ODAT, FLGRD, FLGR2, FLGD, STOP ENDIF #endif - ! ! 1.c Open files without unpacking MDS ,,, ! @@ -1240,7 +1239,11 @@ SUBROUTINE W3INIT ( IMOD, IsMulti, FEXT, MDS, MTRACE, ODAT, FLGRD, FLGR2, FLGD, ! ! 4.d Preprocessing for point output. ! - IF ( FLOUT(2) ) CALL W3IOPP ( NPT, XPT, YPT, PNAMES, IMOD ) +#ifdef W3_MPI + IF ( FLOUT(2) ) CALL W3IOPP ( NPT, XPT, YPT, PNAMES, IMOD, MPI_COMM_WAVE ) +#else + IF ( FLOUT(2) ) CALL W3IOPP ( NPT, XPT, YPT, PNAMES, IMOD, 1 ) +#endif #ifdef W3_PDLIB CALL DEALLOCATE_PDLIB_GLOBAL(IMOD) #endif diff --git a/model/src/w3iopomd.F90 b/model/src/w3iopomd.F90 index bbdfda34c..fec758638 100644 --- a/model/src/w3iopomd.F90 +++ b/model/src/w3iopomd.F90 @@ -146,6 +146,10 @@ MODULE W3IOPOMD !> Dimension name for the netCDF point output file, for WW3TIME character(*), parameter, private :: DNAME_WW3TIME = 'WW3TIME' + !> Dimension name for the netCDF point weight file, WGHTLEN + !> This is 4 the dimension of weights + character(*), parameter, private :: DNAME_WGHTLEN = 'WGHTLEN' + !> Variable name for the netCDF point output file, for NK. character(*), parameter, private :: VNAME_NK = 'NK' @@ -158,6 +162,12 @@ MODULE W3IOPOMD !> Variable name for the netCDF point output file, for PTNME. character(*), parameter, private :: VNAME_PTNME = 'PTNME' + !> Variable name for the netCDF point weight file, for IPTINT + character(*), parameter, private :: VNAME_IPTINT = 'IPTINT' + + !> Variable name for the netCDF point weight file, for PTIFAC + character(*), parameter, private :: VNAME_PTIFAC = 'PTIFAC' + !> Variable name for the netCDF point output file, for TIME. character(*), parameter, private :: VNAME_TIME = 'TIME' @@ -226,7 +236,7 @@ MODULE W3IOPOMD !> !> @author H. L. Tolman @date 02-Sep-2012 !> - SUBROUTINE W3IOPP ( NPT, XPT, YPT, PNAMES, IMOD ) + SUBROUTINE W3IOPP ( NPT, XPT, YPT, PNAMES, IMOD, MPI_COMM_IOPP ) !/ !/ +-----------------------------------+ !/ | WAVEWATCH III NOAA/NCEP | @@ -329,7 +339,8 @@ SUBROUTINE W3IOPP ( NPT, XPT, YPT, PNAMES, IMOD ) ! 10. Source code : ! !/ ------------------------------------------------------------------- / - USE W3GSRUMD + USE NETCDF + USE W3GSRUMD, ONLY: W3GRMP USE W3GDATMD, ONLY: NTH, NK, NSPEC, NX, NY, X0, Y0, SX, GSU,& RLGTYPE, CLGTYPE, UNGTYPE, GTYPE, FLAGLL, & ICLOSE,ICLOSE_NONE,ICLOSE_SMPL,ICLOSE_TRPL, & @@ -340,21 +351,25 @@ SUBROUTINE W3IOPP ( NPT, XPT, YPT, PNAMES, IMOD ) USE W3GDATMD, ONLY: PoLat, PoLon, FLAGUNR USE W3SERVMD, ONLY: W3LLTOEQ #endif - USE W3ODATMD, ONLY: W3DMO2 + USE W3ODATMD, ONLY: W3DMO2, FNMPRE USE W3ODATMD, ONLY: NDSE, NDST, IAPROC, NAPERR, NAPOUT, SCREEN, & NOPTS, PTLOC, PTNME, GRDID, IPTINT, PTIFAC USE W3SERVMD, ONLY: EXTCDE #ifdef W3_S USE W3SERVMD, ONLY: STRACE #endif - USE W3TRIAMD + USE W3TRIAMD, ONLY: IS_IN_UNGRID + USE W3GDATMD, ONLY: FILEXT ! IMPLICIT NONE +#ifdef W3_MPI + INCLUDE "mpif.h" +#endif !/ !/ ------------------------------------------------------------------- / !/ Parameter list !/ - INTEGER, INTENT(IN) :: NPT, IMOD + INTEGER, INTENT(IN) :: NPT, IMOD, MPI_COMM_IOPP REAL, INTENT(INOUT) :: XPT(NPT), YPT(NPT) CHARACTER(LEN=40),INTENT(IN) :: PNAMES(NPT) !/ @@ -389,6 +404,16 @@ SUBROUTINE W3IOPP ( NPT, XPT, YPT, PNAMES, IMOD ) !! Declare a few temporary variables for rotated grid. JGLi12Jun2012 REAL, ALLOCATABLE :: EquLon(:),EquLat(:),StdLon(:),StdLat(:),AnglPT(:) #endif + ! Variables for NetCDF weights file for points + character(len = 124) :: filename + logical :: pnt_wght_exists, pnt_wght_write + integer :: ncerr, fh + integer :: d_nopts, d_namelen, d_vsize, d_wghtlen + integer :: d_nopts_len, d_vsize_len,d_namelen_len,d_wghtlen_len + integer :: v_ptloc, v_ptnme, v_iptint, v_ptifac +#ifdef W3_MPI + integer :: IERR_MPI +#endif !/ !/ ------------------------------------------------------------------- / !/ @@ -423,86 +448,214 @@ SUBROUTINE W3IOPP ( NPT, XPT, YPT, PNAMES, IMOD ) #endif ! - ! Removed by F.A. 2011/04/04 /T CALL W3GSUP( GSU, NDST ) + !If unstructured grid, check to see if a netcdf point weight file exists: + filename = 'pnt_wght.'//FILEXT(:LEN_TRIM(FILEXT))//'.nc' + IF (GTYPE .NE. UNGTYPE) THEN + !skipping weights file for non-unstructured grids. + !likely could be used after proper testing if initialization time is long + pnt_wght_exists = .FALSE. + pnt_wght_write = .FALSE. + ELSE + !for unstructured grid, use saved weights file if exists: + INQUIRE(FILE=filename, EXIST=pnt_wght_exists) + pnt_wght_write = .NOT. pnt_wght_exists + ENDIF ! - ! Loop over output points + ! Loop over output points if saved weights do not exist ! - DO IPT=1, NPT - ! + IF (.NOT. pnt_wght_exists) THEN + DO IPT=1, NPT + ! #ifdef W3_T - WRITE (NDST,9010) IPT, XPT(IPT), YPT(IPT), PNAMES(IPT) + WRITE (NDST,9010) IPT, XPT(IPT), YPT(IPT), PNAMES(IPT) #endif - ! + ! #ifdef W3_RTD - !! Need to wrap rotated Elon values greater than X0. JGLi12Jun2012 - XPT(IPT) = MOD( EquLon(IPT)+360.0, 360.0 ) - IF( XPT(IPT) .LT. X0 ) XPT(IPT) = XPT(IPT) + 360.0 + !! Need to wrap rotated Elon values greater than X0. JGLi12Jun2012 + XPT(IPT) = MOD( EquLon(IPT)+360.0, 360.0 ) + IF( XPT(IPT) .LT. X0 ) XPT(IPT) = XPT(IPT) + 360.0 #endif - ! - ! Check if point within grid and compute interpolation weights - ! - IF (GTYPE .NE. UNGTYPE) THEN - INGRID = W3GRMP( GSU, XPT(IPT), YPT(IPT), IX, IY, RD ) - ELSE - CALL IS_IN_UNGRID(IMOD, DBLE(XPT(IPT)), DBLE(YPT(IPT)), itout, IX, IY, RD) - INGRID = (ITOUT.GT.0) - END IF - ! - IF ( .NOT.INGRID ) THEN - IF ( IAPROC .EQ. NAPERR ) THEN - IF ( FLAGLL ) THEN - WRITE (NDSE,1000) XPT(IPT), YPT(IPT), PNAMES(IPT) - ELSE - WRITE (NDSE,1001) XPT(IPT), YPT(IPT), PNAMES(IPT) + ! + ! Check if point within grid and compute interpolation weights + ! + IF (GTYPE .NE. UNGTYPE) THEN + INGRID = W3GRMP( GSU, XPT(IPT), YPT(IPT), IX, IY, RD ) + ELSE + CALL IS_IN_UNGRID(IMOD, DBLE(XPT(IPT)), DBLE(YPT(IPT)), itout, IX, IY, RD) + INGRID = (ITOUT.GT.0) + END IF + ! + IF ( .NOT.INGRID ) THEN + IF ( IAPROC .EQ. NAPERR ) THEN + IF ( FLAGLL ) THEN + WRITE (NDSE,1000) XPT(IPT), YPT(IPT), PNAMES(IPT) + ELSE + WRITE (NDSE,1001) XPT(IPT), YPT(IPT), PNAMES(IPT) + END IF END IF + CYCLE END IF - CYCLE - END IF - ! + ! #ifdef W3_T - DO K = 1,4 - WRITE (NDST,9012) IX(K), IY(K), RD(K) - END DO + DO K = 1,4 + WRITE (NDST,9012) IX(K), IY(K), RD(K) + END DO #endif - ! - ! Check if point not on land - ! - IF ( MAPSTA(IY(1),IX(1)) .EQ. 0 .AND. & - MAPSTA(IY(2),IX(2)) .EQ. 0 .AND. & - MAPSTA(IY(3),IX(3)) .EQ. 0 .AND. & - MAPSTA(IY(4),IX(4)) .EQ. 0 ) THEN - IF ( IAPROC .EQ. NAPERR ) THEN - IF ( FLAGLL ) THEN - WRITE (NDSE,1002) XPT(IPT), YPT(IPT), PNAMES(IPT) - ELSE - WRITE (NDSE,1003) XPT(IPT), YPT(IPT), PNAMES(IPT) + ! + ! Check if point not on land + ! + IF ( MAPSTA(IY(1),IX(1)) .EQ. 0 .AND. & + MAPSTA(IY(2),IX(2)) .EQ. 0 .AND. & + MAPSTA(IY(3),IX(3)) .EQ. 0 .AND. & + MAPSTA(IY(4),IX(4)) .EQ. 0 ) THEN + IF ( IAPROC .EQ. NAPERR ) THEN + IF ( FLAGLL ) THEN + WRITE (NDSE,1002) XPT(IPT), YPT(IPT), PNAMES(IPT) + ELSE + WRITE (NDSE,1003) XPT(IPT), YPT(IPT), PNAMES(IPT) + END IF END IF + CYCLE END IF - CYCLE - END IF - ! - ! Store interpolation data - ! - NOPTS = NOPTS + 1 - ! - PTLOC (1,NOPTS) = XPT(IPT) - PTLOC (2,NOPTS) = YPT(IPT) + ! + ! Store interpolation data + ! + NOPTS = NOPTS + 1 + ! + PTLOC (1,NOPTS) = XPT(IPT) + PTLOC (2,NOPTS) = YPT(IPT) #ifdef W3_RTD - !! Store the standard lon/lat in PTLOC for output purpose, assuming - !! they are not used for any inside calculation. JGLi12Jun2012 - PTLOC (1,NOPTS) = StdLon(IPT) - PTLOC (2,NOPTS) = StdLat(IPT) + !! Store the standard lon/lat in PTLOC for output purpose, assuming + !! they are not used for any inside calculation. JGLi12Jun2012 + PTLOC (1,NOPTS) = StdLon(IPT) + PTLOC (2,NOPTS) = StdLat(IPT) #endif - ! - DO K = 1,4 - IPTINT(1,K,NOPTS) = IX(K) - IPTINT(2,K,NOPTS) = IY(K) - PTIFAC(K,NOPTS) = RD(K) - END DO + ! + DO K = 1,4 + IPTINT(1,K,NOPTS) = IX(K) + IPTINT(2,K,NOPTS) = IY(K) + PTIFAC(K,NOPTS) = RD(K) + END DO - PTNME(NOPTS) = PNAMES(IPT) - ! - END DO ! End loop over output points (IPT). + PTNME(NOPTS) = PNAMES(IPT) + ! + END DO ! End loop over output points (IPT). + ELSE + ! Saved weight file exists, read weights from file + IF ( IAPROC .EQ. 1 ) THEN + ! Open the netCDF file. + ncerr = nf90_open(filename, NF90_NOWRITE, fh) + if (nf90_err(ncerr) .ne. 0) return + + ! Read the dimension information for NOPTS. + ncerr = nf90_inq_dimid(fh, DNAME_NOPTS, d_nopts) + if (nf90_err(ncerr) .ne. 0) return + ncerr = nf90_inquire_dimension(fh, d_nopts, len = d_nopts_len) + if (nf90_err(ncerr) .ne. 0) return + NOPTS=d_nopts_len + + ! Read the dimension information for VSIZE. + ncerr = nf90_inq_dimid(fh, DNAME_VSIZE, d_vsize) + if (nf90_err(ncerr) .ne. 0) return + ncerr = nf90_inquire_dimension(fh, d_vsize, len = d_vsize_len) + if (nf90_err(ncerr) .ne. 0) return + + ! Read the dimension information for NAMELEN. + ncerr = nf90_inq_dimid(fh, DNAME_NAMELEN, d_namelen) + if (nf90_err(ncerr) .ne. 0) return + ncerr = nf90_inquire_dimension(fh, d_namelen, len = d_namelen_len) + if (nf90_err(ncerr) .ne. 0) return + + ! Read the dimension information for WGHTLEN. + ncerr = nf90_inq_dimid(fh, DNAME_WGHTLEN, d_wghtlen) + if (nf90_err(ncerr) .ne. 0) return + ncerr = nf90_inquire_dimension(fh, d_wghtlen, len = d_wghtlen_len) + if (nf90_err(ncerr) .ne. 0) return + + ! Read vars + ncerr = nf90_inq_varid(fh, VNAME_PTLOC, v_ptloc) + if (nf90_err(ncerr) .ne. 0) return + ncerr = nf90_get_var(fh, v_ptloc, PTLOC, start = (/ 1, 1/), & + count = (/ d_vsize_len, d_nopts_len /)) + if (nf90_err(ncerr) .ne. 0) return + + ncerr = nf90_inq_varid(fh, VNAME_PTNME, v_ptnme) + if (nf90_err(ncerr) .ne. 0) return + ncerr = nf90_get_var(fh, v_ptnme, PTNME, start = (/ 1, 1/), & + count = (/ d_namelen_len, d_nopts_len /)) + if (nf90_err(ncerr) .ne. 0) return + + ncerr = nf90_inq_varid(fh, VNAME_IPTINT, v_iptint) + if (nf90_err(ncerr) .ne. 0) return + ncerr = nf90_get_var(fh, v_iptint, IPTINT, start = (/ 1, 1/), & + count = (/ d_vsize_len, d_wghtlen_len, d_nopts_len /)) + if (nf90_err(ncerr) .ne. 0) return + + ncerr = nf90_inq_varid(fh, VNAME_PTIFAC, v_ptifac) + if (nf90_err(ncerr) .ne. 0) return + ncerr = nf90_get_var(fh, v_ptifac, PTIFAC, start = (/ 1, 1/), & + count = (/ d_wghtlen_len, d_nopts_len /)) + if (nf90_err(ncerr) .ne. 0) return + END IF +#ifdef W3_MPI + ! Broadcast weight info to all MPI tasks: + CALL MPI_BCAST(NOPTS,1,MPI_INTEGER,IAPROC-1,MPI_COMM_IOPP,IERR_MPI) + CALL MPI_BCAST(PTNME,40*NPT,MPI_CHARACTER,IAPROC-1,MPI_COMM_IOPP,IERR_MPI) + CALL MPI_BCAST(PTLOC,2*NPT,MPI_REAL,0,MPI_COMM_IOPP,IERR_MPI) + CALL MPI_BCAST(IPTINT,2*4*NPT,MPI_REAL,0,MPI_COMM_IOPP,IERR_MPI) + CALL MPI_BCAST(PTIFAC,4*NPT,MPI_REAL,0,MPI_COMM_IOPP,IERR_MPI) + CALL MPI_Barrier(MPI_COMM_IOPP,IERR_MPI) +#endif + ENDIF !end if point weight file exists + + !Create a weights file if there are output points: + IF ( pnt_wght_write .AND. (NOPTS > 0) ) THEN + IF ( IAPROC .EQ. 1 ) THEN + ! Create the netCDF file. + ncerr = nf90_create(filename, NF90_NETCDF4, fh) + if (nf90_err(ncerr) .ne. 0) return + + ! Define dimensions. + ncerr = nf90_def_dim(fh, DNAME_NOPTS, NOPTS, d_nopts) + if (nf90_err(ncerr) .ne. 0) return + ncerr = nf90_def_dim(fh, DNAME_NAMELEN, 40, d_namelen) + if (nf90_err(ncerr) .ne. 0) return + ncerr = nf90_def_dim(fh, DNAME_VSIZE, 2, d_vsize) + if (nf90_err(ncerr) .ne. 0) return + ncerr = nf90_def_dim(fh, DNAME_WGHTLEN, 4, d_wghtlen) + if (nf90_err(ncerr) .ne. 0) return + + ! Define vars with nopts as a dimension. Point location and name + ncerr = nf90_def_var(fh, VNAME_PTLOC, NF90_FLOAT, (/d_vsize, d_nopts/), v_ptloc) + if (nf90_err(ncerr) .ne. 0) return + ncerr = nf90_def_var(fh, VNAME_PTNME, NF90_CHAR, (/d_namelen, d_nopts/), v_ptnme) + if (nf90_err(ncerr) .ne. 0) return + ncerr = nf90_def_var(fh, VNAME_IPTINT, NF90_FLOAT, (/d_vsize, d_wghtlen, d_nopts/), v_iptint) + if (nf90_err(ncerr) .ne. 0) return + ncerr = nf90_def_var(fh, VNAME_PTIFAC, NF90_FLOAT, (/d_wghtlen, d_nopts/), v_ptifac) + if (nf90_err(ncerr) .ne. 0) return + + ! End of all variable definitions + ncerr = nf90_enddef(fh) + if (nf90_err(ncerr) .ne. 0) return + + !write variables to file + ncerr = nf90_put_var(fh, v_ptloc, PTLOC(:,1:NOPTS)) + if (nf90_err(ncerr) .ne. 0) return + ncerr = nf90_put_var(fh, v_ptnme, PTNME(1:NOPTS)) + if (nf90_err(ncerr) .ne. 0) return + + ncerr = nf90_put_var(fh, v_iptint, IPTINT(:,:,1:NOPTS)) + if (nf90_err(ncerr) .ne. 0) return + ncerr = nf90_put_var(fh, v_ptifac, PTIFAC(:,1:NOPTS)) + if (nf90_err(ncerr) .ne. 0) return + + ! Close the file. + ncerr = nf90_close(fh) + if (nf90_err(ncerr) .ne. 0) return + + END IF + ENDIF ! #ifdef W3_RTD DEALLOCATE( EquLon, EquLat, StdLon, StdLat, AnglPT ) @@ -1115,7 +1268,6 @@ SUBROUTINE W3IOPE ( A ) !/ END SUBROUTINE W3IOPE -#ifdef W3_BIN2NC !> Handle netCDF return code. !> !> @param errcode NetCDF error code. 0 for no error. @@ -1137,6 +1289,7 @@ integer function nf90_err_check(errcode, ILINE) return endif end function nf90_err_check +#ifdef W3_BIN2NC !> Read point output in netCDF format. !> diff --git a/model/src/w3triamd.F90 b/model/src/w3triamd.F90 index b7fb6aaec..f2118ec24 100644 --- a/model/src/w3triamd.F90 +++ b/model/src/w3triamd.F90 @@ -1697,7 +1697,7 @@ SUBROUTINE IS_IN_UNGRID(IMOD, XTIN, YTIN, ITOUT, IS, JS, RW) ! 10. Source code : ! !/ ------------------------------------------------------------------- / - USE W3GDATMD + USE W3GDATMD, ONLY: GRIDS USE W3SERVMD, ONLY: EXTCDE #ifdef W3_S USE W3SERVMD, ONLY: STRACE diff --git a/model/src/wmiopomd.F90 b/model/src/wmiopomd.F90 index bce460483..1737e04bb 100644 --- a/model/src/wmiopomd.F90 +++ b/model/src/wmiopomd.F90 @@ -500,7 +500,7 @@ SUBROUTINE WMIOPP ( NPT, XPT, YPT, PNAMES ) #endif ! #ifdef W3_SHRD - CALL W3IOPP ( MDATAS(J)%NRUPTS, XP, YP, PN, J ) + CALL W3IOPP ( MDATAS(J)%NRUPTS, XP, YP, PN, J, 1) #endif ! ! 3.d.2 Distributed memory version @@ -535,7 +535,7 @@ SUBROUTINE WMIOPP ( NPT, XPT, YPT, PNAMES ) #endif ! #ifdef W3_MPI - CALL W3IOPP ( MDATAS(J)%NRUPTS, XP, YP, PN, J ) + CALL W3IOPP ( MDATAS(J)%NRUPTS, XP, YP, PN, J, MPI_COMM_MWAVE) #endif ! #ifdef W3_MPI diff --git a/regtests/bin/run_cmake_test b/regtests/bin/run_cmake_test index 07ade5a8b..d7e05497b 100755 --- a/regtests/bin/run_cmake_test +++ b/regtests/bin/run_cmake_test @@ -1358,6 +1358,16 @@ fi done fi +# copy pnt weight files from input to work directory + pntwghtfile=`\ls $path_i/pnt_wght.*.nc 2>/dev/null` + if [ ! -z "$pntwghtfile" ]; then + for pntwghtnc in $pntwghtfile + do + cp $pntwghtnc . + echo "copying $pntwghtnc to $path_w" + done + fi + if [ $multi -ge 1 ] then prog=ww3_multi