WAVEWATCH III  beta 0.0.1
wmgridmd Module Reference

Routines to determine and process grid dependencies in the multi-grid wave model. More...

Functions/Subroutines

subroutine wmglow (FLRBPI)
 Determine relations to lower ranked grids for each grid. More...
 
subroutine wmghgh
 Determine relation to higher ranked grids for each grid. More...
 
subroutine wmgeql
 Determine relations to same ranked grids for each grid. More...
 
subroutine wmrspc
 Generate map with flags for need of spectral grid conversion between models. More...
 
subroutine wmsmceql
 Determine relations to same ranked SMC grids for each grid. More...
 

Detailed Description

Routines to determine and process grid dependencies in the multi-grid wave model.

Author
H. L. Tolman
W. E. Rogers
Date
10-Dec-2014

Function/Subroutine Documentation

◆ wmgeql()

subroutine wmgridmd::wmgeql

Determine relations to same ranked grids for each grid.

Cross mapping of grid points, determine boundary distance data and interpolation weights.

Author
H. L. Tolman
Date
10-Dec-2014

Definition at line 3709 of file wmgridmd.F90.

3709  !/
3710  !/ +-----------------------------------+
3711  !/ | WAVEWATCH III NOAA/NCEP |
3712  !/ | H. L. Tolman |
3713  !/ | FORTRAN 90 |
3714  !/ | Last update : 10-Dec-2014 !
3715  !/ +-----------------------------------+
3716  !/
3717  !/ 24-Apr-2006 : Origination. ( version 3.09 )
3718  !/ 23-Dec-2006 : Adding group test. ( version 3.10 )
3719  !/ 28-Dec-2006 : Simplify NIT for partial comm. ( version 3.10 )
3720  !/ 22-Jan-2007 : Add saving og NAVMAX. ( version 3.10 )
3721  !/ 02-Feb-2007 : Setting FLAGST for replaced points. ( version 3.10 )
3722  !/ 15-Feb-2007 : Tweaking MAPODI algorithm in WMGEQL.( version 3.10 )
3723  !/ 11-Apr-2008 : Big fix active edges (MAPSTA=2) ( version 3.13 )
3724  !/ 14-Apr-2008 : Big fix for global grids. ( version 3.13 )
3725  !/ 20-May-2009 : Linking FLAGST and FLGHG1. ( version 3.14 )
3726  !/ 30-Oct-2009 : Implement run-time grid selection. ( version 3.14 )
3727  !/ (W. E. Rogers & T. J. Campbell, NRL)
3728  !/ 06-Dec-2010 : Change from GLOBAL (logical) to ICLOSE (integer) to
3729  !/ specify index closure for a grid. ( version 3.14 )
3730  !/ (T. J. Campbell, NRL)
3731  !/ 23-Dec-2010 : Fix HPFAC and HQFAC by including the COS(YGRD)
3732  !/ factor with DXDP and DXDQ terms. ( version 3.14 )
3733  !/ (T. J. Campbell, NRL)
3734  !/ 05-Aug-2013 : Change PR2/3 to UQ/UNO in distances.( version 4.12 )
3735  !/ 10-Dec-2014 : Add checks for allocate status ( version 5.04 )
3736  !/ 28-Oct-2020 : Add SMCTYPE for SMC sub-grid. JGLi ( version 6.xx )
3737  !/
3738  ! 1. Purpose :
3739  !
3740  ! Determine relations to same ranked grids for each grid.
3741  !
3742  ! 2. Method :
3743  !
3744  ! Cross mapping of grid points, determine boundary distance data
3745  ! and interpolation weights.
3746  !
3747  ! 3. Parameters :
3748  !
3749  ! 4. Subroutines used :
3750  !
3751  ! Name Type Module Description
3752  ! ----------------------------------------------------------------
3753  ! W3SETG, W3SETO, WMSETM
3754  ! Subr. W3GDATMD Manage data structures.
3755  ! STRACE Subr. W3SERVMD Subroutine tracing.
3756  ! EXTCDE Subr. Id. Program abort.
3757  ! ----------------------------------------------------------------
3758  !
3759  ! 5. Called by :
3760  !
3761  ! 6. Error messages :
3762  !
3763  ! 7. Remarks :
3764  !
3765  ! - In looking for compatable boundary points in overlapping grids
3766  ! two assumptions hav been made.
3767  ! a) No active boundary points exist in global grids.
3768  ! b) For a lower resolution grid an expanded sewarch area is
3769  ! required for corresponding active grid points. By limiting
3770  ! the resolution ratio to 2, only one extra grid point needs
3771  ! to be considered (JXL2 versus JXL etc.).
3772  !
3773  ! 8. Structure :
3774  !
3775  ! 9. Switches :
3776  !
3777  ! !/PRn Propagation scheme.
3778  !
3779  ! !/O12 Removed boundary points output (central).
3780  ! !/O13 Removed boundary points output (edge).
3781 
3782  ! !/S Enable subroutine tracing.
3783  ! !/T Enable test output.
3784  ! !/T5 Detailed test output 'receiving'.
3785  ! !/T6 Detailed test output 'sending'.
3786  ! !/T7 Detailed test output all.
3787  !
3788  ! !/MPI Distribbuted memory management.
3789  !
3790  ! 10. Source code :
3791  !
3792  !/ ------------------------------------------------------------------- /
3793  !
3794  USE constants
3795  USE w3gdatmd
3796  USE w3odatmd
3797  USE w3adatmd
3798  USE wmmdatmd
3799  !
3800  USE w3servmd, ONLY: extcde
3801  ! USE W3PARALL, ONLY: INIT_GET_JSEA_ISPROC_GLOB
3802 #ifdef W3_S
3803  USE w3servmd, ONLY: strace
3804 #endif
3805  !
3806  IMPLICIT NONE
3807  !/
3808  !/ ------------------------------------------------------------------- /
3809  !/ Parameter list
3810  !/
3811  !/ ------------------------------------------------------------------- /
3812  !/ Local parameters
3813  !/
3814  INTEGER :: I, J, IX, IXL, IXH, IY, IYL, IYH, &
3815  JX, JXL, JXH, JXL2, JXH2, &
3816  JY, JYL, JYH, JYL2, JYH2, &
3817  NR, NT, NA, NTL, JJ, NIT, NG, NOUT, &
3818  ISEA, JSEA, ISPROC, ITAG, TGRP, &
3819  EXTRA, IP, NP
3820 #ifdef W3_T7
3821  INTEGER :: IA
3822 #endif
3823 #ifdef W3_S
3824  INTEGER, SAVE :: IENT = 0
3825 #endif
3826  INTEGER, ALLOCATABLE :: MAP3D(:,:,:), NREC(:), NSND(:), &
3827  NTPP(:), MAPOUT(:,:)
3828  REAL :: FACTOR, XSL, XSH, YSL, YSH, XA, YA, &
3829  XR, YR, RX(2), RY(2), STX, STY, &
3830  STXY, NEWVAL, WGTH
3831  REAL, PARAMETER :: TODO = -9.99e25
3832  REAL, PARAMETER :: ODIMAX = 25.
3833  REAL, PARAMETER :: FACMAX = 2.001
3834  REAL, ALLOCATABLE :: WGT3D(:,:,:)
3835  LOGICAL :: CHANGE, XEXPND, YEXPND
3836  LOGICAL, ALLOCATABLE :: SHRANK(:,:), DOGRID(:), &
3837  MASKA(:,:), MASKI(:,:)
3838 #ifdef W3_T5
3839  CHARACTER(LEN=18), ALLOCATABLE :: TSTR(:)
3840  CHARACTER(LEN=18) :: DSTR
3841 #endif
3842  !
3843  TYPE store
3844  INTEGER :: NTOT, NFIN
3845  INTEGER, POINTER :: IX(:), IY(:), NAV(:), ISS(:,:), &
3846  JSS(:,:), IPS(:,:), ITG(:,:)
3847  REAL, POINTER :: AWG(:,:)
3848  LOGICAL, POINTER :: FLA(:)
3849  LOGICAL :: INIT
3850  END TYPE store
3851  !
3852  TYPE(STORE), ALLOCATABLE :: STORES(:,:)
3853  !/
3854 #ifdef W3_S
3855  CALL strace (ient, 'WMGEQL')
3856 #endif
3857  !
3858  ! -------------------------------------------------------------------- /
3859  ! 0. Initializations
3860  !
3861 
3862  ALLOCATE ( shrank(nrgrd,nrgrd), stores(nrgrd,nrgrd), &
3863  dogrid(nrgrd), stat=istat )
3864  check_alloc_status( istat )
3865  !
3866  shrank = .false.
3867  !
3868  DO i=1, nrgrd
3869 
3870  DO j=1, nrgrd
3871  stores(i,j)%INIT = .false.
3872  stores(i,j)%NTOT = 0
3873  stores(i,j)%NFIN = 0
3874  END DO
3875  END DO
3876  !
3877  IF ( flagll ) THEN
3878  factor = radius * dera
3879  !notes: was FACTOR = RADIUS / 360. (I don't know where this came from....
3880  ! ...maybe it was supposed to be CIRCUMFERENCE/360)
3881  ELSE
3882  factor = 1.
3883  END IF
3884  itag = 0
3885  !
3886 #ifdef W3_SMC
3887  !! Check GTYPE for all grids.
3888  IF( improc.EQ.nmperr ) WRITE (mdse,*) " WMGEQL GTYPE:", &
3889  ( grids(i)%GTYPE, i=1, nrgrd )
3890 #endif
3891  !
3892  ! -------------------------------------------------------------------- /
3893  ! 1. Grid point relations and temp data storage
3894  ! 1.a Outer loop over all grids
3895  !
3896 #ifdef W3_T
3897  WRITE (mdst,9010)
3898 #endif
3899  !
3900  DO i=1, nrgrd
3901 
3902 #ifdef W3_T
3903  WRITE (mdst,9011) i, grank(i)
3904 #endif
3905  !
3906  ! 1.b Find grids with same rank
3907  !
3908  nr = 0
3909  !
3910 #ifdef W3_SMC
3911  !! SMC grids use WMSMCEQL for equal ranked grids. JGLi23Mar2021
3912  IF( grids(i)%GTYPE .EQ. smctype ) cycle
3913 #endif
3914  !
3915  DO j=1, nrgrd
3916 
3917  IF ( grank(i).NE.grank(j) .OR. i.EQ.j ) cycle
3918  !
3919 #ifdef W3_SMC
3920  IF( grids(j)%GTYPE .EQ. smctype ) cycle
3921 #endif
3922  !
3923 #ifdef W3_T
3924  WRITE (mdst,9012) j
3925 #endif
3926  shrank(i,j) = .true.
3927  nr = nr + 1
3928  END DO
3929  !
3930  CALL w3setg ( i, mdse, mdst )
3931  !
3932  dogrid(i) = nr .GT. 0
3933 
3934  !..notes: we will reach this point even if there are no equal rank grids
3935 
3936 #ifdef W3_T
3937  IF ( nr .EQ. 0 ) WRITE (mdst,9013) 'NO GRIDS WITH SAME RANK'
3938 #endif
3939  IF ( nr .EQ. 0 ) cycle
3940 
3941  !..notes: we will not reach this point if are no equal rank grids. that makes it a good place to check against grid type
3942 
3943  IF ( iclose .EQ. iclose_trpl ) THEN
3944  IF ( improc.EQ.nmperr ) WRITE(mdse,*)'SUBROUTINE WMGEQL IS'// &
3945  ' NOT YET ADAPTED FOR TRIPOLE GRIDS. STOPPING NOW.'
3946  CALL extcde ( 1 )
3947  END IF
3948 
3949  ! Unresolved bug: this triggers even for 2 irregular grids that are not overlapping!
3950  ! We should only be checking for cases of 2 irregular grids of equal rank that
3951  ! are overlapping. Unfortunately, at this point in the routine, we don't know
3952  ! whether they are overlapping...requires more code to do this, since all code
3953  ! in this routine is for regular grids. Fortunately, there is really no
3954  ! disadvantage to making the two irregular grids to be different rank using
3955  ! ww3_multi.inp
3956 
3957  IF ( gtype .EQ. ungtype ) THEN
3958  IF ( improc.EQ.nmperr )WRITE (mdse,'(/3A)') ' *** ERROR ', &
3959  'WMGEQL: UNSTRUCTURED GRID SUPPORT NOT YET ', &
3960  'IMPLEMENTED ***'
3961  CALL extcde ( 999 )
3962  END IF
3963  IF ( gtype .EQ. clgtype ) THEN
3964  IF ( improc.EQ.nmperr )WRITE (mdse,'(/3A)') ' *** ERROR ', &
3965  'WMGEQL: CURVILINEAR GRID SUPPORT NOT IMPLEMENTED ', &
3966  'FOR NRGRD > 1 ***'
3967  CALL extcde ( 999 )
3968  END IF
3969 
3970  !
3971  ! 1.c Fill TMPMAP with raw relational data
3972  !
3973  ! 1.c.1 Loop over grids, select same rank
3974  !
3975  DO j=1, nrgrd
3976 
3977  IF ( .NOT. shrank(i,j) ) cycle
3978  !
3979  ! 1.c.2 Determine shared area
3980  ! Don't even try for X in LLG
3981  !
3982 
3983  ! Note: Check is against FLAGLL. Would it be more appropriate
3984  ! to check against ICLOSE?
3985  IF ( flagll ) THEN
3986  ixl = 1
3987  ixh = nx
3988  ELSE
3989  xsl = ( grids(j)%X0 - x0 ) / sx - 0.01
3990  xsh = ( grids(j)%X0 + grids(j)%SX*(grids(j)%NX-1) &
3991  - x0 ) / sx + 0.01
3992  ixl = max( 1+nint(xsl) , 1 )
3993  ixh = min( 1+nint(xsh) , nx )
3994  END IF
3995  !
3996  ysl = ( grids(j)%Y0 - y0 ) / sy - 0.01
3997  ysh = ( grids(j)%Y0 + grids(j)%SY*(grids(j)%NY-1) &
3998  - y0 ) / sy + 0.01
3999  iyl = max( 1+nint(ysl) , 1 )
4000  iyh = min( 1+nint(ysh) , ny )
4001  !
4002  nt = (1+ixh-ixl) * (1+iyh-iyl)
4003  IF ( nt .EQ. 0 ) cycle
4004  !
4005  stores(i,j)%INIT = .true.
4006  ALLOCATE ( stores(i,j)%IX(nt) , stores(i,j)%IY(nt) , &
4007  stores(i,j)%NAV(nt) , stores(i,j)%FLA(nt) , &
4008  stores(i,j)%ISS(nt,4), stores(i,j)%JSS(nt,4), &
4009  stores(i,j)%IPS(nt,4), stores(i,j)%ITG(nt,4), &
4010  stores(i,j)%AWG(nt,4), stat=istat )
4011  check_alloc_status( istat )
4012  stores(i,j)%NAV = 0
4013  stores(i,j)%FLA = .false.
4014  stores(i,j)%ISS = 0
4015  stores(i,j)%JSS = 0
4016  stores(i,j)%IPS = 0
4017  stores(i,j)%ITG = 0
4018  stores(i,j)%AWG = 0.
4019  !
4020  ! 1.c.3 Loops over shared area
4021  !
4022  nt = 0
4023  !
4024  xexpnd = sx .GT. grids(j)%SX
4025  yexpnd = sy .GT. grids(j)%SY
4026  !
4027  DO ix=ixl, ixh
4028  xa = x0 + real(ix-1)*sx
4029  IF ( flagll ) THEN
4030  xr = 1. + mod(1080. + xa - grids(j)%X0 , 360. ) &
4031  / grids(j)%SX
4032  ELSE
4033  xr = 1. + (xa-grids(j)%X0) / grids(j)%SX
4034  END IF
4035  jxl = int(xr)
4036  jxh = jxl + 1
4037  rx(1) = 1. - mod(xr,1.)
4038  IF ( rx(1).GT.0.99 .OR. jxh.EQ.grids(j)%NX+1 ) THEN
4039  jxh = jxl
4040  rx(1) = 1.
4041  END IF
4042  IF ( rx(1).LT.0.01 .OR. jxl.EQ.0 ) THEN
4043  jxl = jxh
4044  rx(1) = 1.
4045  END IF
4046  rx(2) = 1. - rx(1)
4047  !
4048  IF ( jxl.LT.1 .OR. jxh.GT.grids(j)%NX ) cycle
4049  !
4050  IF ( xexpnd ) THEN
4051  jxl2 = max( 1 , jxl-1 )
4052  jxh2 = min( grids(j)%NX , jxh+1 )
4053  ELSE
4054  jxl2 = jxl
4055  jxh2 = jxh
4056  END IF
4057  !
4058  DO iy=iyl, iyh
4059  ya = y0 + real(iy-1)*sy
4060  yr = 1. + (ya-grids(j)%Y0) / grids(j)%SY
4061  jyl = int(yr)
4062  jyh = jyl + 1
4063  ry(1) = 1. - mod(yr,1.)
4064  IF ( ry(1).GT.0.99 .OR. jyh.EQ.grids(j)%NY+1 ) THEN
4065  jyh = jyl
4066  ry(1) = 1.
4067  END IF
4068  IF ( ry(1).LT.0.01 .OR. jyl.EQ.0 ) THEN
4069  jyl = jyh
4070  ry(1) = 1.
4071  END IF
4072  IF ( ry(1) .GT. 0.99 ) jyh = jyl
4073  ry(2) = 1. - ry(1)
4074  !
4075  IF ( jyl.LT.1 .OR. jyh.GT.grids(j)%NY ) cycle
4076  !
4077  IF ( yexpnd ) THEN
4078  jyl2 = max( 1 , jyl-1 )
4079  jyh2 = min( grids(j)%NY , jyh+1 )
4080  ELSE
4081  jyl2 = jyl
4082  jyh2 = jyh
4083  END IF
4084  !
4085  ! 1.c.4 Temp storage of raw data
4086  !
4087  nt = nt + 1
4088  na = 0
4089 #ifdef W3_SHRD
4090  isproc = 1
4091 #endif
4092  stores(i,j)%IX(nt) = ix
4093  stores(i,j)%IY(nt) = iy
4094  !
4095  DO jx = jxl, jxh
4096  DO jy = jyl, jyh
4097  IF ( grids(j)%MAPSTA(jy,jx) .NE. 0 ) THEN
4098  na = na + 1
4099  itag = itag + 1
4100  wgth = rx(1+jx-jxl) * ry(1+jy-jyl)
4101  isea = grids(j)%MAPFS(jy,jx)
4102  IF ( isea .EQ. 0 ) THEN
4103  jsea = 0
4104 #ifdef W3_MPI
4105  isproc = 1
4106 #endif
4107  ELSE
4108  CALL init_get_jsea_isproc_glob(isea, j, jsea, isproc)
4109  END IF
4110  stores(i,j)%AWG(nt,na) = wgth
4111  stores(i,j)%ISS(nt,na) = isea
4112  stores(i,j)%JSS(nt,na) = jsea
4113  stores(i,j)%IPS(nt,na) = isproc
4114  stores(i,j)%ITG(nt,na) = itag
4115  END IF
4116  END DO
4117  END DO
4118  !
4119  DO jx = jxl2, jxh2
4120  DO jy = jyl2, jyh2
4121  IF ( abs(grids(j)%MAPSTA(jy,jx)) .EQ. 2 ) &
4122  stores(i,j)%FLA(nt) = .true.
4123  END DO
4124  END DO
4125  !
4126  wgth = sum( stores(i,j)%AWG(nt,1:na) )
4127  IF ( wgth .LT. 0.499 ) THEN
4128  na = 0
4129  ELSE
4130  stores(i,j)%AWG(nt,:) = stores(i,j)%AWG(nt,:) / wgth
4131  END IF
4132  !
4133  stores(i,j)%NAV(nt) = na
4134  !
4135  ! ... End of loops in 1.c
4136  !
4137  END DO
4138  END DO
4139  !
4140  stores(i,j)%NTOT = nt
4141  !
4142  END DO
4143  !
4144  ! -------------------------------------------------------------------- /
4145  ! 2. Generate open edge distance maps
4146  ! 2.a Base map based on MAPSTA only, time step not included.
4147  !
4148 #ifdef W3_T
4149  WRITE (mdst,9020) i
4150 #endif
4151  !
4152  ALLOCATE ( mdatas(i)%MAPODI(ny,nx), stat=istat )
4153  check_alloc_status( istat )
4154  mapodi => mdatas(i)%MAPODI
4155  mapodi = 0.
4156  !
4157  DO ix=1, nx
4158  DO iy=1, ny
4159  IF ( abs(mapsta(iy,ix)) .EQ. 1 ) THEN
4160  mapodi(iy,ix) = todo
4161  ELSE IF ( abs(mapsta(iy,ix)) .EQ. 2 ) THEN
4162  mapodi(iy,ix) = -2. / sig(1) * dtmax
4163  ELSE
4164  mapodi(iy,ix) = -1. / sig(1) * dtmax
4165  END IF
4166  END DO
4167  END DO
4168  !
4169  ! 2.b Add in cross-grid information from STORES
4170  !
4171  ALLOCATE ( maska(ny,nx), stat=istat )
4172  check_alloc_status( istat )
4173  maska = .false.
4174  !
4175  DO j=1, nrgrd
4176  IF ( .NOT. shrank(i,j) ) cycle
4177  DO jj=1, stores(i,j)%NTOT
4178  ix = stores(i,j)%IX(jj)
4179  iy = stores(i,j)%IY(jj)
4180  IF ( ix.EQ.1 .OR. ix.EQ.nx .OR. iy.EQ.1 .OR. iy.EQ.ny ) THEN
4181  maska(iy,ix) = stores(i,j)%FLA(jj) .OR. &
4182  stores(i,j)%NAV(jj).EQ.0
4183  IF ( abs(mapsta(iy,ix)).EQ.2 .AND. &
4184  .NOT.stores(i,j)%FLA(jj) .AND. &
4185  stores(i,j)%NAV(jj).GT.0 ) THEN
4186  mapodi(iy,ix) = 0.
4187 #ifdef W3_O13
4188  IF ( improc.EQ.nmperr ) &
4189  WRITE (mdse,1020) i, ix, 1
4190 #endif
4191  END IF
4192  ELSE
4193  maska(iy,ix) = stores(i,j)%FLA(jj)
4194  END IF
4195  IF ( mapsta(iy,ix).EQ.0 .AND. mapst2(iy,ix) .EQ.1 .AND. &
4196  stores(i,j)%NAV(jj).GT.0 ) mapodi(iy,ix) = 0.
4197  END DO
4198  END DO
4199  !
4200  ! 2.c Remove incompatable boundary points
4201  !
4202  ALLOCATE ( maski(ny,nx), stat=istat )
4203  check_alloc_status( istat )
4204  maski = .false.
4205  !
4206  DO ix=2, nx-1
4207  DO iy=2, ny-1
4208  IF ( abs(mapsta(iy,ix)) .EQ. 2 .AND. &
4209  .NOT. maska(iy,ix) .AND. ( &
4210  mapodi(iy-1,ix ) .GE. 0. .OR. &
4211  mapodi(iy+1,ix ) .GE. 0. .OR. &
4212  mapodi(iy ,ix-1) .GE. 0. .OR. &
4213  mapodi(iy ,ix+1) .GE. 0. ) ) THEN
4214  maski(iy,ix) = .true.
4215 #ifdef W3_O12
4216  IF ( improc.EQ.nmperr ) WRITE (mdse,1020) i, ix, iy
4217 #endif
4218  END IF
4219  END DO
4220  END DO
4221  !
4222  DEALLOCATE ( maska, stat=istat )
4223  check_dealloc_status( istat )
4224  !
4225  DO ix=1, nx
4226  DO iy=1, ny
4227  IF ( maski(iy,ix) ) mapodi(iy,ix) = 0.
4228  END DO
4229  END DO
4230  !
4231  ! 2.d Mask out influenced edge
4232  !
4233 #ifdef W3_PR0
4234  nit = 0
4235 #endif
4236 #ifdef W3_PR1
4237  nit = ( 1 + int(dtmax/dtcfl-0.001) ) * 1
4238 #endif
4239 #ifdef W3_UQ
4240  nit = ( 1 + int(dtmax/dtcfl-0.001) ) * 3
4241 #endif
4242 #ifdef W3_UNO
4243  nit = ( 1 + int(dtmax/dtcfl-0.001) ) * 3
4244 #endif
4245  !
4246  IF ( iclose.NE.iclose_none ) THEN
4247  ixl = 1
4248  ixh = nx
4249  ELSE
4250  ixl = 2
4251  ixh = nx - 1
4252  END IF
4253  !
4254  DO j=1, nit
4255  !
4256  maski = .false.
4257  !
4258  DO ix=ixl, ixh
4259  IF ( ix .EQ. 1 ) THEN
4260  jxl = nx
4261  jxh = 2
4262  ELSE IF ( ix .EQ. nx ) THEN
4263  jxl = nx - 1
4264  jxh = 1
4265  ELSE
4266  jxl = ix - 1
4267  jxh = ix + 1
4268  END IF
4269  !
4270  DO iy=2, ny-1
4271  IF ( mapodi(iy,ix) .EQ. todo .AND. ( &
4272  mapodi(iy+1,ix ) .GE. 0. .OR. &
4273  mapodi(iy ,jxl) .GE. 0. .OR. &
4274  mapodi(iy-1,ix ) .GE. 0. .OR. &
4275  mapodi(iy ,jxh) .GE. 0. .OR. &
4276  ( mapodi(iy+1,jxh) .GE. 0. .AND. .NOT. &
4277  ( mapsta(iy+1,ix ) .NE. 1 .AND. &
4278  mapsta(iy ,jxh) .NE. 1 ) ) .OR. &
4279  ( mapodi(iy+1,jxl) .GE. 0. .AND. .NOT. &
4280  ( mapsta(iy+1,ix ) .NE. 1 .AND. &
4281  mapsta(iy ,jxl) .NE. 1 ) ) .OR. &
4282  ( mapodi(iy-1,jxl) .GE. 0. .AND. .NOT. &
4283  ( mapsta(iy-1,ix ) .NE. 1 .AND. &
4284  mapsta(iy ,jxl) .NE. 1 ) ) .OR. &
4285  ( mapodi(iy-1,jxh) .GE. 0. .AND. .NOT. &
4286  ( mapsta(iy-1,ix ) .NE. 1 .AND. &
4287  mapsta(iy ,jxh) .NE. 1 ) ) ) ) &
4288  maski(iy,ix) = .true.
4289  END DO
4290  !
4291  END DO
4292  !
4293  DO ix=ixl, ixh
4294  DO iy=2, ny-1
4295  IF ( maski(iy,ix) ) mapodi(iy,ix) = 0.
4296  END DO
4297  END DO
4298  !
4299  END DO
4300  !
4301  ! 2.e Compute distances
4302  !
4303  DO
4304  maski = .false.
4305  !
4306  DO ix=ixl, ixh
4307  IF ( ix .EQ. 1 ) THEN
4308  jxl = nx
4309  jxh = 2
4310  ELSE IF ( ix .EQ. nx ) THEN
4311  jxl = nx - 1
4312  jxh = 1
4313  ELSE
4314  jxl = ix - 1
4315  jxh = ix + 1
4316  END IF
4317  DO iy=2, ny-1
4318  IF ( mapodi(iy,ix) .EQ. todo .AND. ( &
4319  mapodi(iy+1,ix ) .GE. 0. .OR. &
4320  mapodi(iy-1,ix ) .GE. 0. .OR. &
4321  mapodi(iy ,jxh) .GE. 0. .OR. &
4322  mapodi(iy ,jxl) .GE. 0. .OR. &
4323  ( mapodi(iy+1,jxh) .GE. 0. .AND. .NOT. &
4324  ( mapsta(iy+1,ix ) .NE. 1 .AND. &
4325  mapsta(iy ,jxh) .NE. 1 ) ) .OR. &
4326  ( mapodi(iy+1,jxl) .GE. 0. .AND. .NOT. &
4327  ( mapsta(iy+1,ix ) .NE. 1 .AND. &
4328  mapsta(iy ,jxl) .NE. 1 ) ) .OR. &
4329  ( mapodi(iy-1,jxl) .GE. 0. .AND. .NOT. &
4330  ( mapsta(iy-1,ix ) .NE. 1 .AND. &
4331  mapsta(iy ,jxl) .NE. 1 ) ) .OR. &
4332  ( mapodi(iy-1,jxh) .GE. 0. .AND. .NOT. &
4333  ( mapsta(iy-1,ix ) .NE. 1 .AND. &
4334  mapsta(iy ,jxh) .NE. 1 ) ) ) ) &
4335  maski(iy,ix) = .true.
4336  END DO
4337  END DO
4338  !
4339  change = .false.
4340  DO iy=2, ny-1
4341  DO ix=ixl, ixh
4342  IF ( ix .EQ. 1 ) THEN
4343  jxl = nx
4344  jxh = 2
4345  ELSE IF ( ix .EQ. nx ) THEN
4346  jxl = nx - 1
4347  jxh = 1
4348  ELSE
4349  jxl = ix - 1
4350  jxh = ix + 1
4351  END IF
4352  isea = mapfs(iy,ix)
4353  sty = factor * hqfac(iy,ix) / ( 0.58 * grav )
4354  stx = factor * hpfac(iy,ix) &
4355  / ( 0.58 * grav )
4356  stxy = sqrt( stx**2 + sty**2 )
4357  IF ( maski(iy,ix) ) THEN
4358  newval = odimax / sig(1) * dtmax
4359  IF ( mapodi(iy+1,ix ).GE.0. .AND. .NOT. &
4360  maski(iy+1,ix ) ) newval = min( &
4361  newval , mapodi(iy+1,ix )+sty )
4362  IF ( mapodi(iy-1,ix ).GE.0. .AND. .NOT. &
4363  maski(iy-1,ix ) ) newval = min( &
4364  newval , mapodi(iy-1,ix )+sty )
4365  IF ( mapodi(iy ,jxh).GE.0. .AND. .NOT. &
4366  maski(iy ,jxh) ) newval = min( &
4367  newval , mapodi(iy ,jxh)+stx)
4368  IF ( mapodi(iy ,jxl).GE.0. .AND. .NOT. &
4369  maski(iy ,jxl) ) newval = min( &
4370  newval , mapodi(iy ,jxl)+stx)
4371  IF ( mapodi(iy+1,jxh).GE.0. .AND. .NOT. &
4372  ( mapsta(iy+1,ix ) .NE. 1 .AND. &
4373  mapsta(iy ,jxh) .NE. 1 ) ) newval = &
4374  min( newval , mapodi(iy+1,jxh)+stxy)
4375  IF ( mapodi(iy+1,jxl).GE.0. .AND. .NOT. &
4376  ( mapsta(iy+1,ix ) .NE. 1 .AND. &
4377  mapsta(iy ,jxl) .NE. 1 ) ) newval = &
4378  min( newval , mapodi(iy+1,jxl)+stxy)
4379  IF ( mapodi(iy-1,jxl).GE.0. .AND. .NOT. &
4380  ( mapsta(iy-1,ix ) .NE. 1 .AND. &
4381  mapsta(iy ,jxl) .NE. 1 ) ) newval = &
4382  min( newval , mapodi(iy-1,jxl)+stxy)
4383  IF ( mapodi(iy-1,jxh).GE.0. .AND. .NOT. &
4384  ( mapsta(iy-1,ix ) .NE. 1 .AND. &
4385  mapsta(iy ,jxh) .NE. 1 ) ) newval = &
4386  min( newval , mapodi(iy-1,jxh)+stxy)
4387  mapodi(iy,ix) = newval
4388  change = .true.
4389  END IF
4390  END DO
4391  END DO
4392  !
4393  IF ( .NOT. change ) EXIT
4394  END DO
4395  !
4396  DO ix=2, nx-1
4397  DO iy=2, ny-1
4398  IF ( mapodi(iy,ix) .EQ. todo ) &
4399  mapodi(iy,ix) = 2. * odimax / sig(1) * dtmax
4400  END DO
4401  END DO
4402  !
4403  DEALLOCATE ( maski, stat=istat )
4404  check_dealloc_status( istat )
4405  !
4406  ! 2.f Update FLAGST
4407  !
4408  DO isea=1, nsea
4409  ix = mapsf(isea,1)
4410  iy = mapsf(isea,2)
4411  IF ( mapodi(iy,ix) .EQ. 0. ) flagst(isea) = .NOT. flghg1
4412  END DO
4413  !
4414  ! 2.g Test output
4415  !
4416 #ifdef W3_T
4417  np = 1 + (nx-1)/65
4418  DO ip=1, np
4419  ixl = 1 + (ip-1)*65
4420  ixh = min( nx, ip*65 )
4421  WRITE (mdst,9024) ixl, ixh
4422  DO iy=ny,1 , -1
4423  WRITE (mdst,9025) nint(mapodi(iy,ixl:ixh)*sig(1)/dtmax)
4424  END DO
4425  END DO
4426 #endif
4427  !
4428  ! ... End of loop in 1.a
4429  !
4430  END DO
4431  !
4432  ! -------------------------------------------------------------------- /
4433  ! 3. Final data base (full data base, scratched at end of routine)
4434  ! 3.a Loop over grids
4435  !
4436  ALLOCATE ( nrec(nrgrd), nsnd(nrgrd), ntpp(nmproc), stat=istat )
4437  check_alloc_status( istat )
4438  !
4439  DO i=1, nrgrd
4440  IF ( .NOT. dogrid(i) ) cycle
4441 #ifdef W3_T
4442  WRITE (mdst,9030) i
4443 #endif
4444  !
4445  CALL w3setg ( i, mdse, mdst )
4446  CALL w3seto ( i, mdse, mdst )
4447  CALL wmsetm ( i, mdse, mdst )
4448  !
4449  ALLOCATE ( map3d(ny,nx,-4:nrgrd), wgt3d(ny,nx,0:nrgrd), stat=istat )
4450  check_alloc_status( istat )
4451  map3d = 0
4452  wgt3d = 0.
4453  nrec = 0
4454  nsnd = 0
4455  !
4456  ! 3.b Filling MAP3D and WGT3D, as well as NREC and NSND
4457  !
4458  DO j=1, nrgrd
4459  IF ( .NOT. shrank(i,j) ) cycle
4460 #ifdef W3_T
4461  WRITE (mdst,9031) j
4462 #endif
4463  mapodi => mdatas(j)%MAPODI
4464  !
4465  DO jj=1, stores(i,j)%NTOT
4466  ix = stores(i,j)%IX(jj)
4467  iy = stores(i,j)%IY(jj)
4468  wgt3d(iy,ix,0) = mdatas(i)%MAPODI(iy,ix)
4469  map3d(iy,ix,-2) = mapfs(iy,ix)
4470  IF ( map3d(iy,ix,-2) .NE. 0 ) THEN
4471  map3d(iy,ix,-3) = 1 + (map3d(iy,ix,-2)-1)/naproc
4472 #ifdef W3_SHRD
4473  map3d(iy,ix,-4) = 1
4474 #endif
4475 #ifdef W3_MPI
4476  map3d(iy,ix,-4) = map3d(iy,ix,-2) - &
4477  (map3d(iy,ix,-3)-1)*naproc + croot - 1
4478 #endif
4479  END IF
4480  IF ( wgt3d(iy,ix,0).GE.0. .AND. mapsta(iy,ix).NE.0. .AND. &
4481  stores(i,j)%NAV(jj).GT.0 ) THEN
4482  wgt3d(iy,ix,j) = odimax / sig(1) * dtmax
4483  DO na=1, stores(i,j)%NAV(jj)
4484  jx = grids(j)%MAPSF(stores(i,j)%ISS(jj,na),1)
4485  jy = grids(j)%MAPSF(stores(i,j)%ISS(jj,na),2)
4486  IF ( mapodi(jy,jx) .GE. 0. ) wgt3d(iy,ix,j) = &
4487  min( wgt3d(iy,ix,j) , mapodi(jy,jx) )
4488  END DO
4489  IF ( wgt3d(iy,ix,j) .GT. 0. ) map3d(iy,ix,j) = 1
4490  END IF
4491  END DO
4492  !
4493  stores(i,j)%NFIN = sum(map3d(:,:,j))
4494 #ifdef W3_T
4495  WRITE (mdst,9032) stores(i,j)%NFIN, stores(i,j)%NTOT
4496 #endif
4497  !
4498  END DO
4499  !
4500  mapodi => mdatas(i)%MAPODI
4501  DO ix=1, nx
4502  DO iy=1, ny
4503  map3d(iy,ix, 0) = maxval(map3d(iy,ix,1:))
4504  map3d(iy,ix,-1) = sum(map3d(iy,ix,1:))
4505  IF ( map3d(iy,ix,-1) .GT. 0 ) THEN
4506  IF ( mapodi(iy,ix)*sig(1)/dtmax .GT. 1.5*odimax ) THEN
4507  wgt3d(iy,ix, 0:) = 0.
4508  map3d(iy,ix,-1:) = 0
4509  ELSE
4510  wgth = sum(wgt3d(iy,ix,:))
4511  IF ( wgth .GT. 1.e-25 ) THEN
4512  wgt3d(iy,ix,:) = wgt3d(iy,ix,:) / wgth
4513  ELSE
4514  wgt3d(iy,ix,:) = 0.
4515  END IF
4516  IF ( map3d(iy,ix,-4) .EQ. improc ) THEN
4517  nrec(i) = nrec(i) + 1
4518  DO jj=1, nrgrd
4519  IF ( map3d(iy,ix,jj) .GT. 0 ) &
4520  nrec(jj) = nrec(jj) + 1
4521  END DO
4522  END IF
4523  END IF
4524  END IF
4525  END DO
4526  END DO
4527  !
4528  DO j=1, nrgrd
4529  IF ( .NOT. shrank(i,j) ) cycle
4530  DO jj=1, stores(i,j)%NTOT
4531  ix = stores(i,j)%IX(jj)
4532  iy = stores(i,j)%IY(jj)
4533  IF ( map3d(iy,ix,j) .NE. 0 ) THEN
4534  DO na=1, stores(i,j)%NAV(jj)
4535  IF ( stores(i,j)%IPS(jj,na) .EQ. improc ) &
4536  nsnd(j) = nsnd(j) + 1
4537  END DO
4538  END IF
4539  END DO
4540  END DO
4541  !
4542  ng = maxval(map3d(:,:,-1))
4543  ntl = sum(map3d(:,:,0))
4544  !
4545  ! 3.c Check for points with all ODI = 0
4546  !
4547  mapodi => mdatas(i)%MAPODI
4548  nout = 0
4549  !
4550  jxl = nx
4551  jxh = 1
4552  jyl = ny
4553  jyh = 1
4554  !
4555  ALLOCATE ( mapout(ny,nx), stat=istat )
4556  check_alloc_status( istat )
4557  mapout = mapsta
4558  !
4559  DO ix=1, nx
4560  DO iy=1, ny
4561  IF ( abs(mapsta(iy,ix)).EQ. 1 .AND. &
4562  mapodi(iy,ix) .EQ. 0. .AND. &
4563  map3d(iy,ix,-1) .EQ. 0 ) THEN
4564  nout = nout + 1
4565  IF ( improc.EQ.nmperr .AND. nout.EQ. 1 ) &
4566  WRITE(mdse,*) ' '
4567  IF ( improc.EQ.nmperr .AND. nout.LE.25 ) &
4568  WRITE(mdse,1001) i, ix, iy
4569  IF ( improc.EQ.nmperr .AND. nout.EQ.25 ) &
4570  WRITE(mdse,1006)
4571  jxl = min( ix, jxl )
4572  jxh = max( ix, jxh )
4573  jyl = min( iy, jyl )
4574  jyh = max( iy, jyh )
4575  mapout(iy,ix) = 999
4576  END IF
4577  END DO
4578  END DO
4579  !
4580  ! 3.d Test and error output
4581  !
4582 #ifdef W3_T
4583  WRITE (mdst,9033) ntl, ng, nout
4584  WRITE (mdst,9034) nrec
4585  WRITE (mdst,9035) nsnd
4586  WRITE (mdst,9036)
4587  DO iy=ny,1 , -1
4588  WRITE (mdst,9037) map3d(iy,:,-1)
4589  END DO
4590 #endif
4591  !
4592  IF ( nout .GT. 0 ) THEN
4593  IF ( improc.EQ.nmperr ) THEN
4594  WRITE(mdse,1000) i, nout
4595  extra = 2
4596  jxl = max( 1, jxl - extra )
4597  jxh = min( nx, jxh + extra )
4598  jyl = max( 1, jyl - extra )
4599  jyh = min( ny, jyh + extra )
4600  WRITE (mdse,1002) jxl, jxh, jyl, jyh
4601  np = 1 + (jxh-jxl)/65
4602  DO ip=1, np
4603  ixl = jxl + (ip-1)*65
4604  ixh = min( nx, ixl+64 )
4605  WRITE (mdse,1005) ixl, ixh
4606  WRITE (mdse,1003) 'STATUS MAP MAPSTA'
4607  DO iy=jyh, jyl, -1
4608  WRITE (mdse,1004) mapsta(iy,ixl:ixh)
4609  END DO
4610  WRITE (mdse,1003) 'MISSING POINTS IN MAPSTA (**)'
4611  DO iy=jyh, jyl, -1
4612  WRITE (mdse,1004) mapout(iy,ixl:ixh)
4613  END DO
4614  WRITE (mdse,1003) 'OPEN BOUND. DISTANCE MAP MAPODI'
4615  DO iy=jyh, jyl, -1
4616  WRITE (mdse,1004) &
4617  nint(mapodi(iy,ixl:ixh)*sig(1)/dtmax)
4618  END DO
4619  WRITE (mdse,1003) 'GRID COVERAGE MAP MAP3D'
4620  DO iy=jyh, jyl, -1
4621  WRITE (mdse,1004) map3d(iy,ixl:ixh,-1)
4622  END DO
4623  WRITE (mdse,*)
4624  END DO
4625  END IF
4626  CALL extcde (1000)
4627  END IF
4628  !
4629  DEALLOCATE ( mapout, stat=istat )
4630  check_dealloc_status( istat )
4631  !
4632 #ifdef W3_T7
4633  WRITE (mdst,9330) i
4634  DO j=1, nrgrd
4635  IF ( .NOT. shrank(i,j) ) THEN
4636  IF ( i .NE. j ) WRITE (mdst,9331) j
4637  cycle
4638  END IF
4639  WRITE (mdst,9332) j, stores(i,j)%NFIN, i, j
4640  IF ( stores(i,j)%NFIN .EQ. 0 ) cycle
4641  ntl = 0
4642  DO jj=1, stores(i,j)%NTOT
4643  ix = stores(i,j)%IX(jj)
4644  iy = stores(i,j)%IY(jj)
4645  IF ( map3d(iy,ix,j) .EQ. 0 ) cycle
4646  ntl = ntl + 1
4647  na = stores(i,j)%NAV(jj)
4648  WRITE (mdst,9333) ntl, ix, iy, map3d(iy,ix,-2), &
4649  map3d(iy,ix,-3), map3d(iy,ix,-4), &
4650  wgt3d(iy,ix,0), wgt3d(iy,ix,j), na, &
4651  stores(i,j)%ISS(jj,1), &
4652  stores(i,j)%JSS(jj,1), &
4653  stores(i,j)%IPS(jj,1), &
4654  stores(i,j)%AWG(jj,1), &
4655  stores(i,j)%ITG(jj,1)
4656  DO ia=2, na
4657  WRITE (mdst,9334) stores(i,j)%ISS(jj,ia), &
4658  stores(i,j)%JSS(jj,ia), &
4659  stores(i,j)%IPS(jj,ia), &
4660  stores(i,j)%AWG(jj,ia), &
4661  stores(i,j)%ITG(jj,ia)
4662  END DO
4663  END DO
4664  END DO
4665 #endif
4666  !
4667  ! -------------------------------------------------------------------- /
4668  ! 4. Save data base as needed in EQSTGE
4669  !
4670  ! 4.a ALLOCATE storage
4671  ! 4.a.1 Local counters, weights and sea counters (grid 'I')
4672  !
4673  IF ( eqstge(i,i)%NREC .NE. 0 ) THEN
4674  DEALLOCATE (eqstge(i,i)%ISEA , eqstge(i,i)%JSEA , &
4675  eqstge(i,i)%WGHT, stat=istat )
4676  check_dealloc_status( istat )
4677  eqstge(i,i)%NREC = 0
4678 #ifdef W3_T
4679  WRITE (mdst,9040) i, i
4680 #endif
4681  END IF
4682  !
4683  IF ( nrec(i) .GT. 0 ) THEN
4684  ALLOCATE ( eqstge(i,i)%ISEA(nrec(i)) , &
4685  eqstge(i,i)%JSEA(nrec(i)) , &
4686  eqstge(i,i)%WGHT(nrec(i)), stat=istat )
4687  check_alloc_status( istat )
4688  eqstge(i,i)%NREC = nrec(i)
4689 #ifdef W3_T
4690  WRITE (mdst,9041) i, i, nrec(i)
4691 #endif
4692  END IF
4693  !
4694  ! 4.a.1 Local counters, arrays weights etc. (grid 'J' receive)
4695  !
4696  DO j=1, nrgrd
4697  IF ( i .EQ. j ) cycle
4698  eqstge(i,i)%NTOT = stores(i,j)%NFIN
4699  !
4700  IF ( eqstge(i,j)%NREC .NE. 0 ) THEN
4701  DEALLOCATE ( eqstge(i,j)%ISEA , eqstge(i,j)%JSEA , &
4702  eqstge(i,j)%WGHT , eqstge(i,j)%SEQL , &
4703  eqstge(i,j)%NAVG , eqstge(i,j)%WAVG , &
4704  eqstge(i,j)%RIP , eqstge(i,j)%RTG, stat=istat )
4705  check_dealloc_status( istat )
4706  eqstge(i,j)%NREC = 0
4707  eqstge(i,j)%NAVMAX = 1
4708 #ifdef W3_T
4709  WRITE (mdst,9042) i, j
4710 #endif
4711  END IF
4712  !
4713  IF ( nrec(j) .GT. 0 ) THEN
4714  na = maxval( stores(i,j)%NAV(1:stores(i,j)%NTOT) )
4715  eqstge(i,j)%NAVMAX = na
4716  ALLOCATE ( eqstge(i,j)%ISEA(nrec(j)) , &
4717  eqstge(i,j)%JSEA(nrec(j)) , &
4718  eqstge(i,j)%WGHT(nrec(j)) , &
4719  eqstge(i,j)%SEQL(sgrds(j)%NSPEC,nrec(j),na), &
4720  eqstge(i,j)%NAVG(nrec(j)) , &
4721  eqstge(i,j)%WAVG(nrec(j),na), &
4722  eqstge(i,j)%RIP(nrec(j),na), &
4723  eqstge(i,j)%RTG(nrec(j),na), stat=istat )
4724  check_alloc_status( istat )
4725  eqstge(i,j)%NREC = nrec(j)
4726 #ifdef W3_T
4727  WRITE (mdst,9043) i, j, nrec(j), na
4728 #endif
4729  END IF
4730  !
4731  IF ( eqstge(i,j)%NSND .NE. 0 ) THEN
4732  DEALLOCATE ( eqstge(i,j)%SIS , eqstge(i,j)%SJS , &
4733  eqstge(i,j)%SI1 , eqstge(i,j)%SI2 , &
4734  eqstge(i,j)%SIP , eqstge(i,j)%STG, stat=istat )
4735  check_dealloc_status( istat )
4736  eqstge(i,j)%NSND = 0
4737 #ifdef W3_T
4738  WRITE (mdst,9044) i, j
4739 #endif
4740  END IF
4741  !
4742  IF ( nsnd(j) .GT. 0 ) THEN
4743  ALLOCATE ( eqstge(i,j)%SIS(nsnd(j)) , &
4744  eqstge(i,j)%SJS(nsnd(j)) , &
4745  eqstge(i,j)%SI1(nsnd(j)) , &
4746  eqstge(i,j)%SI2(nsnd(j)) , &
4747  eqstge(i,j)%SIP(nsnd(j)) , &
4748  eqstge(i,j)%STG(nsnd(j)), stat=istat )
4749  check_alloc_status( istat )
4750  eqstge(i,j)%NSND = nsnd(j)
4751 #ifdef W3_T
4752  WRITE (mdst,9045) i, j, nsnd(j)
4753 #endif
4754  END IF
4755  !
4756  END DO
4757  !
4758  ! 4.b Store data in EQSTGE
4759  ! 4.b.1 Grid I (JSEA and weight only)
4760  !
4761  IF ( eqstge(i,i)%NREC .GT. 0 ) THEN
4762  ntl = 0
4763  DO ix=1, nx
4764  DO iy=1, ny
4765  IF ( map3d(iy,ix,0) .EQ. 0 ) cycle
4766  IF ( map3d(iy,ix,-4) .NE. improc ) cycle
4767  ntl = ntl + 1
4768  eqstge(i,i)%ISEA(ntl) = map3d(iy,ix,-2)
4769  eqstge(i,i)%JSEA(ntl) = map3d(iy,ix,-3)
4770  eqstge(i,i)%WGHT(ntl) = wgt3d(iy,ix,0)
4771  END DO
4772  END DO
4773  END IF
4774  !
4775  ! 4.b.2 All other grids, info for receiving
4776  !
4777  DO j=1, nrgrd
4778  IF ( .NOT. shrank(i,j) ) cycle
4779  IF ( eqstge(i,j)%NREC .EQ. 0 ) cycle
4780  ntl = 0
4781  !
4782  DO jj=1, stores(i,j)%NTOT
4783  ix = stores(i,j)%IX(jj)
4784  iy = stores(i,j)%IY(jj)
4785  IF ( map3d(iy,ix,j) .EQ. 0 ) cycle
4786  IF ( map3d(iy,ix,-4) .NE. improc ) cycle
4787  ntl = ntl + 1
4788  eqstge(i,j)%ISEA(ntl) = map3d(iy,ix,-2)
4789  eqstge(i,j)%JSEA(ntl) = map3d(iy,ix,-3)
4790  eqstge(i,j)%WGHT(ntl) = wgt3d(iy,ix,j)
4791  na = stores(i,j)%NAV(jj)
4792  eqstge(i,j)%NAVG(ntl) = na
4793  eqstge(i,j)%WAVG(ntl,1:na) = stores(i,j)%AWG(jj,1:na)
4794  eqstge(i,j)%RIP (ntl,1:na) = stores(i,j)%IPS(jj,1:na)
4795  eqstge(i,j)%RTG (ntl,1:na) = stores(i,j)%ITG(jj,1:na)
4796  END DO
4797  !
4798  END DO
4799  !
4800  ! 4.b.3 All other grids, info for sending
4801  !
4802  DO j=1, nrgrd
4803  IF ( .NOT. shrank(i,j) ) cycle
4804  IF ( eqstge(i,j)%NSND .EQ. 0 ) cycle
4805  ntpp = 0
4806  ntl = 0
4807  !
4808  DO jj=1, stores(i,j)%NTOT
4809  ix = stores(i,j)%IX(jj)
4810  iy = stores(i,j)%IY(jj)
4811  IF ( map3d(iy,ix,j) .NE. 0 ) THEN
4812  ntpp(map3d(iy,ix,-4)) = ntpp(map3d(iy,ix,-4)) + 1
4813  DO na=1, stores(i,j)%NAV(jj)
4814  IF ( stores(i,j)%IPS(jj,na) .EQ. improc ) THEN
4815  ntl = ntl + 1
4816  eqstge(i,j)%SIS(ntl) = stores(i,j)%ISS(jj,na)
4817  eqstge(i,j)%SJS(ntl) = stores(i,j)%JSS(jj,na)
4818  eqstge(i,j)%SI1(ntl) = ntpp(map3d(iy,ix,-4))
4819  eqstge(i,j)%SI2(ntl) = na
4820  eqstge(i,j)%SIP(ntl) = map3d(iy,ix,-4)
4821  eqstge(i,j)%STG(ntl) = stores(i,j)%ITG(jj,na)
4822  END IF
4823  END DO
4824  END IF
4825  END DO
4826  !
4827  END DO
4828  !
4829  ! 4.c Detailed test output
4830  !
4831 #ifdef W3_T5
4832  dstr = ' '
4833 #endif
4834  !
4835 #ifdef W3_T5
4836  IF ( eqstge(i,i)%NREC .EQ. 0 ) THEN
4837  WRITE (mdst,9140) i
4838  ELSE
4839  WRITE (mdst,9141) i
4840  na = 0
4841  DO j=1, nrgrd
4842  IF ( i.EQ.j .OR. eqstge(i,j)%NREC.EQ.0 ) cycle
4843  na = na + 1
4844  nsnd(na) = j
4845  END DO
4846  WRITE (mdst,9142) nsnd(1:na)
4847  WRITE (mdst,9143)
4848  ALLOCATE ( tstr(na), stat=istat )
4849  check_alloc_status( istat )
4850  DO jj=1, eqstge(i,i)%NREC
4851  DO ng=1, na
4852  j = nsnd(ng)
4853  tstr(ng) = dstr
4854  DO ntl=1, eqstge(i,j)%NREC
4855  IF ( eqstge(i,i)%ISEA(jj) .EQ. &
4856  eqstge(i,j)%ISEA(ntl) ) THEN
4857  WRITE (tstr(ng),9144) ntl, &
4858  eqstge(i,j)%WGHT(ntl), &
4859  eqstge(i,j)%NAVG(ntl)
4860  EXIT
4861  END IF
4862  END DO
4863  END DO
4864  WRITE (mdst,9145) jj, eqstge(i,i)%ISEA(jj), &
4865  eqstge(i,i)%JSEA(jj), &
4866  eqstge(i,i)%WGHT(jj), &
4867  tstr
4868  END DO
4869  DEALLOCATE ( tstr, stat=istat )
4870  check_dealloc_status( istat )
4871  END IF
4872 #endif
4873  !
4874 #ifdef W3_T5
4875  DO j=1, nrgrd
4876  IF ( i.EQ.j .OR. eqstge(i,j)%NREC.EQ.0 ) cycle
4877  WRITE (mdst,9146) j
4878  DO jj=1, eqstge(i,j)%NREC
4879  WRITE (mdst,9147) jj, eqstge(i,j)%NAVG(jj), &
4880  ( eqstge(i,j)%WAVG(jj,na), &
4881  eqstge(i,j)%RIP (jj,na), &
4882  eqstge(i,j)%RTG (jj,na), &
4883  na=1, eqstge(i,j)%NAVG(jj) )
4884  END DO
4885  END DO
4886 #endif
4887  !
4888 #ifdef W3_T6
4889  DO j=1, nrgrd
4890  IF ( i .EQ. j ) cycle
4891  IF ( eqstge(i,j)%NSND .EQ. 0 ) THEN
4892  WRITE (mdst,9240) j
4893  ELSE
4894  WRITE (mdst,9241) j
4895  DO jj=1, eqstge(i,j)%NSND
4896  WRITE (mdst,9242) jj, eqstge(i,j)%SIS(jj), &
4897  eqstge(i,j)%SJS(jj), &
4898  eqstge(i,j)%SI1(jj), &
4899  eqstge(i,j)%SI2(jj), &
4900  eqstge(i,j)%SIP(jj), &
4901  eqstge(i,j)%STG(jj)
4902  END DO
4903  END IF
4904  END DO
4905 #endif
4906  !
4907  ! ... End of loop started in 3.a
4908  !
4909  DEALLOCATE ( map3d, wgt3d, stat=istat )
4910  check_dealloc_status( istat )
4911  END DO
4912  !
4913  ! -------------------------------------------------------------------- /
4914  ! 5. Generate GRDEQL
4915  ! 5.a Size of array
4916  !
4917  nrec = 0
4918  !
4919  DO i=1, nrgrd
4920  DO j=1, nrgrd
4921  IF ( i.EQ.j .OR. stores(i,j)%NFIN.EQ.0 ) cycle
4922  nrec(i) = nrec(i) + 1
4923  END DO
4924  END DO
4925  !
4926  na = maxval(nrec)
4927  ALLOCATE ( grdeql(nrgrd,0:na), stat=istat )
4928  check_alloc_status( istat )
4929  grdeql = 0
4930  !
4931 #ifdef W3_T
4932  WRITE (mdst,9050) na
4933 #endif
4934  !
4935  ! 5.b Fill array
4936  !
4937  DO i=1, nrgrd
4938  grdeql(i,0) = nrec(i)
4939  jj = 0
4940  DO j=1, nrgrd
4941  IF ( i.EQ.j .OR. stores(i,j)%NFIN.EQ.0 ) cycle
4942  jj = jj + 1
4943  grdeql(i,jj) = j
4944  END DO
4945  END DO
4946  !
4947 #ifdef W3_T
4948  WRITE (mdst,9051)
4949  DO i=1, nrgrd
4950  WRITE (mdst,9052) i, grdeql(i,0:grdeql(i,0))
4951  END DO
4952 #endif
4953  !
4954  ! 5.c Resolution test
4955  !
4956 
4957  IF ( flagll ) THEN
4958  factor = 1.
4959  ELSE
4960  factor = 1.e-3
4961  END IF
4962  !
4963  ! notes: This resolution test, with FACMAX=2, is pretty strict, so
4964  ! it is not going to be appropriate for irregular grids.
4965  ! We'll just have to trust the judgement of the user in the
4966  ! case of irregular grids. But if we change our minds and do
4967  ! some kind of check for irregular grids, we could make
4968  ! a check against median(HPFAC) and median(HQFAC).
4969 
4970  DO i=1, nrgrd
4971  CALL w3setg ( i, mdse, mdst )
4972  IF ( gtype.EQ.rlgtype ) THEN
4973  DO jj=1, grdeql(i,0)
4974  j = grdeql(i,jj)
4975  IF ( grids(j)%GTYPE.EQ.rlgtype ) THEN
4976  IF ( sx/grids(j)%SX .GT. facmax .OR. &
4977  sx/grids(j)%SX .LT. 1./facmax .OR. &
4978  sy/grids(j)%SY .GT. facmax .OR. &
4979  sy/grids(j)%SY .LT. 1./facmax ) THEN
4980  IF ( improc.EQ.nmperr ) WRITE(mdse,1050) i, factor*sx, &
4981  factor*sy, j, factor*grids(j)%SX, factor*grids(j)%SY
4982  CALL extcde ( 1050 )
4983  END IF ! IF ( SX/GR ...
4984  END IF ! IF ( GRIDS(J)%GTYPE...
4985  END DO ! DO JJ=...
4986  END IF ! IF ( GTYPE....
4987  END DO ! DO I=...
4988  !
4989  ! 5.d Group number test
4990  !
4991  DO i=1, nrgrd
4992  IF ( grdeql(i,0) .GE. 2 ) THEN
4993  tgrp = grgrp(grdeql(i,1))
4994  DO j=2, grdeql(i,0)
4995  IF ( grgrp(grdeql(i,j)) .NE. tgrp ) THEN
4996  IF ( improc .EQ. nmperr ) WRITE(mdse,1051) &
4997  grdeql(i,1), grgrp(grdeql(i,1)), &
4998  grdeql(i,j), grgrp(grdeql(i,j))
4999  CALL extcde ( 1051 )
5000  END IF
5001  END DO
5002  END IF
5003  END DO
5004  !
5005  ! -------------------------------------------------------------------- /
5006  ! 6. Final clean up
5007  !
5008  DO i=1, nrgrd
5009  DO j=1, nrgrd
5010  IF ( stores(i,j)%INIT ) THEN
5011  DEALLOCATE ( stores(i,j)%IX , stores(i,j)%IY , &
5012  stores(i,j)%NAV , stores(i,j)%FLA , &
5013  stores(i,j)%ISS , stores(i,j)%JSS , &
5014  stores(i,j)%IPS , stores(i,j)%ITG , &
5015  stores(i,j)%AWG , stat=istat )
5016  check_dealloc_status( istat )
5017  END IF
5018  END DO
5019  END DO
5020  !
5021  DEALLOCATE ( shrank, stores, nrec, nsnd, ntpp, stat=istat )
5022  check_dealloc_status( istat )
5023  !
5024  RETURN
5025  !
5026  ! Formats
5027  !
5028 1000 FORMAT (/' *** WAVEWATCH III ERROR IN WMGEQL : *** '/ &
5029  ' UNCOVERED EDGE POINTS FOR GRID',i4,' (',i6,')'/)
5030 1001 FORMAT ( ' GRID',i4,' POINT',2i5,' NOT COVERED (WMGEQL)')
5031 1002 FORMAT ( ' DIAGNOSTICS IX AND IY RANGE:',4i6)
5032 1003 FORMAT (/' SHOWING ',a/)
5033 1004 FORMAT (2x,65i2)
5034 1005 FORMAT (/' SHOWING IX RANGE ',2i6)
5035 1006 FORMAT ( ' (WILL NOT PRINT ANY MORE UNCOVERED POINTS)')
5036  !
5037 1020 FORMAT (/' *** WAVEWATCH III WARNING WMGEQL : *** '/ &
5038  ' REMOVED BOUNDARY POINT FROM OPEN EDGE DISTANCE MAP'/ &
5039  ' GRID, IX, IY :',3i6)
5040  !
5041 1050 FORMAT (/' *** WAVEWATCH III ERROR IN WMGEQL : *** '/ &
5042  ' GRID INCREMENTS TOO DIFFERENT '/ &
5043  ' GRID',i4,' INCREMENTS ',2f8.2/ &
5044  ' GRID',i4,' INCREMENTS ',2f8.2/)
5045 1051 FORMAT (/' *** WAVEWATCH III ERROR IN WMGEQL : *** '/ &
5046  ' OVERLAPPING GRIDS NEED TO BE IN SAME GROUP '/ &
5047  ' GRID',i4,' IN GROUP',i4/ &
5048  ' GRID',i4,' IN GROUP',i4/)
5049  !
5050 #ifdef W3_T
5051 9010 FORMAT ( ' TEST WMGEQL : STARTING LOOP OVER GRIDS')
5052 9011 FORMAT ( ' TEST WMGEQL : I, RANK :',2i4)
5053 9012 FORMAT ( ' GRID ',i3,' HAS SAME RANK')
5054 9013 FORMAT ( ' ',a)
5055 #endif
5056  !
5057 #ifdef W3_T
5058 9020 FORMAT ( ' TEST WMGEQL : GENERATING DISTANCE MAP GRID ',i3)
5059 9024 FORMAT ( ' TEST WMGEQL : FINAL MAP FOR X RANGE ',2i6)
5060 9025 FORMAT (2x,65i2)
5061 #endif
5062  !
5063 #ifdef W3_T
5064 9030 FORMAT ( ' TEST WMGEQL : DEPENDENCE INFORMATION GRID ',i3)
5065 9031 FORMAT ( ' CHECKING GRID ',i3)
5066 9032 FORMAT ( ' POINTS USED/AVAIL :',2i6)
5067 9033 FORMAT ( ' TOTAL/GRIDS/OUT :',3i6)
5068 9034 FORMAT ( ' LOCAL PER GRID :',15i6)
5069 9035 FORMAT ( ' SENDING PER GRID :',15i6)
5070 9036 FORMAT ( ' TEST WMGEQL : NUMBER OF CONTRIBUTING GRIDS MAP')
5071 9037 FORMAT (2x,65i2)
5072 #endif
5073  !
5074 #ifdef W3_T
5075 9040 FORMAT ( ' TEST WMGEQL : GRID ',i2,'-',i2,' CLEAR STORAGE')
5076 9041 FORMAT ( ' TEST WMGEQL : GRID ',i2,'-',i2,' STORAGE SIZE',i6)
5077 9042 FORMAT ( ' RECV ',i2,'-',i2,' CLEAR STORAGE')
5078 9043 FORMAT ( ' RECV ',i2,'-',i2,' STORAGE SIZE',2i6)
5079 9044 FORMAT ( ' SEND ',i2,'-',i2,' CLEAR STORAGE')
5080 9045 FORMAT ( ' SEND ',i2,'-',i2,' STORAGE SIZE',i6)
5081 #endif
5082  !
5083 #ifdef W3_T
5084 9050 FORMAT ( ' TEST WMGEQL : GRDEQL DIMENSIONED AT ',i2)
5085 9051 FORMAT ( ' TEST WMGEQL : GRDEQL :')
5086 9052 FORMAT ( ' ',2i4,' : ',20i3)
5087 #endif
5088  !
5089 #ifdef W3_T5
5090 9140 FORMAT ( ' TEST WMGEQL : NO RECEIVING DATA FOR GRID ',i3, &
5091  ' <=====================================')
5092 9141 FORMAT ( ' TEST WMGEQL : RECEIVING DATA GRID ',i3, &
5093  ' <=====================================')
5094 9142 FORMAT ( ' RECEIVING FROM GRID(S) ',10i3)
5095 9143 FORMAT (16x,'COUNT, ISEA, JSEA, WEIGHT / ', &
5096  'COUNT WEIGHT NR PER GRID')
5097 9144 FORMAT (i6,f6.2,i6)
5098 9145 FORMAT (12x,3i6,f6.2,10(' - ',a))
5099 9146 FORMAT ( ' TEST WMGEQL : RECEIVING DATA AVG. GRID ',i3)
5100 9147 FORMAT (12x,i6,i2,4(f8.2,i4,i6))
5101 #endif
5102  !
5103 #ifdef W3_T6
5104 9240 FORMAT ( ' TEST WMGEQL : NO SENDING DATA FOR GRID ',i3, &
5105  ' <=====================================')
5106 9241 FORMAT ( ' TEST WMGEQL : SENDING DATA GRID ',i3, &
5107  ' <====================================='/ &
5108  11x,'COUNT, ISEA, JSEA, ARRAY IND., PROC, TAG')
5109 9242 FORMAT ( ' ',4i8,i4,2i8)
5110 #endif
5111  !
5112 #ifdef W3_T7
5113 9330 FORMAT ( ' TEST WMGEQL : FULL SOURCE INFO GRID ',i3, &
5114  ' <=====================================')
5115 9331 FORMAT ( ' GRID ',i3,' IS NOT OF SAME RANK')
5116 9332 FORMAT ( ' GRID ',i3,' CONTRIBUTES TO',i6, &
5117  ' GRID POINTS'/ &
5118  18x,'<---------- GRID',i6,' ---------->', &
5119  4x,'<----------- GRID',i6,' ----------->'/ &
5120  18x,'NR IX IY ISEA JSEA IP WGTH', &
5121  2x,' WGTH NA ISEA JSEA IP WGTH TAG' )
5122 9333 FORMAT (15x,3i5,2i6,i4,f6.2,2x,f6.2,i4,2i6,i4,f6.2,i6)
5123 9334 FORMAT (64x,2i6,i4,f6.2,i6)
5124 #endif
5125  !/
5126  !/ End of WMGEQL ----------------------------------------------------- /
5127  !/

References w3gdatmd::clgtype, wmmdatmd::croot, constants::dera, w3gdatmd::dtcfl, w3gdatmd::dtmax, wmmdatmd::eqstge, w3servmd::extcde(), w3gdatmd::flagll, w3gdatmd::flagst, wmmdatmd::flghg1, wmmdatmd::grank, constants::grav, wmmdatmd::grdeql, wmmdatmd::grgrp, w3gdatmd::grids, w3gdatmd::gtype, w3gdatmd::hpfac, w3gdatmd::hqfac, w3gdatmd::iclose, w3gdatmd::iclose_none, w3gdatmd::iclose_trpl, wmmdatmd::improc, wmmdatmd::init_get_jsea_isproc_glob(), w3gdatmd::mapfs, wmmdatmd::mapodi, w3gdatmd::mapsf, w3gdatmd::mapst2, w3gdatmd::mapsta, wmmdatmd::mdatas, wmmdatmd::mdse, wmmdatmd::mdst, w3odatmd::naproc, wmmdatmd::nmperr, wmmdatmd::nmproc, wmmdatmd::nrgrd, w3gdatmd::nsea, w3gdatmd::nx, w3gdatmd::ny, constants::radius, w3gdatmd::rlgtype, w3gdatmd::sgrds, w3gdatmd::sig, w3gdatmd::smctype, w3servmd::strace(), w3gdatmd::sx, w3gdatmd::sy, w3gdatmd::ungtype, w3gdatmd::w3setg(), w3odatmd::w3seto(), wmmdatmd::wmsetm(), w3gdatmd::x0, and w3gdatmd::y0.

Referenced by wminitmd::wminit(), and wminitmd::wminitnml().

◆ wmghgh()

subroutine wmgridmd::wmghgh

Determine relation to higher ranked grids for each grid.

Base map set in WMGLOW, supplemental data computed here. Map averaging information for higher ranked grid to lower ranked grid.

Author
H. L. Tolman
W. E. Rogers
Date
10-Dec-2014

Definition at line 1100 of file wmgridmd.F90.

1100  !/
1101  !/ +-----------------------------------+
1102  !/ | WAVEWATCH III NOAA/NCEP |
1103  !/ | H. L. Tolman |
1104  !/ | W. E. Rogers |
1105  !/ | FORTRAN 90 |
1106  !/ | Last update : 10-Dec-2014 !
1107  !/ +-----------------------------------+
1108  !/
1109  !/ 28-Dec-2005 : Origination. ( version 3.08 )
1110  !/ 09-Mar-2006 : Carry over land mask. ( version 3.09 )
1111  !/ 28-Dec-2006 : Simplify NIT for partial comm. ( version 3.10 )
1112  !/ 07-Feb-2007 : Setting FLAGST. ( version 3.10 )
1113  !/ 20-May-2009 : Linking FLAGST and FLGHG1. ( version 3.14 )
1114  !/ 26-May-2009 : Fix erroneous cyclic updating. ( version 3.14 )
1115  !/ 30-Oct-2009 : Implement run-time grid selection. ( version 3.14 )
1116  !/ (W. E. Rogers & T. J. Campbell, NRL)
1117  !/ 06-Dec-2010 : Change from GLOBAL (logical) to ICLOSE (integer) to
1118  !/ specify index closure for a grid. ( version 3.14 )
1119  !/ (T. J. Campbell, NRL)
1120  !/ 23-Dec-2010 : Fix HPFAC and HQFAC by including the COS(YGRD)
1121  !/ factor with DXDP and DXDQ terms. ( version 3.14 )
1122  !/ (T. J. Campbell, NRL)
1123  !/ 07-Jul-2011 : Bug fix for IX bounds with wrapping ( version 3.14+)
1124  !/ grids (see use of "IDSTLA" below)
1125  !/ (W. E. Rogers, NRL)
1126  !/ 02-Aug-2011 : Adapted for use with irregular ( version 3.14+)
1127  !/ grids (W. E. Rogers, NRL)
1128  !/ 21-Sep-2012 : Modified to implement SCRIP remap ( version 4.11 )
1129  !/ file read and write option
1130  !/ (K. R. Lind, NRL)
1131  !/ 05-Aug-2013 : Change PR2/3 to UQ/UNO in distances.( version 4.12 )
1132  !/ 10-Dec-2014 : Add checks for allocate status ( version 5.04 )
1133  !/ 20-Jan-2017 : Fix SCRIP ALLWGTS allocation error and improve
1134  !/ SCRIPNC SCRIP_STOP report and exit. ( version 6.02 )
1135  !/
1136  ! 1. Purpose :
1137  !
1138  ! Determine relation to higher ranked grids for each grid.
1139  ! Base map set in WMGLOW, supplemental data computed here.
1140  !
1141  ! 2. Method :
1142  !
1143  ! Map averaging information for higher ranked grid to lower
1144  ! ranked grid.
1145  !
1146  ! 3. Parameters :
1147  !
1148  ! 4. Subroutines used :
1149  !
1150  ! Name Type Module Description
1151  ! ----------------------------------------------------------------
1152  ! W3SETO, W3SETG, W3DMO5, WMSETM
1153  ! Subr. W3xDATMD Manage data structures.
1154  ! STRACE Sur. W3SERVMD Subroutine tracing.
1155  ! EXTCDE Sur. Id. Program abort.
1156  ! ----------------------------------------------------------------
1157  !
1158  ! 5. Called by :
1159  !
1160  ! 6. Error messages :
1161  !
1162  ! 7. Remarks :
1163  !
1164  ! Regarding the map of distances to the boundary :
1165  ! - v4.00 : the map of distances to the boundary was intentionally
1166  ! not an accurate characteristic distance. It was felt that
1167  ! it was more important that it be 'safe' and quick to compute.
1168  ! An iterative method was used to compute distance by starting
1169  ! at boundary and working inwards one grid row layer at a time,
1170  ! incrementing distance by dx etc. until the distance map was
1171  ! filled in. This was characterized as "local increment solution
1172  ! only."
1173  ! - v4.01 : conversion to work with irregular grids. Author could not
1174  ! think of any way to retain "local increment solution" method
1175  ! for situation of irregular grids. Therefore method has been
1176  ! changed to compute accurate distances. New method is also
1177  ! more transparent and simpler with much less code, thus
1178  ! easier to modify or debug. It is expected that this method
1179  ! could be more expensive to compute. Isolated timings were
1180  ! not performed. Since the iteration step has been removed,
1181  ! it is hoped that the expense is at least offset somewhat.
1182  !
1183  ! Regarding method of calculating weights :
1184  ! o If SCRIP software is not compiled into WW3 by user
1185  ! (i.e. if SCRIP switch is not set, then original method
1186  ! (denoted "_OM") will be used.
1187  ! o If SCRIP is activated by user, and all grids are
1188  ! regular and specified in terms of meters (cartesian),
1189  ! then WMGHGH will calculate weights using both methods,
1190  ! and then compare the two, producing an error message
1191  ! if they do not match (built-in regression testing)
1192  ! For more info, see Section 0a below.
1193  !
1194  ! re: Inconsistent RANK vs NBI (warning message) in Section 1.d :
1195  ! This was an error, but has been changed to a warning to allow
1196  ! more flexibility, e.g. having two outer grids with different
1197  ! rank (latter to avoid handling via WMGEQL).
1198  ! Change made July 2016.
1199  ! Old system:
1200  ! * grid rank > 1 and NBI>0 : do computations
1201  ! * grid rank > 1 and NBI=0 : error message
1202  ! * grid rank = 1 and NBI>0 : do nothing
1203  ! * grid rank = 1 and NBI=0 : do nothing
1204  ! New system:
1205  ! * grid rank > 1 and NBI>0 : do computations
1206  ! * grid rank > 1 and NBI=0 : do nothing w/ warning message
1207  ! * grid rank = 1 and NBI>0 : do nothing
1208  ! * grid rank = 1 and NBI=0 : do nothing
1209  !
1210  ! 8. Structure :
1211  !
1212  ! See source code.
1213  !
1214  ! 9. Switches :
1215  !
1216  ! !/SHRD Distributed memory approach
1217  ! !/DIST
1218  !
1219  ! !/PRn propagation scheme.
1220  !
1221  ! !/S Enable subroutine tracing.
1222  ! !/T Enable test output.
1223  ! !/T3 Test output for received spectra.
1224  ! !/T4 Test output for sent spectra.
1225  !
1226  ! 10. Source code :
1227  !
1228  !/ ------------------------------------------------------------------- /
1229  !
1230  USE constants
1231  USE w3servmd, ONLY: extcde
1232  USE w3gsrumd, ONLY: w3dist
1233 #ifdef W3_S
1234  USE w3servmd, ONLY: strace
1235 #endif
1236  !
1237  USE w3gdatmd
1238  USE w3odatmd
1239  USE wmmdatmd
1240  USE w3parall, ONLY : init_get_jsea_isproc
1241  ! USE W3PARALL, ONLY : INIT_GET_JSEA_ISPROC_GLOB
1242 #ifdef W3_SCRIP
1243  USE wmscrpmd
1244  USE scrip_interface
1245 #endif
1246  !/
1247  IMPLICIT NONE
1248  !
1249 #ifdef W3_MPI
1250  include "mpif.h"
1251 #endif
1252  !
1253  !/
1254  !/ ------------------------------------------------------------------- /
1255  !/ Parameter list
1256  !/
1257  !/ ------------------------------------------------------------------- /
1258  !/ Local parameters
1259  !/
1260 
1261  ! notes re: variable names: During the extension for irregular grids,
1262  ! some variable were renamed to make the code more readable:
1263  ! JX==> ISRC
1264  ! JY==> JSRC
1265  ! IX==> IDST
1266  ! IY==> JDST
1267  ! grid I ==> grid GDST
1268  ! grid J ==> grid GSRC
1269 
1270  INTEGER :: GDST, IJ, IDST, JDST, GSRC, JJ, IB, ISEA, &
1271  JSEA, IDSTLA, IDSTHA, JDSTLA, JDSTHA, &
1272  ISRC, JSRC, ISRCL, ISRCH, JSRCL, JSRCH, NIT, &
1273  NRTOT, NROK, JF, JR, NLMAX, ISPROC, ISPRO2, &
1274  IREC, ISND, ITMP,ILOC
1275 #ifdef W3_SCRIP
1276  INTEGER :: NLMAX_SCRIP
1277 #endif
1278 
1279 #ifdef W3_DIST
1280  INTEGER :: LTAG0
1281 #endif
1282 #ifdef W3_MPI
1283  INTEGER :: IERR_MPI
1284 #endif
1285 #ifdef W3_S
1286  INTEGER, SAVE :: IENT = 0
1287 #endif
1288 
1289  INTEGER, ALLOCATABLE :: IDSTL(:), IDSTH(:), JDSTL(:), JDSTH(:), &
1290  MAPTST(:,:), &
1291  I1(:,:), I2(:,:), I3(:), I4(:), &
1292  INFLND(:,:)
1293  INTEGER, ALLOCATABLE :: NX_BEG(:), NX_END(:)
1294 #ifdef W3_MPIBDI
1295  INTEGER, ALLOCATABLE :: NX_SIZE(:), IRQ(:), MSTAT(:,:)
1296 #endif
1297 #ifdef W3_MPI
1298  INTEGER :: IM, NX_REM, TAG, NRQ
1299 #endif
1300 
1301  INTEGER, ALLOCATABLE :: TMPINT_OM(:,:),TMPINT(:,:)
1302  REAL, ALLOCATABLE :: TMPRL_OM(:,:) ,TMPRL(:,:)
1303  REAL, ALLOCATABLE :: BDIST_OM(:) ,BDIST(:)
1304  INTEGER :: NR0 , NR1 , NR2 , NRL , NLOC
1305  INTEGER :: NR0_OM, NR1_OM, NR2_OM, NRL_OM, NLOC_OM
1306 
1307 #ifdef W3_DIST
1308  INTEGER, ALLOCATABLE :: LTAG(:)
1309 #endif
1310 
1311  REAL :: FACTOR, STX, STY, STXY, NEWVAL, &
1312  XL, XH, YL, YH, XA, YA, DXC, JD, &
1313  WX, WY, WTOT
1314 
1315  LOGICAL :: FLGREC
1316 
1317  LOGICAL, ALLOCATABLE :: GRIDOK(:), &
1318  STMASK(:,:), MASKI(:,:), TMPLOG(:)
1319 
1320  INTEGER :: JBND,IBND ! counter for boundary points
1321  REAL :: DD ! distance to boundary point
1322  ! (temporary variable)
1323  REAL :: XDST,YDST
1324  REAL :: XSRC,YSRC
1325  REAL :: WXWY
1326  INTEGER :: NJDST,NIDST,KDST
1327  INTEGER :: NJSRC,NISRC,KSRC
1328  INTEGER :: IPNT,ICOUNT,IPNT2
1329  INTEGER :: DST_GRID_SIZE,ISTOP,JTMP
1330 
1331  REAL :: DX_MAX_GDST,DY_MAX_GDST
1332  REAL :: DX_MIN_GSRC,DY_MIN_GSRC
1333 
1334 #ifdef W3_SCRIP
1335  TYPE allwgt
1336  TYPE(WEIGHT_DATA), POINTER :: WGTDATA(:)
1337  END TYPE allwgt
1338  TYPE(ALLWGT), ALLOCATABLE :: ALLWGTS(:)
1339  LOGICAL :: L_MASTER = .true.
1340  LOGICAL :: L_READ = .false.
1341  LOGICAL :: L_WRITE = .false.
1342 #endif
1343 #ifdef W3_SCRIPNC
1344  INTEGER :: IMPROC_ASSIGN
1345  CHARACTER(LEN=80) :: interp_file1, interp_file_test
1346  CHARACTER(LEN=3) :: cdst, csrc
1347  LOGICAL, ALLOCATABLE :: LGRDREAD(:,:)
1348  LOGICAL, ALLOCATABLE :: LGRDWRITE(:,:)
1349  INTEGER :: NGRDRANK(2)
1350 #endif
1351 
1352  LOGICAL :: LSCRIP=.false. ! true if SCRIP switch is set,
1353  ! indicates that SCRIP code has
1354  ! been compiled into WW3
1355  LOGICAL :: LSCRIPNC=.false. ! true if SCRIPNC switch is set,
1356  ! indicates that SCRIP code has
1357  ! been compiled with netCDF
1358  ! into WW3
1359  LOGICAL :: L_STOP = .false. ! true if SCRIPNC switch is set
1360  ! and STOP_SCRIP file exists
1361  LOGICAL :: T38=.false. ! true if T38 switch is set.
1362  ! This logical is necessary
1363  ! since it isn't possible to
1364  ! have two switches disabling
1365  ! the same line of code.
1366  LOGICAL :: ALL_REGULAR=.true. ! true if all grids are
1367  ! regular grids
1368  LOGICAL :: DO_CHECKING=.false. ! true if we will be
1369  ! checking "old method" of
1370  ! computing weights vs.
1371  ! SCRIP method of computing
1372  ! weights.
1373  LOGICAL :: OLD_METHOD=.false. ! true if we will compute
1374  ! using "old method" (does
1375  ! not necessarily mean
1376  ! that this solution is
1377  ! utilized)
1378  LOGICAL :: LMPIBDI=.false. ! true if MPIBDI switch is set
1379  LOGICAL :: CALLED_SCRIP=.false.! true if SCRIP has been
1380  ! called for this processor
1381 
1382 
1383  INTEGER :: ITRI, IM1, IM2, IT, JT, IsFirst
1384  REAL :: DIST_MIN, DIST_MAX, eDist
1385 
1386 #ifdef W3_T
1387  CHARACTER(LEN=1), ALLOCATABLE :: MAPST(:,:)
1388 #endif
1389  !/
1390 #ifdef W3_T38
1391  CHARACTER (LEN=10) :: CDATE_TIME(3)
1392  INTEGER :: DATE_TIME(8)
1393  INTEGER :: ELAPSED_TIME, BEG_TIME(10), END_TIME
1394  INTEGER :: NMYOUT=42
1395  CHARACTER (LEN=14) :: CMYOUT="myout00000.lis"
1396  CHARACTER (LEN=5) :: CRANK
1397 #endif
1398 
1399 #ifdef W3_T38
1400  WRITE(crank, "(I5.5)") improc-1
1401  cmyout(6:10) = crank(1:5)
1402  OPEN (nmyout, file=cmyout, status="REPLACE")
1403 #endif
1404 #ifdef W3_S
1405  CALL strace (ient, 'WMGHGH')
1406 #endif
1407  !
1408 #ifdef W3_MPI
1409  CALL mpi_barrier(mpi_comm_mwave, ierr_mpi)
1410 #endif
1411 #ifdef W3_T38
1412  CALL date_and_time ( cdate_time(1), cdate_time(2), cdate_time(3), date_time)
1413  beg_time(1) = ((date_time(5)*60 + date_time(6))*60 + date_time(7))*1000 + date_time(8)
1414  WRITE(nmyout,*) "WMGHGH: START: 0 MSEC"
1415 #endif
1416 
1417 
1418  ! -------------------------------------------------------------------- /
1419  ! 0. Initializations / tests
1420  !
1421  IF ( .NOT. ALLOCATED(grdhgh) ) THEN
1422  IF ( improc.EQ.nmperr ) WRITE(mdse,1000)
1423  CALL extcde (1000)
1424  END IF
1425 
1426 #ifdef W3_MPIBDI
1427  lmpibdi=.true.
1428 #endif
1429 #ifdef W3_SCRIP
1430  IF (improc .EQ. 1) THEN
1431  l_master = .true.
1432  l_write = .true.
1433  ELSE
1434  l_master = .false.
1435  l_write = .false.
1436  ENDIF
1437 #endif
1438 #ifdef W3_SCRIPNC
1439  INQUIRE(file="SCRIP_STOP", exist=l_stop)
1440  improc_assign = 1
1441 #endif
1442  !
1443  !KRL Allocate helper arrays to enable bottleneck loop parallelization
1444  ALLOCATE ( nx_beg(nmproc), nx_end(nmproc), stat=istat )
1445  check_alloc_status( istat )
1446 #ifdef W3_MPIBDI
1447  ALLOCATE ( nx_size(nmproc), irq(2*nmproc), &
1448  mstat(mpi_status_size,2*nmproc), stat=istat )
1449  check_alloc_status( istat )
1450 #endif
1451  !
1452  !!HT:
1453  !!HT: Set up and initialize storage data structures ....
1454  !!HT:
1455 #ifdef W3_T38
1456  CALL date_and_time ( cdate_time(1), cdate_time(2), cdate_time(3), date_time)
1457  beg_time(2) = ((date_time(5)*60 + date_time(6))*60 + date_time(7))*1000 + date_time(8)
1458 #endif
1459  DO gdst=1, nrgrd
1460  DO gsrc=1, nrgrd
1461  IF ( hgstge(gdst,gsrc)%INIT ) THEN
1462  IF ( hgstge(gdst,gsrc)%NREC .NE. 0 ) THEN
1463  DEALLOCATE ( &
1464  hgstge(gdst,gsrc)%LJSEA , hgstge(gdst,gsrc)%NRAVG, &
1465  hgstge(gdst,gsrc)%IMPSRC, hgstge(gdst,gsrc)%ITAG , &
1466  hgstge(gdst,gsrc)%WGTH , hgstge(gdst,gsrc)%SHGH , &
1467  stat=istat )
1468  check_dealloc_status( istat )
1469  END IF
1470  IF ( hgstge(gdst,gsrc)%NSND .NE. 0 ) THEN
1471  DEALLOCATE ( &
1472  hgstge(gdst,gsrc)%ISEND , &
1473  stat=istat )
1474  check_dealloc_status( istat )
1475  END IF
1476  hgstge(gdst,gsrc)%NTOT = 0
1477  hgstge(gdst,gsrc)%NREC = 0
1478  hgstge(gdst,gsrc)%NRC1 = 0
1479  hgstge(gdst,gsrc)%NSND = 0
1480  hgstge(gdst,gsrc)%NSN1 = 0
1481  hgstge(gdst,gsrc)%NSMX = 0
1482  hgstge(gdst,gsrc)%INIT = .false.
1483  END IF
1484  END DO
1485  END DO
1486  gdst=-999 ! unset grid
1487  gsrc=-999 ! unset grid
1488 
1489 #ifdef W3_T38
1490  CALL date_and_time (cdate_time(1), cdate_time(2), cdate_time(3), date_time)
1491  end_time = ((date_time(5)*60 + date_time(6))*60 + date_time(7))*1000 + date_time(8)
1492  elapsed_time = end_time - beg_time(2)
1493  WRITE(nmyout,*) "WMGHGH, LOOP 1 TOOK ", elapsed_time, " MSEC"
1494 #endif
1495 
1496  ! -------------------------------------------------------------------- /
1497  ! 0.a Plan future behavior by setting logical variables.
1498 
1499 #ifdef W3_SCRIP
1500  lscrip=.true.
1501 #endif
1502 #ifdef W3_SCRIPNC
1503  lscripnc=.true.
1504 #endif
1505 #ifdef W3_T38
1506  t38=.true.
1507 #endif
1508 
1509  DO gdst=1, nrgrd
1510  IF ( grids(gdst)%GTYPE .NE. rlgtype .AND. &
1511  grids(gdst)%GTYPE .NE. smctype ) THEN
1512  !!Li Add SMCTYPE option into ALL_REGULAR case. JGLi20Nov2020
1513  all_regular=.false.
1514  END IF
1515  END DO
1516 
1517  ! Notes re: FLAGLL case: Old method calculates overlap area based on deg lat
1518  ! and deg lon. New method (SCRIP) calculates overlap area based on real
1519  ! distances. Therefore weights will not match for FLAGLL case, so we
1520  ! do not perform checking for FLAGLL case.
1521 
1522  IF ( (.NOT.flagll) .AND. all_regular .AND. lscrip ) THEN
1523  IF ( improc.EQ.nmperr ) &
1524  WRITE (mdse,'(/2A)')'We will check SCRIP calculations ', &
1525  'against old method of calculating weights.'
1526  do_checking=.true.
1527  END IF
1528 
1529  IF (do_checking .OR. (.NOT.lscrip)) old_method=.true.
1530 
1531  ! -------------------------------------------------------------------- /
1532  ! 0.b Check solution method
1533 
1534  IF ( (.NOT.lscrip) .AND. (.NOT.all_regular) .AND. &
1535  (nrgrd.GT.1) ) THEN
1536  IF ( improc.EQ.nmperr ) &
1537  WRITE (mdse,'(/3A)') ' *** ERROR WMGHGH: ', &
1538  'IRREGULAR or UNSTRUCTURED grid detected: this requires ', &
1539  'SCRIP switch.'
1540  CALL extcde ( 999 )
1541  END IF
1542 
1543  !
1544  ! -------------------------------------------------------------------- /
1545  ! 1. Set boundary distance maps
1546  ! 1.a Check if needed
1547  !
1548  !!HT: FLGBDI is a flag set in WMMDATMD to .FALSE. and is used to identify
1549  !!HT: if the boundary distance maps have been initialized
1550  !!HT:
1551  !!HT: For each individual grid a map is generated identifying the distance
1552  !!HT: to open boundaries (MAPBDI, saved in structure MDATA in WMMDATMD).
1553  !!HT: This map is used later to choose if more that 1 high-res grids
1554  !!HT: could provide data to a low-res grid. The high-res grid with data
1555  !!HT: furthest away from its own open boundary will be used.
1556 
1557 #ifdef W3_SCRIPNC
1558  IF (.NOT. l_stop) THEN ! Do not need MAPBDI if going to stop after generating mappings
1559 #endif
1560  IF ( .NOT. flgbdi ) THEN
1561  !
1562  IF ( flagll ) THEN
1563  factor = radius * dera
1564  !notes: was FACTOR = RADIUS / 360. (bug fix)
1565  ELSE
1566  factor = 1.
1567  END IF
1568  !
1569 #ifdef W3_T
1570  WRITE (mdst,9010)
1571 #endif
1572  !
1573  ! 1.b Loop over grids
1574  !
1575 #ifdef W3_T38
1576  CALL date_and_time ( cdate_time(1), cdate_time(2), cdate_time(3), date_time)
1577  beg_time(3) = ((date_time(5)*60 + date_time(6))*60 + date_time(7))*1000 + date_time(8)
1578  elapsed_time = beg_time(3) - beg_time(1)
1579  WRITE(nmyout,*) "WMGHGH, BEGINNING BOTTLENECK LOOP AT ", elapsed_time, " MSEC"
1580 #endif
1581  DO gdst=1, nrgrd
1582 
1583 #ifdef W3_T38
1584  IF(improc.EQ.nmperr)WRITE(mdse,*)'GDST = ',gdst,' OUT OF ',nrgrd
1585 #endif
1586 
1587  CALL w3seto ( gdst, mdse, mdst )
1588  CALL w3setg ( gdst, mdse, mdst )
1589  CALL wmsetm ( gdst, mdse, mdst )
1590 
1591  ! IF ( GTYPE .EQ. UNGTYPE ) THEN
1592  ! IF ( IMPROC.EQ.NMPERR ) &
1593  ! WRITE (MDSE,'(/2A)') ' *** ERROR WMGHGH: ', &
1594  ! 'UNSTRUCTURED GRID SUPPORT NOT YET IMPLEMENTED ***'
1595  ! CALL EXTCDE ( 999 )
1596  ! END IF
1597 
1598  !
1599 #ifdef W3_T
1600  WRITE (mdst,9011) gdst, grank(gdst), nbi
1601 #endif
1602  !
1603  ! -------------------------------------------------------------------- /
1604  ! Inconsistent RANK vs NBI (warning message)
1605  ! This was an error, now changed to a warning (see notes section)
1606  IF ( (grank(gdst).NE.1) .AND. (nbi.EQ.0) ) THEN
1607  IF ( improc.EQ.nmperr ) &
1608  WRITE (mdse,'(/2A)') ' WARNING in WMGHGH: ', &
1609  'NBI=0 AND RANK > 1 '
1610  END IF
1611 
1612  ! -------------------------------------------------------------------- /
1613  ! 1.c NBI=0, so computations not needed (test output only)
1614  !
1615  IF ( (nbi.EQ.0) .OR. (grank(gdst).EQ.1) ) THEN
1616  ! (then do nothing except test output)
1617 #ifdef W3_T
1618  WRITE (mdst,9012)
1619 #endif
1620 
1621  ! -------------------------------------------------------------------- /
1622  ! 1.d NBI>0, Generate map with distances to boundary.
1623 
1624  !!HT: Initialize MAPBDI
1625  !!HT: 0. for active boundary points
1626  !!HT: -1. for points that are not considered at all (rescaled for test
1627  !!HT: output only, only negative value is essentially later).
1628  !!HT: -2. for points that still need to be processed.
1629 
1630  ELSE
1631 
1632  IF(improc.EQ.nmperr)WRITE(mdse,'(A)') &
1633  ' Generating map with distances to boundary.'
1634  ! for purposes of screen output, would be useful to wait for other processors to catch up here...(if mpibdi switch used)
1635  ALLOCATE ( mdatas(gdst)%MAPBDI(ny,nx), stat=istat )
1636  check_alloc_status( istat )
1637  mapbdi => mdatas(gdst)%MAPBDI
1638  !
1639  !KRL Set up ranges for X. If not MPIBDI, just 1 to NX
1640  nx_beg(improc) = 1
1641  nx_end(improc) = nx
1642 #ifdef W3_MPIBDI
1643  nx_beg(1) = 1
1644  IF ( nmproc .EQ. 1 ) THEN
1645  nx_end(1) = nx
1646  nx_size(1) = nx
1647  ELSE
1648  nx_rem = mod( nx, nmproc )
1649  nx_size(1) = nx / nmproc
1650  IF (nx_rem .GT. 0) nx_size(1) = nx_size(1) + 1
1651  nx_end(1) = nx_beg(1) + nx_size(1) - 1
1652  DO im = 2, nmproc
1653  nx_beg(im) = nx_end(im-1) + 1
1654  nx_size(im) = nx / nmproc
1655  IF (im .LE. nx_rem) nx_size(im) = nx_size(im) + 1
1656  nx_end(im) = nx_beg(im) + nx_size(im) - 1
1657  nx_size(im-1) = nx_size(im-1) * ny
1658  END DO
1659  nx_size(nmproc) = nx_size(nmproc) * ny
1660  END IF
1661 #endif
1662  !KRL Setup complete
1663  !
1664  ! -------------------------------------------------------------------- /
1665  ! Loop to determine MAPBDI
1666  ! -------------------------------------------------------------------- /
1667 
1668  IF(improc.EQ.nmperr)WRITE(mdse,'(A)') &
1669  'Starting MAPBDI 1st loop.'
1670 
1671  DO idst=nx_beg(improc), nx_end(improc)
1672  IF(mod(idst,250).EQ.0)THEN
1673  IF(lmpibdi)THEN
1674  WRITE(mdse,'(4x,3(A,I5))')&
1675  'processing column ',idst,' out of ',nx, &
1676  ' on processor ',improc
1677  ELSEIF(improc.EQ.nmperr)THEN
1678  WRITE(mdse,'(4x,2(A,I5))')&
1679  'processing column ',idst,' out of ',nx
1680  ENDIF
1681  ENDIF
1682  DO jdst=1, ny
1683  IF ( mapsta(jdst,idst) .EQ. 0 ) THEN ! (excluded point)
1684  mapbdi(jdst,idst) = -1. / sig(1) * dtmax ! new (bug fix)
1685  ELSE IF ( abs(mapsta(jdst,idst)) .EQ. 2 ) THEN
1686  ! (boundary point)
1687  mapbdi(jdst,idst) = 0.
1688  ELSE ! ABS(MAPSTA)=1 (sea point)
1689  mapbdi(jdst,idst) = 1.0e+10
1690  ENDIF ! IF MAPSTA
1691  END DO ! DO JDST...
1692  END DO ! DO IDST...
1693 
1694  ! -------------------------------------------------------------------- /
1695 
1696  IF(improc.EQ.nmperr)WRITE(mdse,'(A)') &
1697  'Starting MAPBDI 2nd loop.'
1698 
1699  DO ibnd=1,nx
1700  IF ( (mod(ibnd,25).EQ.0) .AND. &
1701  (improc.EQ.nmperr) ) THEN
1702  WRITE(mdse,'(4x,2(A,I5))') &
1703  'bnd. point ',ibnd,' out of ',nx
1704  ENDIF
1705  DO jbnd=1,ny
1706  IF ( abs(mapsta(jbnd,ibnd)) .EQ. 2 ) THEN
1707  ! (boundary point)
1708 #ifdef W3_OMPH
1709  !$OMP PARALLEL DO PRIVATE(IDST,JDST,DD),SCHEDULE(DYNAMIC)
1710 #endif
1711  DO idst=nx_beg(improc), nx_end(improc)
1712  DO jdst=1, ny
1713  IF (abs(mapsta(jdst,idst)) .EQ. 1) THEN
1714  !....find distance to this boundary point.
1715  dd=factor*w3dist(flagll,real(xgrd(jdst,idst)), &
1716  REAL(YGRD(JDST,IDST)),REAL(XGRD(JBND,IBND)), &
1717  REAL(YGRD(JBND,IBND)))
1718 
1719  ! Notes: The origin of "0.58 * GRAV" is to translate from distance (in meters)
1720  ! to time (in seconds) required for a wave to travel from the boundary to point
1721  ! JDST,IDST based on a specific group velocity 0.58*grav would be the group
1722  ! velocity of a 7.3 s wave in deep water. Significance of T=7.3 s is explained
1723  ! in notes by HT below.
1724 
1725  dd=dd/ ( 0.58 * grav )
1726  mapbdi(jdst,idst)=min(mapbdi(jdst,idst),dd)
1727  ENDIF
1728  END DO ! DO JDST
1729  END DO ! DO IDST
1730 #ifdef W3_OMPH
1731  !$OMP END PARALLEL DO
1732 #endif
1733  ENDIF ! (if BND point)
1734 
1735  END DO ! DO JBND
1736  END DO ! DO IBND
1737 
1738  IF(improc.EQ.nmperr)WRITE(mdse,'(A)') &
1739  'Finished MAPBDI 2nd loop.'
1740 
1741  ! -------------------------------------------------------------------- /
1742 
1743 #ifdef W3_MPIBDI
1744  !KRL Exchange (Note: for efficiency, post receives first)
1745  !KRL MPI_ALLGATHERV would do this, but freezes for PGI and open_mpi
1746  !KRL This suggests they use blocking SEND/RECV, so this is faster anyway and less implementation-dependent
1747  nrq = 0
1748  DO im = 1, nmproc
1749  IF ( im .NE. improc ) THEN
1750  nrq = nrq + 1
1751  tag = nmproc * im + improc
1752  CALL mpi_irecv ( mapbdi(1,nx_beg(im)), nx_size(im), mpi_real, im - 1, tag, mpi_comm_mwave, &
1753  irq(nrq), ierr_mpi )
1754  END IF
1755  END DO
1756  DO im = 1, nmproc
1757  IF ( im .NE. improc ) THEN
1758  nrq = nrq + 1
1759  tag = nmproc * improc + im
1760  CALL mpi_isend( mapbdi(1,nx_beg(improc)), nx_size(improc), mpi_real, im - 1, tag, mpi_comm_mwave, &
1761  irq(nrq), ierr_mpi )
1762  END IF
1763  END DO
1764  CALL mpi_waitall( nrq, irq, mpi_status_ignore, ierr_mpi )
1765  CALL mpi_barrier ( mpi_comm_mwave, ierr_mpi )
1766 #endif
1767 
1768  IF(improc.EQ.nmperr)WRITE(mdse,'(A/)') &
1769  ' Finished generating map with distances to boundary.'
1770 
1771  !...notes regarding old method of doing what we just did
1772  !!HT:
1773  !!HT: (1)
1774  !!HT:
1775  !!HT: CHANGE array is used to identify grid points that still need to
1776  !!HT: be processed, and that are adjacent to points that have been
1777  !!HT: processed. Only those points can be updated in this step of the
1778  !!HT: loop started above here. The two loops below set the CHANGE array.
1779  !!HT:
1780  !!HT: (2)
1781  !!HT:
1782  !!HT: CHANGD identify if more points have been updated
1783  !!HT:
1784  !!HT: STX and STY are partial normalized distances, defined as the
1785  !!HT: physical distance Delta Y ( FACTOR * SY ) and Delta X
1786  !!HT: ( FACTOR * SX * XLAT(JDST) ), devided by the sistance traveled,
1787  !!HT: which is CgMAX * DTMAX. CgMAX is approximately 1.15 * CgDEEP,
1788  !!HT: or 1.15 * 0.5 * C_DEEP = 0.58 * GRAV / SIG(1). Since SIG(1) and
1789  !!HT: DTMAX may vary, these two factors are not included in MAPBDI.
1790  !!HT:
1791  !!HT: This defines MAPBDI similar to an inverse CFL number.
1792  !!HT:
1793  !!HT: (3)
1794  !!HT:
1795  !!HT: ERROR : Should be CLAT(JDST), not CLATI(JDST) : "STX = FACTOR * SX * CLATI(JDST) / ( 0.58 * GRAV )"
1796 
1797  ! 1.e Test output
1798  !
1799  !!HT: Note that SIG(1) and DTMAX are included here so that the map defines
1800  !!HT: how many time steps DTMAX it takes to reach this place.
1801 
1802 #ifdef W3_T
1803  WRITE (mdst,9013)
1804  DO jdst=ny,1 , -1
1805  WRITE (mdst,9014) nint(mapbdi(jdst,:)*sig(1)/dtmax)
1806  END DO
1807 #endif
1808  !
1809  END IF
1810  END DO
1811  flgbdi = .true.
1812  END IF
1813 #ifdef W3_SCRIPNC
1814  END IF
1815 #endif
1816  !
1817  ! -------------------------------------------------------------------- /
1818  ! 2. Data sources for reconcilliation
1819  ! 2.a Loop over grids, processing check
1820  !
1821 
1822  !!HT: GRDHGH(GDST,0) was set in WMGLOW to identify how many grids may
1823  !!HT: contribute from higher ranks to the present grid (GDST).
1824 
1825  ALLOCATE ( i1(nrgrd,nmproc), i2(nrgrd,nmproc), &
1826  i3(nrgrd), i4(nrgrd), stat=istat )
1827  check_alloc_status( istat )
1828 
1829 #ifdef W3_DIST
1830  ltag0 = 0
1831 #endif
1832 
1833 #ifdef W3_SCRIPNC
1834  ! If reading/writing SCRIP files, need to determine in advance which it is to avoid race condition:
1835  ! Processor writing file before other processor can check for it
1836  ngrdrank = shape(grdhgh)
1837  ALLOCATE( lgrdread(ngrdrank(1)-1, ngrdrank(2)), stat=istat )
1838  check_alloc_status( istat )
1839  ALLOCATE(lgrdwrite(ngrdrank(1)-1, ngrdrank(2)), stat=istat )
1840  check_alloc_status( istat )
1841  DO gdst=1, nrgrd
1842  DO jj = 1, grdhgh(gdst,0)
1843  IF ( grdhgh(gdst,0) .EQ. 0 ) THEN
1844  ! If no remap, then no file
1845  lgrdread(gdst,jj) = .false.
1846  lgrdwrite(gdst,jj) = .false.
1847  ELSE
1848  gsrc = grdhgh(gdst,jj)
1849  interp_file1 = "rmp_src_to_dst_conserv_xxx_xxx.nc"
1850  WRITE(cdst, "(I3.3)") gdst
1851  WRITE(csrc, "(I3.3)") gsrc
1852  interp_file1(24:26) = csrc
1853  interp_file1(28:30) = cdst
1854  INQUIRE(file=interp_file1, exist=l_read)
1855  ! At this point, file either exists already (L_READ = .TRUE.) or needs to be written
1856  lgrdread(gdst,jj) = l_read
1857  lgrdwrite(gdst,jj) = .NOT. l_read
1858  END IF
1859  END DO
1860  END DO
1861 #endif
1862 #ifdef W3_MPI
1863  IF (lscripnc) CALL mpi_barrier(mpi_comm_mwave, ierr_mpi)
1864 #endif
1865 
1866  lowrank_grid : DO gdst=1, nrgrd
1867 
1868 #ifdef W3_T38
1869  CALL date_and_time ( cdate_time(1), cdate_time(2), cdate_time(3), date_time)
1870  beg_time(2) = ((date_time(5)*60 + date_time(6))*60 + date_time(7))*1000 + date_time(8)
1871  elapsed_time = beg_time(2) - beg_time(1)
1872  WRITE(nmyout,*) "WMGHGH, LOOP LOWRANK_GRID, GDST= ", gdst, " START: ", elapsed_time, " MSEC"
1873 #endif
1874 
1875  ! Test output
1876 #ifdef W3_T
1877  WRITE (mdst,9020) gdst, grdhgh(gdst,0)
1878 #endif
1879 #ifdef W3_SCRIP
1880  IF ( improc.EQ.nmperr.AND.t38 )WRITE(mdst,*)'GDST = ',gdst,' OUT OF ',nrgrd
1881 #endif
1882 
1883  !
1884  IF ( grdhgh(gdst,0) .EQ. 0 ) THEN ! no grids of higher rank than this
1885  ! one.
1886 #ifdef W3_T
1887  WRITE (mdst,9021)
1888 #endif
1889  ELSE ! processing required
1890 
1891  !
1892  ! 2.b Process grid
1893  ! 2.b.1 Preparations
1894  !
1895  !!HT: Grid I has higher rank grids covering it, we now set up MAPTST
1896  !!HT: MAPTST shows from which gid the data is averages.
1897  !!HT: INFLND inferred land points based on land in high-res grids.
1898  !!HT:
1899  CALL w3seto ( gdst, mdse, mdst )
1900  CALL w3setg ( gdst, mdse, mdst )
1901  CALL wmsetm ( gdst, mdse, mdst )
1902 
1903  ! W3SETG set ICLOSE for us, and we have determined that there is
1904  ! interaction between high and low rank. So this is a good point
1905  ! to check the closure type.
1906 
1907  IF ( iclose .EQ. iclose_trpl ) THEN
1908  IF ( improc.EQ.nmperr ) &
1909  WRITE(mdse,*)'SUBROUTINE WMGHGH IS'// &
1910  ' NOT YET ADAPTED FOR TRIPOLE GRIDS. STOPPING NOW.'
1911  CALL extcde ( 1 )
1912  END IF
1913 
1914  ALLOCATE ( maptst(ny,nx), inflnd(ny,nx), stat=istat )
1915  check_alloc_status( istat )
1916  maptst = 0
1917  inflnd = 0
1918 
1919  !################################################################
1920  ! Start new block of code: Calculate weights by calling SCRIP interface
1921  !################################################################
1922 
1923  ! Notes on grid variables:
1924  ! GRIDS(GSRC)%{grid variable} (src grid, high rank, high resolution grid)
1925  ! GRIDS(GDST)%{grid variable} (dst grid, low rank, low resolution grid)
1926 
1927  ! At this point, we are working on a particular low rank (dst) grid.
1928  ! We will save our weight information in the structure "ALLWGTS".
1929  ! For this dst grid, it is possible to have many src grids. That is
1930  ! why we store it this way.
1931  ! First, we ALLOCATE ALLWGTS from 1 up to the largest value of all
1932  ! the possible source grids. This will be referenced as "GSRC"
1933  ! Not every value of GSRC will be filled (e.g. "1" usually isn't filled)
1934  ! but since we are doing this as a derived data type, we are still
1935  ! efficient in terms of memory usage.
1936  ! Inside SCRIP interface, we have:
1937  ! type weight_data
1938  ! integer (kind=int_kind) :: n ! number of weights for
1939  ! dst cell, formerly npnts(:)
1940  ! real (kind=dbl_kind), allocatable :: w(:) ! weights, sized by n,
1941  ! formerly wxwy(:,:)
1942  ! integer (kind=int_kind), allocatable :: k(:) ! source grid cells,
1943  ! sized by n, formerly KSRC(:,:)
1944  ! end type weight_data
1945  ! ....
1946  ! type(weight_data), allocatable :: WGTDATA(:)
1947  ! ....
1948  ! ALLOCATE ( WGTDATA(grid2_size), STAT=ISTAT ) ! grid2=destination grid
1949  ! CHECK_ALLOC_STATUS ( ISTAT )
1950 
1951 #ifdef W3_SCRIP
1952  njdst=ny
1953  nidst=nx
1954  ALLOCATE ( allwgts(maxval(grdhgh)), stat=istat )
1955  check_alloc_status( istat )
1956 #endif
1957 
1958  ! Next, we loop through the src grids for the dst grid that we are working on.
1959 #ifdef W3_SCRIP
1960  DO jj=1, grdhgh(gdst,0)
1961 #endif
1962 #ifdef W3_T38
1963  CALL date_and_time ( cdate_time(1), cdate_time(2), cdate_time(3), date_time)
1964  beg_time(3) = ((date_time(5)*60 + date_time(6))*60 + date_time(7))*1000 + date_time(8)
1965  elapsed_time = beg_time(3) - beg_time(1)
1966  WRITE(nmyout,*) "WMGHGH, LOOP JJ= ", jj, " START: ", elapsed_time, " MSEC"
1967 #endif
1968 
1969 #ifdef W3_SCRIP
1970  gsrc = grdhgh(gdst,jj)
1971  nisrc=grids(gsrc)%NX
1972  njsrc=grids(gsrc)%NY ! only needed for diagnostics
1973 #endif
1974 
1975  ! Next, we call SCRIP for this src grid.
1976  ! Conditions for calling SCRIP are:
1977  ! 1) Not using L_STOP: in this case, all processes need all the weight
1978  ! information, so all processes need to call SCRIP for all grid pairs
1979  ! OR
1980  ! 2) Using L_STOP, writing .nc files and not reading .nc files. With
1981  ! L_STOP, different processors are doing different things, and so
1982  ! have different settings for L_WRITE. L_READ is the same for all
1983  ! processors, since it is simply based on whether the file already
1984  ! exists.
1985 
1986 #ifdef W3_SCRIPNC
1987  interp_file1 = "rmp_src_to_dst_conserv_xxx_xxx.nc"
1988  WRITE(cdst, "(I3.3)") gdst
1989  WRITE(csrc, "(I3.3)") gsrc
1990  interp_file1(24:26) = csrc
1991  interp_file1(28:30) = cdst
1992  l_read = lgrdread(gdst, jj)
1993 #endif
1994 #ifdef W3_T38
1995  CALL date_and_time ( cdate_time(1), cdate_time(2), cdate_time(3), date_time)
1996  beg_time(4) = ((date_time(5)*60 + date_time(6))*60 + date_time(7))*1000 + date_time(8)
1997  elapsed_time = beg_time(3) - beg_time(1)
1998  WRITE(nmyout,*) "WMGHGH, SCRIP WRAPPER START: ", elapsed_time, " MSEC"
1999 #endif
2000 #ifdef W3_SCRIPNC
2001  IF (l_stop) l_write = (improc .EQ. improc_assign)
2002 #endif
2003 
2004 #ifdef W3_SCRIPNC
2005  IF(l_stop.AND.l_read)THEN
2006  IF ( improc.EQ.nmperr ) &
2007  WRITE(mdse,'(A)')'ERROR: You should either have SCRIP_STOP '// &
2008  'or remapping (.nc) files. Not both. We will exit now.'
2009  CALL extcde (505)
2010  ENDIF
2011 #endif
2012 
2013 #ifdef W3_SCRIP
2014  called_scrip=.false. ! initialize
2015 #endif
2016 
2017 #ifdef W3_SCRIPNC
2018  IF ((.NOT. l_stop) .OR. ((.NOT. l_read) .AND. l_write)) THEN
2019 #endif
2020 #ifdef W3_SCRIP
2021  IF (l_stop) THEN ! we are sending different grids to different processors
2022  WRITE(mdse,'(A,2(I5),A,I5)')'Calling SCRIP for GSRC,GDST = ', &
2023  gsrc,gdst,' on processor ',improc
2024  ELSEIF(improc.EQ.nmperr)THEN
2025  WRITE(mdse,'(A,2(I5))')'Calling SCRIP interface for GSRC,GDST = ', &
2026  gsrc,gdst
2027  ENDIF
2028  CALL scrip_wrapper (gsrc, gdst, &
2029  grids(gsrc)%MAPSTA,grids(gsrc)%MAPST2,flagll, &
2030  grids(gsrc)%GRIDSHIFT,l_write,l_read,t38)
2031  called_scrip=.true.
2032 #endif
2033 #ifdef W3_SCRIPNC
2034  END IF
2035 #endif
2036 #ifdef W3_SCRIP
2037  CALL flush(mdse)
2038 #endif
2039 #ifdef W3_SCRIPNC
2040  IF (l_stop) THEN
2041  IF (.NOT. l_read) THEN
2042  improc_assign = improc_assign + 1
2043  IF (improc_assign .GT. nmproc) improc_assign = 1
2044  IF(called_scrip)THEN ! we called scrip_wrapper, so we need
2045  ! to deallocate before leaving
2046  dst_grid_size=nidst*njdst
2047  DO kdst=1,dst_grid_size
2048  DEALLOCATE(wgtdata(kdst)%W, stat=istat )
2049  check_dealloc_status( istat )
2050  DEALLOCATE(wgtdata(kdst)%K, stat=istat )
2051  check_dealloc_status( istat )
2052  END DO
2053  DEALLOCATE(wgtdata, stat=istat )
2054  check_dealloc_status( istat )
2055  END IF
2056  cycle ! cycle out of this loop : DO JJ=1, GRDHGH(GDST,0)
2057  END IF
2058  END IF
2059 #endif
2060 #ifdef W3_T38
2061  CALL date_and_time (cdate_time(1), cdate_time(2), cdate_time(3), date_time)
2062  end_time = ((date_time(5)*60 + date_time(6))*60 + date_time(7))*1000 + date_time(8)
2063  elapsed_time = end_time - beg_time(4)
2064  WRITE(nmyout,*) "WMGHGH, SCRIP WRAPPER, GSRC= ", gsrc, " TOOK ", elapsed_time, " MSEC"
2065 #endif
2066 
2067 #ifdef W3_SCRIP
2068  IF(.NOT.called_scrip)THEN ! we should not be here, since we need
2069  ! WGTDATA(KDST)%N which is created by SCRIP
2070  IF ( improc.EQ.nmperr ) WRITE(mdse,'(A)')'ERROR: we '// &
2071  'should have cycled out by now. We will exit now.'
2072  CALL extcde (506)
2073  ENDIF
2074 #endif
2075 
2076  ! SCRIP has now created the data strucure "WGTDATA" and stored the weights
2077  ! in it. However, this is only for the present src grid. We want to store the
2078  ! data for all the src grids. Thus, we use a new data structure of type
2079  ! "ALLWGT" to store this data. First though, we need to ALLOCATE it:
2080  ! (note: "k" is equivalent to isea, but includes *all* points)
2081 
2082 #ifdef W3_SCRIP
2083  dst_grid_size=nidst*njdst
2084  ALLOCATE(allwgts(gsrc)%WGTDATA(dst_grid_size),stat=istat)
2085  check_alloc_status( istat )
2086  DO kdst=1,dst_grid_size
2087  ALLOCATE(allwgts(gsrc)%WGTDATA(kdst) &
2088  %W(wgtdata(kdst)%N),stat=istat)
2089  check_alloc_status( istat )
2090  ALLOCATE(allwgts(gsrc)%WGTDATA(kdst) &
2091  %K(wgtdata(kdst)%N),stat=istat)
2092  check_alloc_status( istat )
2093  END DO
2094 #endif
2095 
2096  ! Now that we have it allocated, we can just copy WGTDATA into ALLWGTS
2097 
2098  ! Notes re: short and long way to do this:
2099  ! pgf90 on IBM Opteron, gfortran, g95, xlf, all tested ok with "short method"
2100  ! pgf90 on our linux workstations (Intel) requires the "long method"
2101  ! (possible compiler bug)
2102  ! ALLWGTS(GSRC)%WGTDATA = WGTDATA !short method
2103 
2104  ! BEGIN long method for filling derived data type "ALLWGTS"
2105 
2106 #ifdef W3_SCRIP
2107  DO kdst=1,dst_grid_size
2108  allwgts(gsrc)%WGTDATA(kdst)%N=wgtdata(kdst)%N
2109  allwgts(gsrc)%WGTDATA(kdst)%NR0=wgtdata(kdst)%NR0
2110  allwgts(gsrc)%WGTDATA(kdst)%NR2=wgtdata(kdst)%NR2
2111  allwgts(gsrc)%WGTDATA(kdst)%NRL=wgtdata(kdst)%NRL
2112  DO ipnt=1,wgtdata(kdst)%N
2113  allwgts(gsrc)%WGTDATA(kdst)%W(ipnt) &
2114  =wgtdata(kdst)%W(ipnt)
2115  allwgts(gsrc)%WGTDATA(kdst)%K(ipnt) &
2116  =wgtdata(kdst)%K(ipnt)
2117  END DO
2118  END DO
2119 #endif
2120 
2121  ! END long method for filling derived data type "ALLWGTS"
2122 
2123  ! We're done with WGTDATA, so we can DEALLOCATE it. This is important,
2124  ! since it will be allocated again the next time SCRIP is called.
2125 
2126 #ifdef W3_SCRIP
2127  DO kdst=1,dst_grid_size
2128  DEALLOCATE(wgtdata(kdst)%W, stat=istat )
2129  check_dealloc_status( istat )
2130  DEALLOCATE(wgtdata(kdst)%K, stat=istat )
2131  check_dealloc_status( istat )
2132  END DO
2133  DEALLOCATE(wgtdata, stat=istat )
2134  check_dealloc_status( istat )
2135 #endif
2136 
2137  ! Here's a "test output" block of code to demonstrate how the weights can
2138  ! be called up from ALLWGTS...and to verify that the data is stored properly.
2139  ! (again note that "k" is equivalent to isea, but includes *all* points)
2140 
2141 #ifdef W3_SCRIP
2142  IF(t38)THEN
2143  WRITE(mdst,'(/2A)')' XDST YDST ', &
2144  ' XSRC YSRC WXWY'
2145  DO jdst=1,njdst
2146  DO idst=1,nidst
2147  kdst=(jdst-1)*nidst+idst
2148  xdst=real(grids(gdst)%XGRD(jdst,idst))
2149  ydst=real(grids(gdst)%YGRD(jdst,idst))
2150  DO ipnt=1,allwgts(gsrc)%WGTDATA(kdst)%N
2151  ksrc=allwgts(gsrc)%WGTDATA(kdst)%K(ipnt)
2152  jsrc=int((ksrc-1)/nisrc)+1
2153  isrc=ksrc-(jsrc-1)*nisrc
2154  xsrc=real(grids(gsrc)%XGRD(jsrc,isrc))
2155  ysrc=real(grids(gsrc)%YGRD(jsrc,isrc))
2156  wxwy=allwgts(gsrc)%WGTDATA(kdst)%W(ipnt)
2157  WRITE(mdst,'(5(1X,F12.5))')xdst,ydst,xsrc, &
2158  ysrc,wxwy
2159  END DO
2160  END DO
2161  END DO ! DO JDST=1,NJDST
2162  ENDIF ! IF(T38)THEN
2163 #endif
2164 
2165 #ifdef W3_T38
2166  CALL date_and_time (cdate_time(1), cdate_time(2), cdate_time(3), date_time)
2167  end_time = ((date_time(5)*60 + date_time(6))*60 + date_time(7))*1000 + date_time(8)
2168  elapsed_time = end_time - beg_time(3)
2169  WRITE(nmyout,*) "WMGHGH, LOOP JJ, GSRC= ", gsrc, " TOOK ", elapsed_time, " MSEC"
2170 #endif
2171 
2172 #ifdef W3_SCRIP
2173  END DO ! DO JJ=1, GRDHGH(GDST,0)
2174  gsrc = -999 ! unset grid
2175 #endif
2176 
2177  ! If SCRIPNC and L_STOP, then cycle LOWRANK_GRID loop and deallocate
2178  ! storage associated with dst grid.
2179 
2180 #ifdef W3_SCRIPNC
2181  IF (l_stop) THEN
2182  IF ( ALLOCATED(maptst) ) THEN
2183  DEALLOCATE ( maptst, stat=istat )
2184  check_dealloc_status( istat )
2185  END IF
2186  IF ( ALLOCATED(inflnd) ) THEN
2187  DEALLOCATE ( inflnd, stat=istat )
2188  check_dealloc_status( istat )
2189  END IF
2190  IF ( ALLOCATED(allwgts) ) THEN
2191  DO jj=1, grdhgh(gdst,0)
2192  gsrc = grdhgh(gdst,jj)
2193  IF ( ASSOCIATED(allwgts(gsrc)%WGTDATA) ) THEN
2194  DO kdst=1, dst_grid_size
2195 
2196  !#########################################################################################
2197  !menta: for some reason gfortran complains that these lines are too long. Unindenting them
2198  IF ( ALLOCATED(allwgts(gsrc)%WGTDATA(kdst)%W) ) THEN
2199  DEALLOCATE ( allwgts(gsrc)%WGTDATA(kdst)%W, stat=istat )
2200  check_dealloc_status( istat )
2201  END IF
2202  IF ( ALLOCATED(allwgts(gsrc)%WGTDATA(kdst)%K) ) THEN
2203  DEALLOCATE ( allwgts(gsrc)%WGTDATA(kdst)%K, stat=istat )
2204  check_dealloc_status( istat )
2205  END IF
2206  !#########################################################################################
2207  END DO
2208  DEALLOCATE ( allwgts(gsrc)%WGTDATA, stat=istat )
2209  check_dealloc_status( istat )
2210  NULLIFY ( allwgts(gsrc)%WGTDATA )
2211  END IF
2212  END DO
2213  DEALLOCATE ( allwgts, stat=istat )
2214  check_dealloc_status( istat )
2215  END IF
2216  cycle lowrank_grid
2217  END IF
2218 #endif
2219 
2220  !################################################################
2221  ! End new block of code: Calculate weights by calling SCRIP interface
2222  !################################################################
2223 
2224  ! 2.b.2 Find points used for boundary data in higher ranked grids
2225  !
2226  !!HT: These points are marked in MAPTST as negative values to assure
2227  !!HT: that the grid poits used for boundary data are not getting
2228  !!HT: averaged values from high-reswolution grids as that will result
2229  !!HT: in cyclic, possibly non-conservative updating.
2230  !!HT:
2231  !!HT: NBI2S has all necessary data set in WMGLOW as called before WMGHGH.
2232  !!HT:
2233  !!HT: JJ loop goes over grids that reviously have been identified as
2234  !!HT: getting data from the grid presently cousidered.
2235  !
2236  ! notes: The purpose of this is to identify points
2237  ! that should not be used in the averaging procedure. It is
2238  ! related to statement in Tolman (OM, 2008): "Second, Eq (7) is not
2239  ! applied to grid points in the low resolution grid that contribute
2240  ! to boundary data for the high resolution grid. This avoids cyclic
2241  ! updating of data between grids.
2242 
2243  ! notes: GRDHGH(GDST,0) is number of grids of higher rank than the present
2244  ! grid (GDST)
2245  ! GRDHGH(GDST,1...etc.) is the grid number
2246 
2247  ! notes: Setting MAPTST=negative here is probably overkill, since it means
2248  ! we will not have weights for this point. However, to change this,
2249  ! we would need a new variable to use in its place, since we need
2250  ! to mark the point for use in STMASK determination.
2251 
2252  DO jj=1, grdhgh(gdst,0)
2253  gsrc = grdhgh(gdst,jj)
2254  DO ib=1, SIZE(mdatas(gsrc)%NBI2S(:,1))
2255  IF ( mdatas(gsrc)%NBI2S(ib,1) .EQ. gdst ) THEN
2256  idst = mapsf(mdatas(gsrc)%NBI2S(ib,2),1)
2257  jdst = mapsf(mdatas(gsrc)%NBI2S(ib,2),2)
2258  maptst(jdst,idst) = - gsrc
2259  END IF
2260  END DO
2261  END DO
2262  gsrc = -999 ! unset grid
2263  !
2264  ! 2.b.3 Range of coverage per grid
2265 
2266  !!HT:
2267  !!HT: In this JJ loop, we go over all higher resolution grids to find
2268  !!HT: ranges that can be averaged to replace data in the 'I' (GDST) grid.!
2269  !!HT:
2270 
2271  ALLOCATE ( idstl(grdhgh(gdst,0)), idsth(grdhgh(gdst,0)), &
2272  jdstl(grdhgh(gdst,0)), jdsth(grdhgh(gdst,0)), &
2273  gridok(grdhgh(gdst,0)),bdist(grdhgh(gdst,0)), &
2274  stat=istat )
2275  check_alloc_status( istat )
2276 
2277  IF (old_method) THEN
2278  ALLOCATE (bdist_om(grdhgh(gdst,0)), stat=istat )
2279  check_alloc_status( istat )
2280  END IF
2281 
2282  !
2283  ! Notes: For case of lower ranked grid GDST being irregular, grid indices
2284  ! i and j do not correspond to x and y, so optimization
2285  ! by limiting search in manner of pre-curvilinear versions of
2286  ! WW3 is not appropriate.
2287  !
2288  IF ( (gtype .EQ. clgtype).or.(gtype .EQ. ungtype) ) THEN
2289 
2290  idstla = 1
2291  idstha = nx
2292  jdstla = 1
2293  jdstha = ny
2294 
2295  ELSE
2296 
2297  ! loop through higher ranked grids GSRC
2298 
2299  DO jj=1, grdhgh(gdst,0)
2300  gsrc = grdhgh(gdst,jj)
2301  !!HT:
2302  !!HT: XL,XH, and YL,YH and the low and high (X,Y) values of the grid box
2303  !!HT: in the grid 'I' fro which the high-res data needs to be averaged.
2304  !!HT: To be efficient, we compute a range of high-res grid point that
2305  !!HT: could be considered, rather than looking through the whole grid.
2306  !!HT: This will work only for the old grids, not for the newer curvilinear
2307  !!HT: and unstructured grids.
2308  !!HT:
2309  !!HT: This sets the range in the low-res grid to consider.
2310  !
2311  ! Notes (HLT): outer edges already taken off here ...
2312  ! will not work in a simple way for spherical grids,
2313  ! so we don't even try ....
2314  !
2315  ! Notes: SX and SY are only used in cases where GTYPE .NE. CLGTYPE,
2316  ! i.e. regular grids. In case of regular grids, SX and SY
2317  ! can be replaced with HPFAC HQFAC, if desired.
2318  !
2319  ! find upper and lower bounds of higher ranks grids
2320 
2321  IF ( (grids(gsrc)%GTYPE .EQ. clgtype) .OR. &
2322  (grids(gsrc)%GTYPE .EQ. ungtype) ) THEN
2323 
2324  ! Notes: in case of irregular grids, there is no obvious way to
2325  ! offset by dx/2 dy/2, so we omit that sliver (thus we increase
2326  ! search area slightly).
2327 
2328  xl=real(minval(grids(gsrc)%XGRD))
2329  yl=real(minval(grids(gsrc)%YGRD))
2330  xh=real(maxval(grids(gsrc)%XGRD))
2331  yh=real(maxval(grids(gsrc)%YGRD))
2332 
2333  ELSE
2334 
2335  xl = grids(gsrc)%X0 + 0.5 * grids(gsrc)%SX
2336  xh = grids(gsrc)%X0 + ( real(grids(gsrc)%NX) - 1.5 ) &
2337  * grids(gsrc)%SX
2338  yl = grids(gsrc)%Y0 + 0.5 * grids(gsrc)%SY
2339  yh = grids(gsrc)%Y0 + ( real(grids(gsrc)%NY) - 1.5 ) &
2340  * grids(gsrc)%SY
2341 
2342  ENDIF ! IF ( GRIDS(GSRC)%GTYPE .EQ. CLGTYPE )
2343 
2344  !
2345  ! find where this falls in the current (low) ranked grid
2346 
2347  IF ( flagll ) THEN
2348  idstl(jj) = 1
2349  idsth(jj) = nx
2350  ELSE
2351 
2352  ! Notes: from check "IF ( GTYPE .EQ. CLGTYPE ) THEN" above, we know that
2353  ! GTYPE .NE CLGTYPE....so it is safe to use SX SY etc here
2354 
2355  idstl(jj) = 2 + int( (xl-x0)/sx + 0.49 )
2356  idsth(jj) = 1 + int( (xh-x0)/sx - 0.49 )
2357  END IF
2358 
2359  jdstl(jj) = 2 + int( (yl-y0)/sy + 0.49 )
2360  jdsth(jj) = 1 + int( (yh-y0)/sy - 0.49 )
2361 
2362  idstl(jj) = max( 1 , idstl(jj) )
2363  idsth(jj) = min( nx , idsth(jj) )
2364  jdstl(jj) = max( 1 , jdstl(jj) )
2365  jdsth(jj) = min( ny , jdsth(jj) )
2366  !
2367 #ifdef W3_T
2368  WRITE (mdst,9022) gsrc, idstl(jj),idsth(jj), &
2369  jdstl(jj),jdsth(jj)
2370 #endif
2371  !
2372  END DO ! end loop through higher ranked grids
2373  gsrc = -999 ! unset grid
2374  !
2375 
2376  ! save the extremities of that set of high-ranked grids
2377  idstla = minval(idstl)
2378  idstha = maxval(idsth)
2379  jdstla = minval(jdstl)
2380  jdstha = maxval(jdsth)
2381 
2382  ENDIF ! IF ( (GTYPE .EQ. CLGTYPE ) .or. (GTYPE .EQ. UNGTYPE))
2383 
2384  ! loop through higher ranked grids
2385 
2386  !
2387  ! 2.b.4 Point by point check
2388  !
2389  ! Notes: We loop through all grids of higher rank
2390  ! GSRC=the grid number of the higher rank grid.
2391  ! NLMAX is used for dimensioning purposes.
2392  ! It is apparently using the ratio between the resolution
2393  ! of the low rank grid (GDST) and high rank grid (GSRC)
2394  ! Obviously, we cannot use this calculation for irregular grids.
2395 
2396  nlmax = 0
2397 #ifdef W3_SCRIP
2398  nlmax_scrip=0
2399 #endif
2400  DO jj=1, grdhgh(gdst,0)
2401  gsrc = grdhgh(gdst,jj)
2402 
2403  ! Notes: NLMAX is used to dimension TMPINT,TMPRL, and to set ITAG and LTAG
2404  ! (MPI case).
2405  ! As we remove more of the older code, it may turn out that
2406  ! NLMAX is no longer needed, in which case we can remove this
2407  ! block of code. For example, the weights data structure is introduced
2408  ! to WW3 already dimensioned.
2409 
2410  IF ( grids(gdst)%GTYPE .EQ. clgtype ) THEN
2411  dx_max_gdst=maxval(grids(gdst)%HPFAC)
2412  dy_max_gdst=maxval(grids(gdst)%HQFAC)
2413  ELSEIF ( grids(gdst)%GTYPE .EQ. rlgtype ) THEN
2414  dx_max_gdst=grids(gdst)%SX
2415  dy_max_gdst=grids(gdst)%SY
2416  ELSE
2417  isfirst=1
2418  dist_max=0
2419  dist_min=0
2420  DO itri=1,grids(gdst)%NTRI
2421  DO it=1,3
2422  IF (it.eq.3) THEN
2423  jt=1
2424  ELSE
2425  jt=it+1
2426  END IF
2427  im1=grids(gdst)%TRIGP(it,itri)
2428  im2=grids(gdst)%TRIGP(jt,itri)
2429  edist=w3dist(flagll, real(grids(gdst)%XGRD(1,im1)), &
2430  REAL(GRIDS(GDST)%YGRD(1,IM1)), &
2431  REAL(GRIDS(GDST)%XGRD(1,IM2)), REAL(GRIDS(GDST)%YGRD(1,IM2)))
2432  IF (isfirst.eq.1) THEN
2433  dist_max=edist
2434  dist_min=edist
2435  isfirst=0
2436  ELSE
2437  IF (edist.gt.dist_max) THEN
2438  dist_max=edist
2439  END IF
2440  IF (edist.lt.dist_min) THEN
2441  dist_min=edist
2442  END IF
2443  END IF
2444  END DO
2445  END DO
2446  dx_max_gdst=dist_max
2447  dy_max_gdst=dist_max
2448  END IF
2449 
2450  IF ( grids(gsrc)%GTYPE .EQ. clgtype ) THEN
2451  dx_min_gsrc=minval(grids(gsrc)%HPFAC)
2452  dy_min_gsrc=minval(grids(gsrc)%HQFAC)
2453  ELSEIF ( grids(gsrc)%GTYPE .EQ. rlgtype ) THEN
2454  dx_min_gsrc=grids(gsrc)%SX
2455  dy_min_gsrc=grids(gsrc)%SY
2456  ELSE
2457  isfirst=1
2458  dist_max=0
2459  dist_min=0
2460  DO itri=1,grids(gsrc)%NTRI
2461  DO it=1,3
2462  IF (it.eq.3) THEN
2463  jt=1
2464  ELSE
2465  jt=it+1
2466  END IF
2467  im1=grids(gsrc)%TRIGP(it,itri)
2468  im2=grids(gsrc)%TRIGP(jt,itri)
2469  edist=w3dist(flagll, real(grids(gsrc)%XGRD(1,im1)), &
2470  REAL(GRIDS(GSRC)%YGRD(1,IM1)), &
2471  REAL(GRIDS(GSRC)%XGRD(1,IM2)), REAL(GRIDS(GSRC)%YGRD(1,IM2)))
2472  IF (isfirst.eq.1) THEN
2473  dist_max=edist
2474  dist_min=edist
2475  isfirst=0
2476  ELSE
2477  IF (edist.gt.dist_max) THEN
2478  dist_max=edist
2479  END IF
2480  IF (edist.lt.dist_min) THEN
2481  dist_min=edist
2482  END IF
2483  END IF
2484  END DO
2485  END DO
2486  dx_min_gsrc=dist_min
2487  dy_min_gsrc=dist_min
2488  END IF
2489 
2490  ! notes: original code was much simpler:
2491  ! NLMAX = MAX ( NLMAX , (2+INT(SX/GRIDS(J)%SX+0.001)) * &
2492  ! (2+INT(SY/GRIDS(J)%SY+0.001)) )
2493 
2494  nlmax = max( nlmax , &
2495  (2+int(dx_max_gdst/dx_min_gsrc+0.001)) * &
2496  (2+int(dy_max_gdst/dy_min_gsrc+0.001)) )
2497 
2498 #ifdef W3_T38
2499  WRITE(mdst,*)'ratio 1 = ',(dx_max_gdst/dx_min_gsrc), &
2500  dx_max_gdst,dx_min_gsrc
2501  WRITE(mdst,*)'ratio 2 = ',(dy_max_gdst/dy_min_gsrc), &
2502  dy_max_gdst,dy_min_gsrc
2503  WRITE(mdse,*)'GSRC, NLMAX = ',gsrc,nlmax
2504 #endif
2505 
2506 #ifdef W3_SCRIP
2507  DO jdst=1, ny
2508  DO idst=1, nx
2509  kdst=(jdst-1)*nidst+idst
2510  nloc=allwgts(gsrc)%WGTDATA(kdst)%N
2511  nlmax_scrip=max(nlmax_scrip,nloc)
2512  END DO
2513  END DO
2514 #endif
2515 
2516  END DO ! DO JJ=1, GRDHGH(GDST,0)
2517  gsrc=-999 ! unset grid
2518 
2519  ! Notes regarding 3 possible scenarios:
2520  ! If only using SCRIP, then
2521  ! * set NLMAX=NLMAX_SCRIP here.
2522  ! * TMPRL_OM will not be created
2523  ! * TMPRL will be calculated using SCRIP
2524  ! If only using old method
2525  ! * NLMAX is already set, and SCRIP switch does not exist, so
2526  ! nothing is done here
2527  ! * both TMPRL and TMPRL_OM will be dimensioned
2528  ! * TMPRL_OM will be calculated
2529  ! * TMPRL_OM will be copied to TMPRL for use
2530  ! If using both methods ("DO_CHECKING")
2531  ! * set NLMAX=MAX(NLMAX, NLMAX_SCRIP) here.
2532  ! * both TMPRL_OM and TMPRL will be created
2533  ! * both will be calculated using the 2 methods, and
2534  ! checked against each other
2535  ! * the SCRIP version of weights (TMPRL) will be the ones used.
2536 
2537 #ifdef W3_SCRIP
2538  IF ( improc.EQ.nmperr.AND.t38 ) &
2539  WRITE(mdse,*) 'NLMAX,NLMAX_SCRIP=',nlmax,nlmax_scrip
2540  IF(do_checking)THEN
2541  nlmax = max(nlmax, nlmax_scrip)
2542  ELSE
2543  nlmax = nlmax_scrip
2544  ENDIF
2545  IF ( improc.EQ.nmperr.AND.t38 ) &
2546  WRITE(mdse,*) 'NEW NLMAX:',nlmax
2547 #endif
2548 
2549  IF(nlmax.GT.100)THEN
2550  WRITE(mdse,'(/A,I8)') &
2551  'WARNING: unusually large value for NLMAX : ',nlmax
2552  END IF
2553 
2554  nrtot = 0
2555  IF(old_method)THEN
2556  ALLOCATE ( tmpint_om(nx*ny,-4:nlmax), stat=istat )
2557  check_alloc_status( istat )
2558  ALLOCATE ( tmprl_om(nx*ny,0:nlmax), stat=istat )
2559  check_alloc_status( istat )
2560  ENDIF
2561  ALLOCATE ( tmpint(nx*ny,-4:nlmax), stat=istat )
2562  check_alloc_status( istat )
2563  ALLOCATE ( tmprl(nx*ny,0:nlmax), stat=istat )
2564  check_alloc_status( istat )
2565  ALLOCATE ( tmplog(nx*ny), stat=istat )
2566  check_alloc_status( istat )
2567  !
2568 #ifdef W3_DIST
2569  ALLOCATE ( ltag(nlmax), stat=istat )
2570  check_alloc_status( istat )
2571  DO jj=1, nlmax
2572  ltag(jj) = jj + ltag0
2573  END DO
2574 #endif
2575  !
2576  !!HT:
2577  !!HT: After the search range is set, we are actually searching in the
2578  !!HT: high-res grid. IDST, JDST are counters in the grid to which the
2579  !!HT: averaged data is to go. XA and YA are center locatons of target
2580  !!HT: grid. Necxt two loops over all relevant point in target grid.
2581  !!HT:
2582 
2583  ! Notes: This is the start of the large loop through the individual
2584  ! grid points of the low-rank grid.
2585  ! The checks below for JDST.LT.JDSTLA , IDST.LT.IDSTLA etc are to save
2586  ! time but will only be useful for the case of regular grids.
2587 
2588  lowrank_j : DO jdst=1, ny
2589  IF ( jdst.LT.jdstla .OR. jdst.GT.jdstha ) cycle
2590 
2591  lowrank_i : DO idst=1, nx
2592  IF ( idst.LT.idstla .OR. idst.GT.idstha ) cycle
2593  ! check that this is a sea point
2594  IF ( abs(mapsta(jdst,idst)) .NE. 1 ) cycle
2595  ! MAPTST: see Section 2.b.2 above
2596  IF ( maptst(jdst,idst) .LT. 0 ) cycle
2597  xa = real(xgrd(jdst,idst)) ! old code: X0 + REAL(IDST-1)*SX
2598  ya = real(ygrd(jdst,idst)) ! old code: Y0 + REAL(JDST-1)*SY
2599 
2600  !!HT: For each point in the target grid, loop over all relevant high-res
2601  !!HT: grid (JJ loop).
2602 
2603  nrok = 0
2604 
2605  ! notes: GRDHGH(GDST,0) is number of grids of higher rank than the present
2606  ! grid (GDST)
2607  ! GRDHGH(GDST,1...etc.) is the grid number
2608 
2609  DO jj=1, grdhgh(gdst,0)
2610  gsrc = grdhgh(gdst,jj)
2611 
2612 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2613  ! Start counting using old method
2614 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2615 
2616  ! Note for LLG: Assumption is made that the higher ranked grid
2617  ! cannot be global.
2618  !
2619  !!HT: Set search range in [candidate] high-res grid.
2620 
2621  ! Notes: The quantities XL YL XH YH apear to be a bounding box in
2622  ! index space for later searching within the high rank grid (or
2623  ! otherwise making computations from the high rank grid). They
2624  ! are the distance from the coarse grid point to the origin of
2625  ! the high rank grid, measured in grid cells of the high rank
2626  ! grid. So, they are the i and j values in the high rank
2627  ! bounding the low rank grid cell.
2628 
2629  IF (old_method)THEN
2630  ! ...then we do the counting using the old method
2631 
2632  ! Notes: Resulting "old method" variables are saved with "_OM" suffix.
2633 
2634  IF ( flagll ) THEN
2635  dxc = mod( 1080.+xa-grids(gsrc)%X0 , 360. )
2636  xl = 1. + (dxc-0.5*sx)/grids(gsrc)%SX
2637  xh = 1. + (dxc+0.5*sx)/grids(gsrc)%SX
2638  ELSE
2639  xl = 1. + (xa-grids(gsrc)%X0-0.5*sx)/grids(gsrc)%SX
2640  xh = 1. + (xa-grids(gsrc)%X0+0.5*sx)/grids(gsrc)%SX
2641  END IF
2642  yl = 1. + (ya-grids(gsrc)%Y0-0.5*sy)/grids(gsrc)%SY
2643  yh = 1. + (ya-grids(gsrc)%Y0+0.5*sy)/grids(gsrc)%SY
2644 
2645  isrcl = nint(xl+0.01)
2646  isrch = nint(xh-0.01)
2647  jsrcl = nint(yl+0.01)
2648  jsrch = nint(yh-0.01)
2649 
2650  IF ( isrcl.LT.1 .OR. isrch.GT.grids(gsrc)%NX .OR. &
2651  jsrcl.LT.1 .OR. jsrch.GT.grids(gsrc)%NY ) THEN
2652  ! dst point not in src grid, so go to next src grid
2653  gridok(jj) = .false. ! does this get used anywhere?
2654  cycle ! leave GSRC loop
2655  END IF
2656 
2657  !!HT: Loop over search range in high-res grid, ISRC and JSRC loops.
2658  !!HT: NR0_OM counts high-res grid points with MAPSTA=0, etc.
2659  !!HT: NRL_OM separately identifies explitcit land points.
2660  !!HT: BDIST_OM saves the boundary data from the source grid.
2661  !!HT:
2662 
2663  ! Notes: We appear to be searching for the smallest boundary distance and
2664  ! doing some counting
2665  ! Purpose of counting is unknown (for dimensioning?)
2666 
2667  ! Initialize
2668  nr0_om = 0 ! counter of MAPSTA=0 (indicates
2669  ! excluded point)
2670  nrl_om = 0 ! counter of MAPSTA=0 (indicates
2671  ! excluded point) and MAPST2=0
2672  ! (indicates land)
2673  nr1_om = 0 ! counter of |MAPSTA|=1
2674  ! (indicates sea point)
2675  nr2_om = 0 ! counter of |MAPSTA|=2
2676  ! (indicates boundary point)
2677  bdist_om(jj) = 9.99e33
2678 
2679  DO isrc=isrcl, isrch
2680  DO jsrc=jsrcl, jsrch
2681  IF (grids(gsrc)%MAPSTA(jsrc,isrc).EQ.0) THEN
2682  ! excluded point
2683  nr0_om = nr0_om + 1
2684 
2685  ! Notes: Q: What does MAPST2=0 indicate?
2686  ! A: MAPST2 is the "second grid status map"
2687  ! For disabled points (MAPSTA=0) , MAPST2 indicates land (0) or
2688  ! excluded (1). For sea and active boundary points, MAPST2 indicates
2689  ! a) ice coverage b) drying out of points c) land in moving grid or
2690  ! inferred land in nesting and d) masked in two-way nesting
2691 
2692  IF (grids(gsrc)%MAPST2(jsrc,isrc).EQ.0) &
2693  nrl_om = nrl_om + 1
2694  ELSE IF (abs(grids(gsrc)%MAPSTA(jsrc,isrc)) &
2695  .EQ.1) THEN ! sea point
2696  nr1_om = nr1_om + 1
2697 
2698  ! Notes: check against stored "distance to boundary point"
2699  ! This BDIST_OM array will be used later, when we select
2700  ! the high rank grid to average from.
2701 
2702  bdist_om(jj) = min( bdist_om(jj) , &
2703  mdatas(gsrc)%MAPBDI(jsrc,isrc) )
2704  ELSE IF (abs(grids(gsrc)%MAPSTA(jsrc,isrc)) &
2705  .EQ.2) THEN ! bnd point
2706  nr2_om = nr2_om + 1
2707  END IF
2708  END DO ! DO JSRC=JSRCL, JSRCH
2709  END DO ! DO ISRC=ISRCL, ISRCH
2710 
2711  END IF ! (if OLD_METHOD)
2712 
2713 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2714  ! Done with counting using old method.
2715 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2716 
2717 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2718  ! Start counting using new method
2719 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2720 
2721  ! Initialize
2722 
2723 #ifdef W3_SCRIP
2724  bdist(jj) = 9.99e33
2725 #endif
2726 
2727  ! Notes on variables used here:
2728  ! IDST, JDST given by loop, NIDST set above, the rest we need to set here
2729 
2730 #ifdef W3_SCRIP
2731  nisrc=grids(gsrc)%NX
2732  kdst=(jdst-1)*nidst+idst
2733 #endif
2734 
2735 #ifdef W3_SCRIP
2736  DO ipnt=1,allwgts(gsrc)%WGTDATA(kdst)%N
2737  ksrc=allwgts(gsrc)%WGTDATA(kdst)%K(ipnt)
2738  jsrc=int((ksrc-1)/nisrc)+1
2739  isrc=ksrc-(jsrc-1)*nisrc
2740  IF (abs(grids(gsrc)%MAPSTA(jsrc,isrc)).EQ.1) THEN
2741 #endif
2742  ! sea point
2743 #ifdef W3_SCRIP
2744  bdist(jj) = min( bdist(jj) , &
2745  mdatas(gsrc)%MAPBDI(jsrc,isrc) )
2746  ELSE
2747  IF ( improc.EQ.nmperr ) &
2748  WRITE(mdse,*) &
2749  'we masked non-sea points. (coding error)'
2750  CALL extcde ( 999 )
2751  END IF
2752  END DO
2753 #endif
2754 
2755  ! Pull NR0, etc. from storage...
2756 #ifdef W3_SCRIP
2757  nr0 = allwgts(gsrc)%WGTDATA(kdst)%NR0
2758 #endif
2759  ! counter of MAPSTA=0 (indicates excluded point)
2760 #ifdef W3_SCRIP
2761  nrl = allwgts(gsrc)%WGTDATA(kdst)%NRL
2762 #endif
2763  ! counter of MAPSTA=0 (indicates excluded point)
2764  ! and MAPST2=0 (indicates land)
2765 #ifdef W3_SCRIP
2766  nr1 = allwgts(gsrc)%WGTDATA(kdst)%N
2767 #endif
2768  ! counter of |MAPSTA|=1 (indicates sea point)
2769 #ifdef W3_SCRIP
2770  nr2 = allwgts(gsrc)%WGTDATA(kdst)%NR2
2771 #endif
2772  ! counter of |MAPSTA|=2 (indicates boundary point)
2773 
2774 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2775  ! Finished counting using new method.
2776 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2777 
2778  ! Compare results
2779  IF(do_checking)THEN
2780  ! then it is OK to compare with the values that we got using the old method
2781 #ifdef W3_T38
2782  WRITE(mdst,*)'STARTING TEST 1'
2783 #endif
2784  IF(nr0_om.NE.nr0)THEN
2785  IF ( improc.EQ.nmperr )WRITE (mdse,'(/1A,2(I8))') &
2786  ' *** ERROR WMGHGH: NR0_OM,NR0 = ',nr0_om,nr0
2787  CALL extcde ( 999 )
2788  ENDIF
2789  IF(nr1_om.NE.nr1)THEN
2790  IF ( improc.EQ.nmperr )WRITE (mdse,'(/1A,2(I8))') &
2791  ' *** ERROR WMGHGH: NR1_OM,NR1 = ',nr1_om,nr1
2792  CALL extcde ( 999 )
2793  ENDIF
2794  IF(nr2_om.NE.nr2)THEN
2795  IF ( improc.EQ.nmperr )WRITE (mdse,'(/1A,2(I8))') &
2796  ' *** ERROR WMGHGH: NR2_OM,NR2 = ',nr2_om,nr2
2797  CALL extcde ( 999 )
2798  ENDIF
2799  IF(nrl_om.NE.nrl)THEN
2800  IF ( improc.EQ.nmperr )WRITE (mdse,'(/1A,2(I8))') &
2801  ' *** ERROR WMGHGH: NRL_OM,NRL = ',nrl_om,nrl
2802  CALL extcde ( 999 )
2803  ENDIF
2804  IF(bdist_om(jj).NE.bdist(jj))THEN
2805  IF ( improc.EQ.nmperr ) &
2806  WRITE (mdse,'(/2A,2(F12.5))') &
2807  ' *** ERROR WMGHGH: ', &
2808  ' BDIST_OM(JJ),BDIST(JJ) = ', &
2809  bdist_om(jj),bdist(jj)
2810  CALL extcde ( 999 )
2811  ENDIF
2812 #ifdef W3_T38
2813  WRITE(mdst,*)'PASSED TEST 1'
2814 #endif
2815  END IF ! (if DO_CHECKING)
2816 
2817  ! Notes: We are done with the counting. If we didn't use SCRIP to get NR0,
2818  ! etc., then we need to set them using the _OM variables.
2819 
2820  IF(.NOT.lscrip)THEN
2821  nr0=nr0_om
2822  nr1=nr1_om
2823  nr2=nr2_om
2824  nrl=nrl_om
2825  bdist=bdist_om
2826  END IF
2827 
2828  ! Notes: Potential future improvement: for irregular grids, it would make
2829  ! more sense to use the overlapped area, rather than simply counting cells
2830  ! to decide on "inferred land". However, since grid cell size it typically
2831  ! fairly uniform locally, the current approach will suffice for now.
2832 
2833  ! Notes: This is the only place that the "NRL" "NR0" "NR1" and "NR2" variables
2834  ! are used directly. They affect MAPST2 indirectly below.
2835  ! The calculation itself is essentially "50% or more of the grid
2836  ! cells are land".
2837 
2838  IF ( nrl .GT. (nr0+nr1+nr2)/2 ) THEN
2839 
2840  ! Notes: This is not considered an OK grid (NROK is not incremented) and
2841  ! it is considered "inferred land"
2842 
2843  inflnd(jdst,idst) = 1
2844  ELSE
2845  gridok(jj) = nr1.GT.0 .AND. nr2.EQ.0
2846 
2847  ! Notes: for a grid cell to be considered "OK", we require that there is
2848  ! at least one sea point being used, and no boundary points being used
2849 
2850  IF ( gridok(jj) ) nrok = nrok + 1
2851  END IF
2852 
2853  END DO ! GSRC loop
2854  gsrc=-999 ! unset grid
2855 
2856  IF ( nrok .EQ. 0 ) THEN
2857 
2858  ! Notes: exit IDST loop since there are no "OK" source grid cells for this
2859  ! dst point. At this point, INFLND could be 1, but isn't necessarily 1
2860 
2861  cycle
2862 
2863  ELSE
2864 
2865  ! Notes: If any grids are OK for this dst point, then we override any prior
2866  ! setting of INFLD=1. Apparently this is for the situation of having some src
2867  ! grids giving INFLD=1 and another giving INFLD=0 for the same dst point.
2868  ! I wouldn't expect this to happen very often.
2869 
2870  inflnd(jdst,idst) = 0
2871 
2872  END IF
2873  !
2874  ! 2.b.5 Select source grid
2875  !
2876  ! Notes: It appears that we are selecting the high rank grid from
2877  ! which we will perform the averaging.
2878  ! The code is written such that the first higher rank
2879  ! grid that we find has the rank that we want, but isn't necessarily the
2880  ! grid that we want.
2881  ! Are grids necessarily in order of rank? If so, then we want the grid
2882  ! that is higher rank but of nearest rank to the present grid.
2883  ! Anyway, once we have decided on the grid rank that we want, we select
2884  ! the specific grid according to criterion: larger distance to
2885  ! boundary = better
2886  ! Keep in mind that this grid is selected for *this* (IDST,JDST) and not
2887  ! necesssarily for the next...
2888 
2889  jf = 0
2890 
2891  !!HT: Another loop over all high-res grid to decide which grid will
2892  !!HT: be used to average data. If more than 1 grids are available,
2893  !!HT: the boundary distance in the high-res grid, stored in BDIST is
2894  !!HT: used to make the choice.
2895 
2896  !!ER: Old logic was to select a grid that is of the "next rank up,
2897  !!ER: for which data is available". This was done by searching
2898  !!ER: from 1 to GRDHGH (remember that the available source grids
2899  !!ER: are in order of rank), and exiting when the rank increased.
2900  !!ER: The problem with selecting the "lowest rank grid with rank
2901  !!ER: greater than that of GDST" is that at this point, we have
2902  !!ER: no knowledge of what will be masked in that SRC grid, since
2903  !!ER: we haven't updated MAPSTA for that GSRC yet, based on what
2904  !!ER: points are covered by higher rank grids (in case of masking
2905  !!ER: computations). We can avoid this problem by reversing the
2906  !!ER: order of GSRC search (from highest rank to lowest rank of
2907  !!ER: higher rank). For example, grid 1 wants data from grid 2,
2908  !!ER: but just gets zeros because grid 2 is masked there, because
2909  !!ER: grid 2 is masked by grid 3 in Section 2.3.2 below. Going
2910  !!ER: directly to GSRC=3 for GDST=1 (skipping GSRC=2) avoids
2911  !!ER: this: the highest rank at that location will never be
2912  !!ER: masked by a higher rank grid.
2913 
2914  DO jj=grdhgh(gdst,0),1,-1
2915  !old DO JJ=1, GRDHGH(GDST,0) ! used before Aug 2014
2916 
2917  gsrc = grdhgh(gdst,jj)
2918 
2919  IF ( gridok(jj) ) THEN
2920  IF ( jf .EQ. 0 ) THEN ! we haven't already found a grid
2921  jf = gsrc ! now we have found a grid.
2922  jr = grank(gsrc)
2923  ! this is the rank that we want....the rank of the first grid that we find
2924  jd = bdist(jj) ! larger distance = better
2925  ELSE
2926  ! we already found a grid, but maybe this one is better
2927  IF ( grank(gsrc) .NE. jr ) EXIT
2928  ! this is not the rank that we want
2929  IF ( bdist(jj) .GT. jd ) THEN
2930  ! we like this grid better
2931  jf = gsrc
2932  jd = bdist(jj)
2933  END IF
2934  END IF
2935  END IF
2936  END DO
2937  gsrc=jf
2938 #ifdef W3_T38
2939  WRITE(mdst,'(A,2(I8),A,I8)')'For grid point IDST,JDST = ',idst,jdst,', we selected GSRC = ',gsrc
2940 #endif
2941 
2942  !!HT: Data for grid point IDST,JDST in the low-res grid will be taken from
2943  !!HT: high-res grid GSRC.
2944 
2945  maptst(jdst,idst) = gsrc
2946  !
2947  ! 2.b.6 Store data (temp)
2948  !
2949  ! Notes: This section is for calculations of weights for the
2950  ! area-weighted averaging.
2951 
2952  nrtot = nrtot + 1
2953  tmpint(nrtot,-4) = idst
2954  tmpint(nrtot,-3) = jdst
2955  tmpint(nrtot,-2) = mapfs(jdst,idst)
2956  tmpint(nrtot,-1) = gsrc
2957  tmprl(nrtot, 0) = jd * sig(1) / dtmax
2958 
2959  ! Notes: Calculation for XL YL XH YH is same as it was in section 2.b.4, so
2960  ! see notes in that section.
2961 
2962 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2963  !...Begin block of code for computing weights using old method
2964 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2965 
2966  IF (old_method)THEN
2967  ! it is OK to do the counting using the old method
2968  ! (These variables are saved with "_OM" suffix)
2969 
2970  DO itmp=-4,-1
2971  tmpint_om(nrtot,itmp)=tmpint(nrtot,itmp)
2972  END DO
2973  tmprl_om(nrtot,0)=tmprl(nrtot,0)
2974 
2975  IF ( flagll ) THEN
2976  dxc = mod( 1080.+xa-grids(gsrc)%X0 , 360. )
2977  xl = 1. + (dxc-0.5*sx)/grids(gsrc)%SX
2978  xh = 1. + (dxc+0.5*sx)/grids(gsrc)%SX
2979  ELSE
2980  xl = 1. + (xa-grids(gsrc)%X0-0.5*sx)/grids(gsrc)%SX
2981  xh = 1. + (xa-grids(gsrc)%X0+0.5*sx)/grids(gsrc)%SX
2982  END IF
2983  yl = 1. + (ya-grids(gsrc)%Y0-0.5*sy)/grids(gsrc)%SY
2984  yh = 1. + (ya-grids(gsrc)%Y0+0.5*sy)/grids(gsrc)%SY
2985 
2986  ! Notes: Here, we save the search bounds. These bounds are given in terms of
2987  ! index space of the high rank grid. "L" and "H" here do *not* refer
2988  ! to grid rank! They refer to lower and upper bounds.
2989 
2990  isrcl = nint(xl+0.01)
2991  isrch = nint(xh-0.01)
2992  jsrcl = nint(yl+0.01)
2993  jsrch = nint(yh-0.01)
2994 
2995  wtot = 0.
2996  nloc_om = 0
2997  DO isrc=isrcl, isrch
2998  wx = min(xh,real(isrc)+0.5) - max(xl,real(isrc)-0.5)
2999  DO jsrc=jsrcl, jsrch
3000  IF (abs(grids(gsrc)%MAPSTA(jsrc,isrc)).EQ.1) THEN
3001  ! sea point
3002  wy = min(yh,real(jsrc)+0.5) - &
3003  max(yl,real(jsrc)-0.5)
3004  wtot = wtot + wx*wy
3005  nloc_om = nloc_om + 1
3006  ! Notes: check here that we are sufficiently dimensioned.
3007  IF ( nloc_om .GT. nlmax ) THEN
3008  IF ( improc.EQ.nmperr ) WRITE (mdse,1020)
3009  CALL extcde(1020)
3010  END IF
3011  tmpint_om(nrtot,nloc_om) = &
3012  grids(gsrc)%MAPFS(jsrc,isrc)
3013  tmprl_om(nrtot,nloc_om) = wx*wy
3014  END IF
3015  END DO
3016  END DO
3017  tmpint_om(nrtot,0) = nloc_om
3018  tmprl_om(nrtot,1:nloc_om) = tmprl_om(nrtot,1:nloc_om) &
3019  / wtot
3020 
3021  END IF ! (if OLD_METHOD)
3022 
3023 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3024  !...End block of code for computing weights using old method
3025 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3026 
3027 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3028  !...Begin block of code for "computing" weights using new method
3029 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3030 
3031  ! Notes: Weights have already been computed by SCRIP.
3032  ! We just need to transfer them to TMPINT and TMPRL
3033 
3034 #ifdef W3_SCRIP
3035  kdst=(jdst-1)*nidst+idst
3036  nloc=allwgts(gsrc)%WGTDATA(kdst)%N
3037  tmpint(nrtot,0) = nloc
3038  nisrc=grids(gsrc)%NX
3039 #endif
3040 
3041  ! Test output
3042 #ifdef W3_SCRIP
3043  IF ( improc.EQ.nmperr.AND.t38 ) THEN
3044  WRITE(mdst,*)'GSRC,KDST,NLOC = ',gsrc,kdst,nloc
3045  ENDIF
3046 #endif
3047 
3048  ! Notes: check here that we are sufficiently dimensioned.
3049 
3050 #ifdef W3_SCRIP
3051  IF ( nloc .GT. nlmax ) THEN
3052  IF ( improc.EQ.nmperr ) THEN
3053  WRITE (mdse,'(/2A,4(1x,I8))') &
3054  ' *** ERROR WMGHGH: ', &
3055  ' IDST,JDST,NLOC,NLMAX = ', &
3056  idst,jdst,nloc,nlmax
3057  WRITE(mdse,1021)
3058  ENDIF
3059  CALL extcde(1021)
3060  END IF
3061  DO ipnt=1,nloc
3062  ksrc=allwgts(gsrc)%WGTDATA(kdst)%K(ipnt)
3063  jsrc=int((ksrc-1)/nisrc)+1
3064  isrc=ksrc-(jsrc-1)*nisrc
3065  tmpint(nrtot,ipnt) = grids(gsrc)%MAPFS(jsrc,isrc)
3066  tmprl(nrtot,ipnt)= &
3067  allwgts(gsrc)%WGTDATA(kdst)%W(ipnt) ! WX*WY / WTOT
3068  END DO ! DO IPNT=1,NLOC
3069 #endif
3070 
3071 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3072  !...End block of code for "computing" weights using new method
3073 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3074 
3075 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3076  !...Begin block of code that is just for testing
3077 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3078 
3079  IF (do_checking)THEN
3080  ! compare with the values that we got using the old method
3081 #ifdef W3_T38
3082  WRITE(mdst,*)'STARTING TEST 2'
3083 #endif
3084  if (nloc.NE.nloc_om) THEN
3085  IF ( improc.EQ.nmperr )WRITE (mdse,'(/1A,2(I8))') &
3086  ' *** ERROR WMGHGH: NLOC,NLOC_OM = ',nloc,nloc_om
3087  CALL extcde ( 999 )
3088  END IF
3089  istop=0
3090  icount=0
3091  DO ipnt=1,nloc
3092  DO ipnt2=1,nloc
3093  IF (tmpint_om(nrtot,ipnt).EQ.tmpint(nrtot,ipnt2))THEN
3094  ! we found our point
3095  icount=icount+1
3096  IF(abs(tmprl_om(nrtot,ipnt)-tmprl(nrtot,ipnt2)) &
3097  .GT.4.0e-5)then
3098  IF ( improc.EQ.nmperr )WRITE &
3099  (mdse,'(/2A,2(F12.5))') &
3100  ' *** ERROR WMGHGH: ', &
3101  ' *** TMPRL_OM(NRTOT,IPNT),TMPRL(NRTOT,IPNT2) = ', &
3102  tmprl_om(nrtot,ipnt),tmprl(nrtot,ipnt2)
3103  istop=1
3104  END IF
3105  END IF
3106  END DO
3107  END DO
3108  IF(icount.NE.nloc)THEN
3109  IF ( improc.EQ.nmperr )WRITE (mdse,'(/1A,2(I8))') &
3110  ' *** ERROR WMGHGH: ICOUNT,NLOC = ',icount,nloc
3111  istop=1
3112  END IF
3113  IF(istop.EQ.1)THEN
3114  CALL extcde ( 999 )
3115  END IF
3116 #ifdef W3_T38
3117  WRITE(mdst,*)'PASSED TEST 2'
3118 #endif
3119 
3120  END IF ! (if both grids are regular grids)
3121 
3122 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3123  !...End block of code that is just for testing
3124 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3125 
3126  nrok = 0
3127 
3128  END DO lowrank_i ! DO IDST=1, NX
3129  END DO lowrank_j ! DO JDST=1, NY
3130 
3131 #ifdef W3_T38
3132  WRITE(mdst,*)'WMGHGH Section 2.b.6 completed.'
3133 #endif
3134 
3135  ! Notes: We are done with the counting. If we didn't use SCRIP to get
3136  ! TMPINT, TMPRL, then we need to set them using the _OM variables.
3137 
3138  IF(.NOT.lscrip)THEN
3139  tmpint=tmpint_om
3140  tmprl=tmprl_om
3141  END IF
3142 
3143 #ifdef W3_T
3144  WRITE (mdst,9023) gdst, nrtot
3145 #endif
3146  !
3147  ! 2.c Set up masks based on stencil width of scheme and inferred land
3148  ! 2.c.1 Inferred land
3149  !
3150  !!HT: Inferred land from INFLND is added to MAPSTA / MAPST2
3151  !!HT:
3152  mapst2 = mapst2 - 4*mod(mapst2/4,2)
3153  mapst2 = mapst2 + 4*inflnd
3154  DO idst=1, nx
3155  DO jdst=1, ny
3156  IF ( mapst2(jdst,idst).GT.0 ) mapsta(jdst,idst) = &
3157  - abs(mapsta(jdst,idst))
3158  END DO
3159  END DO
3160  !
3161  ! 2.c.2 Masking
3162  !
3163  !!HT: This is masking in the low-res grid to identify where the grid
3164  !!HT: is covered by high-res grids, and far enough away from the
3165  !!HT: high-res grid edges so that no dynamic computations are needed
3166  !!HT: in the low-res grid.
3167  !!HT:
3168  ALLOCATE ( stmask(ny,0:nx+1), maski(ny,nx), stat=istat )
3169  check_alloc_status( istat )
3170  IF ( mdatas(gdst)%MSKINI ) THEN
3171  DEALLOCATE ( mdatas(gdst)%MAPMSK, stat=istat )
3172  check_dealloc_status( istat )
3173  END IF
3174  ALLOCATE ( mdatas(gdst)%MAPMSK(ny,nx), stat=istat )
3175  check_alloc_status( istat )
3176  mapmsk => mdatas(gdst)%MAPMSK
3177  mdatas(gdst)%MSKINI = .true.
3178 
3179  mapmsk = mod(mapst2/8,2)
3180  mapst2 = mapst2 - 8*mapmsk
3181 
3182 
3183  !!HT: STMASK (logical) is used to start this up. We first use the point
3184  !!HT: MAPTST that have been marked as used for boundary points in
3185  !!HT: the corrsponding high-res grids.
3186  !!HT: NIT sets the stencil width of the propagation scheme, used to see
3187  !!HT: how far we need to move in from the boundary points of
3188  !!HT: the high-res grid to reach the area in the low-res grid
3189  !!HT: where we do not need to compute.
3190 
3191  stmask(:,1:nx) = maptst .LT. 0
3192  stmask(:,0) = stmask(:,nx)
3193  stmask(:,nx+1) = stmask(:,1)
3194 
3195 #ifdef W3_PR0
3196  nit = 0
3197 #endif
3198 #ifdef W3_PR1
3199  nit = ( 1 + int(dtmax/dtcfl-0.001) ) * 1
3200 #endif
3201 #ifdef W3_UQ
3202  nit = ( 1 + int(dtmax/dtcfl-0.001) ) * 3
3203 #endif
3204 #ifdef W3_UNO
3205  nit = ( 1 + int(dtmax/dtcfl-0.001) ) * 3
3206 #endif
3207 
3208  idstla=2
3209  idstha=nx-1
3210 
3211  ! notes....bug fix: in official release 3.14, the if-then below
3212  ! was missing. This would produce incorrect results for a global grid that
3213  ! had a higher rank grid on the branch cut (180 to -180 or 360 to 0). See
3214  ! treatment of STMASK after the if-then statement. There, it is clear that
3215  ! it was intended that MASKI be available for i=1 and i=nx, ... but it wasn't
3216  ! available. Symptoms of bug: when using "T T" for masking options, a strip
3217  ! of land would be placed along the i-column just east of the branch cut.
3218  ! This would be seen in the global (low rank) grid.
3219 
3220  IF ( iclose.NE.iclose_none ) THEN
3221  idstla=1
3222  idstha=nx
3223  END IF
3224 
3225  DO jtmp=1, nit
3226  maski = .false.
3227  DO idst=idstla,idstha
3228  DO jdst=2, ny-1
3229  IF ( .NOT. stmask(jdst,idst) .AND. ( &
3230  stmask(jdst+1,idst+1) .OR. stmask(jdst+1,idst ) .OR. &
3231  stmask(jdst+1,idst-1) .OR. stmask(jdst ,idst-1) .OR. &
3232  stmask(jdst-1,idst-1) .OR. stmask(jdst-1,idst ) .OR. &
3233  stmask(jdst-1,idst+1) .OR. stmask(jdst ,idst+1) ) ) &
3234  maski(jdst,idst) = .true.
3235  END DO
3236  END DO
3237  stmask(:,1:nx) = stmask(:,1:nx) .OR. maski
3238  stmask(:,0) = stmask(:,nx)
3239  stmask(:,nx+1) = stmask(:,1)
3240  END DO
3241 
3242  !!HT: Loop over all point from which low-res grid gets data from
3243  !!HT: high-res grid(s). Comparing to STMASK shows which points can be
3244  !!HT: masked out for computation.
3245  !!HT:
3246  !!HT: MAPMSK is stored in WMMDATMD for use in wave model.
3247 
3248  DO iloc=1, nrtot
3249  idst = tmpint(iloc,-4)
3250  jdst = tmpint(iloc,-3)
3251  tmplog(iloc) = stmask(jdst,idst)
3252  IF ( .NOT. stmask(jdst,idst) ) THEN
3253  mapmsk(jdst,idst) = 1
3254  IF ( flghg1 ) mapsta(jdst,idst) = -abs(mapsta(jdst,idst))
3255  maptst(jdst,idst) = 99
3256  END IF
3257  END DO
3258 
3259  IF ( flghg1 ) mapst2 = mapst2 + 8*mapmsk
3260 
3261  DEALLOCATE ( stmask, maski, stat=istat )
3262  check_dealloc_status( istat )
3263 
3264  !!HT: Now that all temporary data is stored, and all mosks are set, all
3265  !!HT: can be put from temporaty storage in permanent storage.
3266  !!HT:
3267  !!HT: Should require no modifications for newer grids ...
3268  !!HT: ... unless more data is needed than for old grids .....
3269 
3270  !
3271  ! 2.d Set up mapping for staging data
3272  ! 2.d.1 Set counters / required array sizes
3273  !
3274 #ifdef W3_SHRD
3275  isproc = 1
3276  ispro2 = 1
3277 #endif
3278  i1 = 0
3279  i2 = 0
3280  i3 = 0
3281  i4 = 0
3282 
3283  DO iloc=1, nrtot
3284 
3285  jj = tmpint(iloc,-1)
3286  hgstge(gdst,jj)%NTOT = hgstge(gdst,jj)%NTOT + 1
3287  isea = tmpint(iloc,-2)
3288  CALL init_get_jsea_isproc(isea, jsea, isproc)
3289 #ifdef W3_DIST
3290  isproc = isproc + croot - 1
3291 #endif
3292  !
3293  i1(jj,isproc) = i1(jj,isproc) + 1
3294  IF ( tmplog(iloc) ) i2(jj,isproc) = i2(jj,isproc) + 1
3295  IF ( improc .EQ. isproc ) THEN
3296  hgstge(gdst,jj)%NSMX = max(hgstge(gdst,jj)%NSMX,tmpint(iloc,0))
3297  END IF
3298 
3299  DO jr=1, tmpint(iloc,0)
3300  isea = tmpint(iloc,jr)
3301  CALL init_get_jsea_isproc_glob(isea, jj, jsea, ispro2)
3302  IF ( ispro2 .EQ. improc ) THEN
3303  hgstge(gdst,jj)%NSND = hgstge(gdst,jj)%NSND + 1
3304  IF ( tmplog(iloc) ) hgstge(gdst,jj)%NSN1 = &
3305  hgstge(gdst,jj)%NSN1 + 1
3306  END IF
3307  END DO
3308  !
3309  END DO
3310 
3311  hgstge(gdst,:)%NREC = i1(:,improc)
3312  hgstge(gdst,:)%NRC1 = i2(:,improc)
3313  !
3314  ! 2.d.2 ALLOCATE (DEALLOCATE in section 0 as needed)
3315  !
3316  DO gsrc=1, nrgrd
3317  IF ( hgstge(gdst,gsrc)%NREC .GT. 0 ) THEN
3318  ALLOCATE ( &
3319  hgstge(gdst,gsrc)%LJSEA (hgstge(gdst,gsrc)%NREC), &
3320  hgstge(gdst,gsrc)%NRAVG (hgstge(gdst,gsrc)%NREC), &
3321  hgstge(gdst,gsrc)%IMPSRC(hgstge(gdst,gsrc)%NREC, &
3322  hgstge(gdst,gsrc)%NSMX), &
3323  hgstge(gdst,gsrc)%ITAG (hgstge(gdst,gsrc)%NREC, &
3324  hgstge(gdst,gsrc)%NSMX), &
3325  hgstge(gdst,gsrc)%WGTH (hgstge(gdst,gsrc)%NREC, &
3326  hgstge(gdst,gsrc)%NSMX), &
3327  hgstge(gdst,gsrc)%SHGH (sgrds(gsrc)%NSPEC, &
3328  hgstge(gdst,gsrc)%NSMX, &
3329  hgstge(gdst,gsrc)%NREC), stat=istat )
3330  check_alloc_status( istat )
3331 #ifdef W3_T3
3332  hgstge(gdst,gsrc)%LJSEA = -1
3333  hgstge(gdst,gsrc)%NRAVG = -1
3334  hgstge(gdst,gsrc)%IMPSRC = -1
3335  hgstge(gdst,gsrc)%ITAG = -1
3336  hgstge(gdst,gsrc)%WGTH = -1.
3337 #endif
3338  END IF
3339  IF ( hgstge(gdst,gsrc)%NSND .GT. 0 ) THEN
3340  ALLOCATE ( hgstge(gdst,gsrc)%ISEND (hgstge(gdst,gsrc)%NSND,5), &
3341  stat=istat )
3342  check_alloc_status( istat )
3343 #ifdef W3_T4
3344  hgstge(gdst,gsrc)%ISEND = -1
3345 #endif
3346  END IF
3347  hgstge(gdst,gsrc)%INIT = .true.
3348  END DO
3349  !
3350  ! 2.d.3 Fill allocated arrays
3351  !
3352  flgrec = .true.
3353  i2 = i1 + 1
3354  i1 = 0
3355  i4 = hgstge(gdst,:)%NSND + 1
3356  i3 = 0
3357 
3358  DO iloc=1, nrtot
3359 
3360  isea = tmpint(iloc,-2)
3361  jj = tmpint(iloc,-1)
3362  nr0 = tmpint(iloc, 0)
3363  CALL init_get_jsea_isproc(isea, jsea, isproc)
3364 #ifdef W3_DIST
3365  isproc = isproc + croot - 1
3366  flgrec = isproc .EQ. improc
3367 #endif
3368  !
3369  IF ( tmplog(iloc) ) THEN
3370  i1(jj,isproc) = i1(jj,isproc) + 1
3371  irec = i1(jj,isproc)
3372  ELSE
3373  i2(jj,isproc) = i2(jj,isproc) - 1
3374  irec = i2(jj,isproc)
3375  END IF
3376 
3377  IF ( flgrec ) THEN
3378  hgstge(gdst,jj)%LJSEA(irec) = jsea
3379  hgstge(gdst,jj)%NRAVG(irec) = nr0
3380  hgstge(gdst,jj)%WGTH(irec,:nr0) = tmprl(iloc,1:nr0)
3381 #ifdef W3_DIST
3382  hgstge(gdst,jj)%ITAG(irec,:nr0) = ltag(:nr0)
3383 #endif
3384  END IF
3385 
3386  DO ij=1, nr0
3387 
3388  isea = tmpint(iloc,ij)
3389  CALL init_get_jsea_isproc_glob(isea, jj, jsea, ispro2)
3390  IF ( flgrec ) hgstge(gdst,jj)%IMPSRC(irec,ij) = ispro2
3391 
3392  IF ( ispro2 .EQ. improc ) THEN
3393  IF ( tmplog(iloc) ) THEN
3394  i3(jj) = i3(jj) + 1
3395  isnd = i3(jj)
3396  ELSE
3397  i4(jj) = i4(jj) - 1
3398  isnd = i4(jj)
3399  END IF
3400  hgstge(gdst,jj)%ISEND(isnd,1) = jsea
3401 #ifdef W3_DIST
3402  hgstge(gdst,jj)%ISEND(isnd,2) = isproc
3403 #endif
3404  hgstge(gdst,jj)%ISEND(isnd,3) = irec
3405  hgstge(gdst,jj)%ISEND(isnd,4) = ij
3406 #ifdef W3_DIST
3407  hgstge(gdst,jj)%ISEND(isnd,5) = ltag(ij)
3408 #endif
3409  END IF
3410 
3411  END DO
3412  !
3413 #ifdef W3_DIST
3414  ltag = ltag + nr0
3415  ltag0 = ltag0 + nr0
3416 #endif
3417  !
3418  END DO
3419  !
3420  ! 2.e Adjust FLAGST using MAPTST
3421  !
3422 #ifdef W3_T
3423  ALLOCATE ( mapst(ny,nx), stat=istat )
3424  check_alloc_status( istat )
3425  mapst = '-'
3426 #endif
3427  !
3428  DO isea=1, nsea
3429  idst = mapsf(isea,1)
3430  jdst = mapsf(isea,2)
3431  IF ( maptst(jdst,idst) .GT. 0 ) flagst(isea) = .NOT. flghg1
3432 #ifdef W3_T
3433  IF ( flagst(isea) ) THEN
3434  mapst(jdst,idst) = 'O'
3435  ELSE
3436  mapst(jdst,idst) = 'X'
3437  END IF
3438 #endif
3439  END DO
3440  !
3441  ! 2.f Test output map
3442  !
3443 #ifdef W3_T
3444  WRITE (mdst,9025) 'MAPTST'
3445  DO jdst=ny,1 , -1
3446  WRITE (mdst,9026) maptst(jdst,:) + 88*inflnd(jdst,:)
3447  END DO
3448 #endif
3449  !
3450 #ifdef W3_T
3451  WRITE (mdst,9025) 'MAPSTA'
3452  DO jdst=ny,1 , -1
3453  WRITE (mdst,9026) mapsta(jdst,:)
3454  END DO
3455 #endif
3456  !
3457 #ifdef W3_T
3458  WRITE (mdst,9025) 'MAPST2'
3459  DO jdst=ny,1 , -1
3460  WRITE (mdst,9026) mapst2(jdst,:)
3461  END DO
3462 #endif
3463  !
3464 #ifdef W3_T
3465  WRITE (mdst,9025) 'FLAGST'
3466  DO jdst=ny,1 , -1
3467  WRITE (mdst,9027) mapst(jdst,:)
3468  END DO
3469 #endif
3470  !
3471  DEALLOCATE ( maptst, inflnd, stat=istat )
3472  check_dealloc_status( istat )
3473 #ifdef W3_T
3474  DEALLOCATE ( mapst, stat=istat )
3475  check_dealloc_status( istat )
3476 #endif
3477  !
3478  ! 2.g Test output receiving
3479  !
3480 #ifdef W3_T3
3481  DO gsrc=1, nrgrd
3482  nr0 = hgstge(gdst,gsrc)%NREC
3483  IF ( nr0 .EQ. 0 ) THEN
3484  WRITE (mdst,9030) gsrc
3485  ELSE
3486  WRITE (mdst,9031) gsrc, nr0
3487  DO irec=1, nr0
3488  jsea = hgstge(gdst,gsrc)%LJSEA(irec)
3489  nrtot = hgstge(gdst,gsrc)%NRAVG(irec)
3490  IF ( nrtot .LE. 15 ) THEN
3491  WRITE (mdst,9032) jsea, nrtot, &
3492  hgstge(gdst,gsrc)%WGTH(irec,:nrtot)
3493  ELSE
3494  WRITE (mdst,9032) jsea, nrtot, &
3495  hgstge(gdst,gsrc)%WGTH(irec,1:15)
3496  WRITE (mdst,9033) &
3497  hgstge(gdst,gsrc)%WGTH(irec,16:nrtot)
3498  END IF
3499  WRITE (mdst,9034) &
3500  hgstge(gdst,gsrc)%IMPSRC(irec,1:nrtot)
3501  WRITE (mdst,9034) &
3502  hgstge(gdst,gsrc)%ITAG(irec,1:nrtot)
3503  END DO
3504  END IF
3505  END DO
3506 #endif
3507  !
3508  ! 2.h Test output sending
3509  !
3510 #ifdef W3_T4
3511  DO gsrc=1, nrgrd
3512  nr0 = hgstge(gdst,gsrc)%NSND
3513  IF ( nr0 .EQ. 0 ) THEN
3514  WRITE (mdst,9040) gsrc
3515  ELSE
3516  WRITE (mdst,9041) gsrc, nr0
3517  DO isnd=1, nr0
3518  WRITE (mdst,9042) hgstge(gdst,gsrc)%ISEND(isnd,:)
3519  END DO
3520  END IF
3521  END DO
3522 #endif
3523  !
3524  ! 2.i Final clean up
3525  !
3526  DEALLOCATE ( idstl, idsth, jdstl, jdsth, gridok, bdist, &
3527  tmpint, tmprl, tmplog, stat=istat )
3528  check_dealloc_status( istat )
3529 
3530  IF (old_method) THEN
3531  DEALLOCATE ( bdist_om, tmpint_om, tmprl_om, stat=istat )
3532  check_dealloc_status( istat )
3533  END IF
3534 
3535 #ifdef W3_DIST
3536  DEALLOCATE ( ltag, stat=istat )
3537  check_dealloc_status( istat )
3538 #endif
3539  !
3540 
3541  ! Notes: We are done with this dst (low rank) grid, so we deallocate ALLWGTS .
3542  ! This is important because ALLWGTS will be allocated again for the next
3543  ! dst grid.
3544 
3545 #ifdef W3_SCRIP
3546  DO jj=1, grdhgh(gdst,0)
3547  gsrc = grdhgh(gdst,jj)
3548  DO kdst=1,dst_grid_size
3549  DEALLOCATE ( allwgts(gsrc)%WGTDATA(kdst)%W, stat=istat )
3550  check_dealloc_status( istat )
3551  DEALLOCATE ( allwgts(gsrc)%WGTDATA(kdst)%K, stat=istat )
3552  check_dealloc_status( istat )
3553  END DO
3554  DEALLOCATE ( allwgts(gsrc)%WGTDATA, stat=istat )
3555  check_dealloc_status( istat )
3556  END DO
3557  DEALLOCATE ( allwgts, stat=istat )
3558  check_dealloc_status( istat )
3559 #endif
3560 
3561  END IF ! IF ( GRDHGH(GDST,0) ...
3562 #ifdef W3_T38
3563  CALL date_and_time (cdate_time(1), cdate_time(2), cdate_time(3), date_time)
3564  end_time = ((date_time(5)*60 + date_time(6))*60 + date_time(7))*1000 + date_time(8)
3565  elapsed_time = end_time - beg_time(2)
3566  WRITE(nmyout,*) "WMGHGH, LOOP LOWRANK_GRID, GDST= ", gdst, " TOOK ", elapsed_time, " MSEC"
3567 #endif
3568  END DO lowrank_grid
3569 
3570  ! If SCRIPNC and L_STOP, then we are done
3571  IF ( lscripnc .AND. l_stop ) THEN
3572  ! WW3 processes wait here till all have finished
3573 #ifdef W3_MPI
3574  CALL mpi_barrier( mpi_comm_mwave, ierr_mpi )
3575 #endif
3576  ! This is not a true error, so exit code is zero
3577  WRITE( mdse, '(A,I4.4,A)' ) 'IMPROC=',improc, &
3578  ': STOP_SCRIP option invoked: '// &
3579  'non-error exit after writing remap netcdf files'
3580  CALL extcde( 0 )
3581  END IF
3582 
3583  DEALLOCATE ( i1, i2, i3, i4, stat=istat )
3584  check_dealloc_status( istat )
3585 #ifdef W3_MPIBDI
3586  DEALLOCATE ( nx_size, irq, mstat, stat=istat )
3587  check_dealloc_status( istat )
3588 #endif
3589  DEALLOCATE ( nx_beg, nx_end, stat=istat )
3590  check_dealloc_status( istat )
3591 
3592  !
3593  ! 2.j Test output counters
3594  !
3595 #ifdef W3_T
3596  WRITE (mdst,9028) 'NTOT'
3597  DO jj=1, nrgrd
3598  WRITE (mdst,9029) hgstge(jj,:)%NTOT
3599  END DO
3600 #endif
3601  !
3602 #ifdef W3_T
3603  WRITE (mdst,9028) 'NREC'
3604  DO jj=1, nrgrd
3605  WRITE (mdst,9029) hgstge(jj,:)%NREC
3606  END DO
3607 #endif
3608  !
3609 #ifdef W3_T
3610  WRITE (mdst,9028) 'NRC1'
3611  DO jj=1, nrgrd
3612  WRITE (mdst,9029) hgstge(jj,:)%NRC1
3613  END DO
3614 #endif
3615  !
3616 #ifdef W3_T
3617  WRITE (mdst,9028) 'NSND'
3618  DO jj=1, nrgrd
3619  WRITE (mdst,9029) hgstge(jj,:)%NSND
3620  END DO
3621 #endif
3622  !
3623 #ifdef W3_T
3624  WRITE (mdst,9028) 'NSN1'
3625  DO jj=1, nrgrd
3626  WRITE (mdst,9029) hgstge(jj,:)%NSN1
3627  END DO
3628 #endif
3629  !
3630 #ifdef W3_T
3631  WRITE (mdst,9028) 'NSMX'
3632  DO jj=1, nrgrd
3633  WRITE (mdst,9029) hgstge(jj,:)%NSMX
3634  END DO
3635 #endif
3636  !
3637 #ifdef W3_T38
3638  CALL date_and_time (cdate_time(1), cdate_time(2), cdate_time(3), date_time)
3639  end_time = ((date_time(5)*60 + date_time(6))*60 + date_time(7))*1000 + date_time(8)
3640  elapsed_time = end_time - beg_time(1)
3641  WRITE(nmyout,*) "WMGHGH, ALL TOOK ", elapsed_time, " MSEC"
3642 #endif
3643 
3644  RETURN
3645  !
3646  ! Formats
3647  !
3648 1000 FORMAT (/' *** WAVEWATCH III ERROR IN WMGHGH : *** '/ &
3649  ' GRDHGH NOT YET ALLOCATED, CALL WMGLOW FIRST'/)
3650 1020 FORMAT (/' *** WAVEWATCH III ERROR IN WMGHGH : *** '/ &
3651  ' TMPINT AND TMPRL TOO SMALL (w/out SCRIP)'/)
3652 #ifdef W3_SCRIP
3653 1021 FORMAT (/' *** WAVEWATCH III ERROR IN WMGHGH : *** '/ &
3654  ' TMPINT AND TMPRL TOO SMALL (w/SCRIP) '/)
3655 #endif
3656  !
3657 #ifdef W3_T
3658 9010 FORMAT ( ' TEST WMGHGH : INITIALIZE BOUNDARY DISTANCE MAPS')
3659 9011 FORMAT ( ' GRID = ',i3,' RANK = ',i3, &
3660  ' NBI = ',i6)
3661 9012 FORMAT ( ' *** MAP NOT NEEDED ***')
3662 9013 FORMAT ( ' TEST WMGHGH : FINAL MAP ')
3663 9014 FORMAT (2x,65i2)
3664 #endif
3665  !/
3666 #ifdef W3_T
3667 9020 FORMAT ( ' TEST WMGHGH : GRID',i3,' HAS',i3,' DATA SOURCES')
3668 9021 FORMAT ( ' NO PROCESSING REQUIRED')
3669 9022 FORMAT ( ' TEST WMGHGH : GRID',i3,' COVERS ',4i8)
3670 9023 FORMAT ( ' TEST WMGHGH : GRID',i3, &
3671  ', NR OF POINTS TO PROCESS:',i5)
3672 9025 FORMAT ( ' TEST WMGHGH : FINAL ',a)
3673 9026 FORMAT (2x,65i2)
3674 9027 FORMAT (2x,65a2)
3675 #endif
3676  !
3677 #ifdef W3_T
3678 9028 FORMAT ( ' TEST WMGHGH : COUNTERS ',a)
3679 9029 FORMAT (2x,20i6)
3680 #endif
3681  !
3682 #ifdef W3_T3
3683 9030 FORMAT ( ' TEST WMGHG : FROM GRID',i3,', NO DATA TO RECEIVE')
3684 9031 FORMAT ( ' TEST WMGHG : FROM GRID',i3,', RECEIVING ',i6)
3685 9032 FORMAT ( 2x,i10,i6,15f6.2)
3686 9033 FORMAT ( 18x,15f6.2)
3687 9034 FORMAT ( 18x,15i6)
3688 #endif
3689  !
3690 #ifdef W3_T4
3691 9040 FORMAT ( ' TEST WMGHG : FROM GRID',i3,', NO DATA TO SEND')
3692 9041 FORMAT ( ' TEST WMGHG : FROM GRID',i3,', SENDING ',i6)
3693 9042 FORMAT ( 12x,i10,4i6)
3694 #endif
3695  !/
3696  !/ End of WMGHGH ----------------------------------------------------- /
3697  !/

References w3gdatmd::clgtype, wmmdatmd::croot, constants::dera, w3gdatmd::dtcfl, w3gdatmd::dtmax, w3servmd::extcde(), file(), w3gdatmd::flagll, w3gdatmd::flagst, wmmdatmd::flgbdi, wmmdatmd::flghg1, wmmdatmd::grank, constants::grav, wmmdatmd::grdhgh, w3gdatmd::grids, w3gdatmd::gtype, wmmdatmd::hgstge, w3gdatmd::iclose, w3gdatmd::iclose_none, w3gdatmd::iclose_trpl, wmmdatmd::improc, include(), w3parall::init_get_jsea_isproc(), wmmdatmd::init_get_jsea_isproc_glob(), wmmdatmd::mapbdi, w3gdatmd::mapfs, wmmdatmd::mapmsk, w3gdatmd::mapsf, w3gdatmd::mapst2, w3gdatmd::mapsta, wmmdatmd::mdatas, wmmdatmd::mdse, wmmdatmd::mdst, wmmdatmd::mpi_comm_mwave, w3odatmd::nbi, wmmdatmd::nmperr, wmmdatmd::nmproc, wmmdatmd::nrgrd, w3gdatmd::nsea, w3gdatmd::nx, w3gdatmd::ny, constants::radius, w3gdatmd::rlgtype, wmscrpmd::scrip_wrapper(), w3gdatmd::sgrds, w3gdatmd::sig, w3gdatmd::smctype, w3servmd::strace(), w3gdatmd::sx, w3gdatmd::sy, w3gdatmd::ungtype, w3gdatmd::w3setg(), w3odatmd::w3seto(), scrip_interface::wgtdata, wmmdatmd::wmsetm(), w3gdatmd::x0, w3gdatmd::xgrd, and w3gdatmd::y0.

Referenced by wminitmd::wminit(), and wminitmd::wminitnml().

◆ wmglow()

subroutine wmgridmd::wmglow ( logical, dimension(nrgrd), intent(out), optional  FLRBPI)

Determine relations to lower ranked grids for each grid.

On the fly, the opposite relations are also saved. Map active boundary points to lower ranked grids.

Parameters
[out]FLRBPIArray with flags for external file use.
Author
H. L. Tolman
W. E. Rogers
Date
06-Jun-2018

Definition at line 152 of file wmgridmd.F90.

152  !/
153  !/ +-----------------------------------+
154  !/ | WAVEWATCH III NOAA/NCEP |
155  !/ | H. L. Tolman |
156  !/ | W. E. Rogers |
157  !/ | FORTRAN 90 |
158  !/ | Last update : 06-Jun-2018 !
159  !/ +-----------------------------------+
160  !/
161  !/ 06-Oct-2005 : Origination. ( version 3.08 )
162  !/ 10-Feb-2006 : Add test on grid resolution. ( version 3.09 )
163  !/ 26-Mar-2009 : Adding test output !/T9. ( version 3.14 )
164  !/ 30-Oct-2009 : Implement run-time grid selection. ( version 3.14 )
165  !/ (W. E. Rogers & T. J. Campbell, NRL)
166  !/ 22-Dec-2010 : Adapt for use with irregular grids ( version 3.14 )
167  !/ (W. E. Rogers, NRL)
168  !/ 12-Mar-2012 : Use MPI_COMM_NULL in checks. ( version 4.07 )
169  !/ 06-Jun-2012 : Porting bugfixes from 3.14 to 4.07 ( version 4.07 )
170  !/ 10-Dec-2014 : Add checks for allocate status ( version 5.04 )
171  !/ 06-Jun-2018 : Use W3PARALL ( version 6.04 )
172  !/
173  ! 1. Purpose :
174  !
175  ! Determine relations to lower ranked grids for each grid.
176  ! On the fly, the opposite relations are also saved.
177  !
178  ! 2. Method :
179  !
180  ! Map active boundary points to lower ranked grids.
181  !
182  ! 3. Parameters :
183  !
184  ! Parameter list
185  ! ----------------------------------------------------------------
186  ! FLRBPI L.A. O Array with flags for external file use.
187  ! ----------------------------------------------------------------
188  !
189  ! 4. Subroutines used :
190  !
191  ! Name Type Module Description
192  ! ----------------------------------------------------------------
193  ! W3SETO, W3SETG, W3DMO5
194  ! Subr. W3xDATMD Manage data structures.
195  !
196  ! STRACE Subr. W3SERVMD Subroutine tracing.
197  ! EXTCDE Subr. Id. Program abort.
198  !
199  ! MPI_BCAST, MPI_BARRIER
200  ! Subr. mpif.h Comunication routines.
201  ! ----------------------------------------------------------------
202  !
203  ! 5. Called by :
204  !
205  ! Name Type Module Description
206  ! ----------------------------------------------------------------
207  ! WMINIT Subr WMINITMD Multi-grid model initialization.
208  ! ----------------------------------------------------------------
209  !
210  ! 6. Error messages :
211  !
212  ! 7. Remarks :
213  !
214  ! - For MPI version it is assumed that NX, NY, NSEA, and NSEAL are
215  ! properly initialized even if the grid is not run on the local
216  ! process.
217  !
218  ! 8. Structure :
219  !
220  ! See source code.
221  !
222  ! 9. Switches :
223  !
224  ! !/MPI Distribbuted memory management.
225  !
226  ! !/S Enable subroutine tracing.
227  ! !/T Enable test output.
228  ! !/T1 Test output for individual boundary points
229  ! !/T2 Test output cross-reference table
230  ! !/T9 Test output of map of boundary origine.
231  !
232  ! 10. Source code :
233  !
234  !/ ------------------------------------------------------------------- /
235  !
236  USE w3servmd, ONLY: extcde
237 #ifdef W3_S
238  USE w3servmd, ONLY: strace
239 #endif
240  !
241  USE w3gdatmd
242  USE w3odatmd
243  USE w3triamd
244  USE wmmdatmd
245  USE w3parall, ONLY : init_get_jsea_isproc
246  !
247  IMPLICIT NONE
248  !
249 #ifdef W3_MPI
250  include "mpif.h"
251 #endif
252  !/
253  !/ ------------------------------------------------------------------- /
254  !/ Parameter list
255  !/
256  LOGICAL, INTENT(OUT), OPTIONAL :: FLRBPI(NRGRD)
257  !/
258  !/ ------------------------------------------------------------------- /
259  !/ Local parameters
260  !/
261  INTEGER :: I, IBI, IX, IY, JS, J, &
262  JTOT, I1, J1, I2, J2
263 #ifdef W3_MPI
264  INTEGER :: NXYG, IERR_MPI
265 #endif
266 #ifdef W3_S
267  INTEGER, SAVE :: IENT = 0
268 #endif
269  INTEGER, ALLOCATABLE :: TSTORE(:,:)
270 #ifdef W3_MPI
271  LOGICAL :: FLBARR
272 #endif
273  REAL :: XA, YA
274  REAL :: FACTOR
275  LOGICAL :: GRIDD(NRGRD,NRGRD) ! indicates grid-to-grid
276  ! dependency
277  LOGICAL :: RFILE(NRGRD), FLAGOK
278  LOGICAL :: INGRID ! indicates whether boundary point
279  ! is in lower rank grid
280  INTEGER :: IVER(4),JVER(4) ! (I,J) indices of vertices
281  ! of cell (in lower rank grid J) enclosing
282  ! boundary point (in higher rank grid I)
283  REAL :: RW(4) ! Array of interpolation weights.
284  INTEGER :: KVER ! counter for 4 vertices
285 
286  REAL :: DX_MIN_GRIDI,DY_MIN_GRIDI,DX_MAX_GRIDI, &
287  DY_MAX_GRIDI
288  REAL :: DX_MIN_GRIDJ,DY_MIN_GRIDJ,DX_MAX_GRIDJ, &
289  DY_MAX_GRIDJ
290  INTEGER :: ITRI, IM1, IM2, IT, JT, ISFIRST, ITOUT, NBRELEVANT
291  REAL :: DIST_MIN, DIST_MAX, EDIST
292  LOGICAL RESOL_CHECK
293  !
294 #ifdef W3_T9
295  CHARACTER(LEN=1), ALLOCATABLE :: TMAP(:,:)
296 #endif
297  !/
298 #ifdef W3_S
299  CALL strace (ient, 'WMGLOW')
300 #endif
301  !
302  ! -------------------------------------------------------------------- /
303  ! 1. Test grid, Initialize and synchronize grids as needed ( !/MPI )
304  !
305 #ifdef W3_MPI
306  flbarr = .false.
307 #endif
308  !
309  DO i=1, nrgrd
310  !
311  IF ( .NOT. grids(i)%GINIT ) THEN
312  IF ( improc .EQ. nmperr ) WRITE (mdse,1000) i
313  CALL extcde ( 1000 )
314  END IF
315 
316  CALL w3seto ( i, mdse, mdst )
317  CALL w3setg ( i, mdse, mdst )
318  !
319 #ifdef W3_MPI
320  flbarr = flbarr .OR. mdatas(i)%FBCAST
321  IF ( mdatas(i)%FBCAST .AND. &
322  mdatas(i)%MPI_COMM_BCT.NE.mpi_comm_null ) THEN
323  nxyg = grids(i)%NX * grids(i)%NY
324  CALL mpi_bcast ( grids(i)%MAPSTA(1,1), nxyg, &
325  mpi_integer, 0, &
326  mdatas(i)%MPI_COMM_BCT, ierr_mpi )
327  CALL mpi_bcast ( grids(i)%MAPST2(1,1), nxyg, &
328  mpi_integer, 0, &
329  mdatas(i)%MPI_COMM_BCT, ierr_mpi )
330  CALL mpi_bcast ( grids(i)%MAPFS (1,1), nxyg, &
331  mpi_integer, 0, &
332  mdatas(i)%MPI_COMM_BCT, ierr_mpi )
333  nxyg = 3*grids(i)%NSEA
334  CALL mpi_bcast ( grids(i)%MAPSF (1,1), nxyg, &
335  mpi_integer, 0, &
336  mdatas(i)%MPI_COMM_BCT, ierr_mpi )
337  CALL mpi_bcast ( grids(i)%CLATIS(1), nsea, mpi_real, 0,&
338  mdatas(i)%MPI_COMM_BCT, ierr_mpi )
339  CALL mpi_bcast ( sgrds(i)%SIG(0), nk+2, mpi_real, 0,&
340  mdatas(i)%MPI_COMM_BCT, ierr_mpi )
341  END IF
342 #endif
343  !
344  END DO
345  !
346 #ifdef W3_MPI
347  IF (flbarr) CALL mpi_barrier (mpi_comm_mwave,ierr_mpi)
348 #endif
349  !
350 #ifdef W3_T
351  WRITE (mdst,9010)
352 #endif
353  !
354 #ifdef W3_SMC
355  !! Check GTYPE for all grids.
356  IF( improc.EQ.nmperr ) WRITE(mdse,*) " GTYPES in WMGLOW:", &
357  ( grids(i)%GTYPE, i=1, nrgrd )
358 #endif
359  !
360  ! -------------------------------------------------------------------- /
361  ! 2. Process grids
362  !
363  IF ( flagll ) THEN
364  factor = 1.
365  ELSE
366  factor = 1.e-3
367  END IF
368  !
369  gridd = .false.
370  rfile = .false.
371  !
372  IF ( .NOT. ALLOCATED(nbi2g) ) THEN
373  ALLOCATE ( nbi2g(nrgrd,nrgrd), stat=istat )
374  check_alloc_status( istat )
375  END IF
376  nbi2g = 0
377  !
378 #ifdef W3_T
379  WRITE (mdst,9020)
380 #endif
381  !
382  DO i=1, nrgrd
383  !
384 #ifdef W3_T
385  WRITE (mdst,9021) i, grank(i), outpts(i)%OUT5%NBI
386 #endif
387  !
388  ! 2.a Test for input boundary points
389  !
390  IF ( outpts(i)%OUT5%NBI .EQ. 0 ) THEN
391 #ifdef W3_T
392  WRITE (mdst,9022) 'NO INPUT BOUNDARY POINTS, SKIPPING'
393 #endif
394  cycle
395  END IF
396  !
397  ! 2.b Test for lowest rank
398  !
399  IF ( grank(i) .EQ. 1 ) THEN
400  rfile(i) = .true.
401 #ifdef W3_T
402  WRITE (mdst,9022) 'RANK = 1, DATA FROM FILE'
403 #endif
404  cycle
405  END IF
406  !
407 #ifdef W3_SMC
408  !! SMC grid only appears in same ranked group. JGLi23Mar2021
409  IF( grids(i)%GTYPE .EQ. smctype ) THEN
410  IF( improc.EQ.nmperr ) WRITE(mdse,*) ' WMGLOW skip SMC grid', i
411  cycle
412  END IF
413 #endif
414  !
415  ! 2.c Search for input boundary points
416  !
417 
418 #ifdef W3_T
419  WRITE (mdst,9022) 'SEARCHING FOR ACTIVE BOUNDARY POINTS'
420 #endif
421  ibi = 0
422  !
423  ! ... Set up data structure for grid
424  !
425  CALL w3seto ( i, mdse, mdst )
426  CALL w3setg ( i, mdse, mdst )
427  CALL w3dmo5 ( i, mdse, mdst, 1 )
428  ALLOCATE ( tstore(nbi,0:4), stat=istat )
429  check_alloc_status( istat )
430  !
431  ! ... Set up loop structure for grid
432  !
433  DO iy=1, ny
434  DO ix=1, nx
435 
436  !notes : MAPSTA refers to GRIDS(I)%MAPSTA ...this is set in W3SETG
437  IF ( abs(mapsta(iy,ix)) .EQ. 2 ) THEN
438  xa = real(xgrd(iy,ix)) !old code: X0 + REAL(IX-1)*SX
439  ya = real(ygrd(iy,ix)) !old code: Y0 + REAL(IY-1)*SY
440  !
441  ! ... Loop over previous (lower ranked) grids, going in order from highest
442  ! of lower ranked grids (I-1) to lowest of lower ranked grids (1)
443  !
444  js = 0
445  !
446  DO j=i-1, 1, -1
447  !
448  IF ( grank(j) .GE. grank(i) ) cycle
449  !
450 #ifdef W3_SMC
451  !! SMC grid only suppots same ranked group so far. JGLi12Apr2021
452  IF( grids(j)%GTYPE .EQ. smctype ) THEN
453  IF( improc.EQ.nmperr ) WRITE(mdse,*) &
454  ' WMGLOW skip SMC grid', j
455  cycle
456  END IF
457 #endif
458  !
459  ! ... Check if in grid
460  !
461  ! notes:
462  ! old version (v4.00):
463  ! if in grid, return location in grid: a) JX, JY
464  ! (lower left indices of cell),
465  ! b) RX, RY
466  ! (normalized location in cell)
467  ! in not in grid, cycle (search next grid)
468  ! new version (v4.01):
469  ! Check if point within grid and compute interpolation weights using GSU
470  ! if not in grid, cycle (search next grid)
471  !
472  IF (grids(j)%GTYPE .EQ. ungtype) THEN
473  !AR: Here we need to take special care in the case that any problem occurs due to the XA, YA beeing 4 byte
474  CALL is_in_ungrid(j, dble(xa), dble(ya), itout, iver, jver, rw)
475  IF (itout.EQ.0) THEN
476  ingrid=.false.
477  ELSE
478  ingrid=.true.
479  flagok =( abs(grids(j)%MAPSTA(jver(1),iver(1))).GE.1 .OR. &
480  rw(1).LT.0.05 ) .AND. &
481  ( abs(grids(j)%MAPSTA(jver(2),iver(2))).GE.1 .OR. &
482  rw(2).LT.0.05 ) .AND. &
483  ( abs(grids(j)%MAPSTA(jver(3),iver(3))).GE.1 .OR. &
484  rw(3).LT.0.05 )
485  END IF
486  nbrelevant=3
487  ELSE
488  ingrid = w3grmp( grids(j)%GSU, xa, ya, iver , jver, rw )
489  ! Print *, 'J=', J, 'IX=', IX, 'IY=', IY
490  ! Print *, 'IN=', INGRID, 'XA=', XA, 'YA=', YA
491  ! Print *, ' 1: IVER=', IVER(1), 'JVER=', JVER(1), 'RW=', RW(1)
492  ! Print *, ' 2: IVER=', IVER(2), 'JVER=', JVER(2), 'RW=', RW(2)
493  ! Print *, ' 3: IVER=', IVER(3), 'JVER=', JVER(3), 'RW=', RW(3)
494  ! Print *, ' 4: IVER=', IVER(4), 'JVER=', JVER(4), 'RW=', RW(4)
495  IF (ingrid) THEN
496  flagok =( abs(grids(j)%MAPSTA(jver(1),iver(1))).GE.1 .OR. &
497  rw(1).LT.0.05 ) .AND. &
498  ( abs(grids(j)%MAPSTA(jver(2),iver(2))).GE.1 .OR. &
499  rw(2).LT.0.05 ) .AND. &
500  ( abs(grids(j)%MAPSTA(jver(4),iver(4))).GE.1 .OR. &
501  rw(4) .LT.0.05 ) .AND. &
502  ( abs(grids(j)%MAPSTA(jver(3),iver(3))).GE.1 .OR. &
503  rw(3) .LT.0.05 )
504  END IF
505  nbrelevant=4
506  END IF
507  ! internal name= GSU XTIN YTIN IS JS RW (notes)
508  ! role=out in in in out out out
509  ! size= --- 1 1 4 4 4
510  !
511  ! notes:
512  ! - organization of IVER(4),JVER(4),RW(4) as returned by W3GRMP are
513  ! as follows:
514  ! Point 1 : lower i , lower j (JY1,JX1)
515  ! Point 2 : upper i , lower j (JY1,JX2)
516  ! Point 3 : upper i , upper j (JY2,JX2)
517  ! Point 4 : lower i , upper j (JY2,JX1)
518  ! (counter-clockwise starting from lower i, lower j)
519  !
520  ! ... if not in grid, warning message and cycle (search next grid)
521  IF ( .NOT.ingrid ) THEN
522 #ifdef W3_T
523  IF ( iaproc .EQ. naperr ) THEN
524  IF ( flagll ) THEN
525  WRITE (ndse,2000) xa, ya
526  ELSE
527  WRITE (ndse,2001) xa, ya
528  END IF
529  END IF
530 #endif
531  cycle
532  END IF
533 
534  !
535  ! ... Check against MAPSTA
536  !
537 
538  ! Notes:
539  ! Old code | becomes | New code
540  !-----------------| --------| -------
541  ! (1.-RX)*(1.-RY) | becomes | RW(1)
542  ! RX*(1.-RY) | becomes | RW(2)
543  ! (1.-RX)*RY | becomes | RW(4)
544  ! RX*RY | becomes | RW(3)
545  ! JX1 | becomes | IVER(1)
546  ! JY1 | becomes | JVER(1)
547  ! JX2 | becomes | IVER(3)
548  ! JY2 | becomes | JVER(3)
549 
550  ! Notes:
551  ! IVER(1)=IVER(4), IVER(2)=IVER(3)
552  ! JVER(1)=JVER(2), JVER(3)=JVER(4)
553 
554  ! point 1:
555  flagok = ( abs(grids(j)%MAPSTA(jver(1),iver(1))).GE.1 .OR. &
556  rw(1).LT.0.05 ) .AND. &
557  ! point 2:
558  ( abs(grids(j)%MAPSTA(jver(2),iver(2))).GE.1 .OR. &
559  rw(2).LT.0.05 ) .AND. &
560  ! point 4:
561  ( abs(grids(j)%MAPSTA(jver(4),iver(4))).GE.1 .OR. &
562  rw(4) .LT.0.05 ) .AND. &
563  ! point 3:
564  ( abs(grids(j)%MAPSTA(jver(3),iver(3))).GE.1 .OR. &
565  rw(3) .LT.0.05 )
566  !
567  IF ( .NOT.flagok ) cycle
568  !
569  ! ... We found interpolation data !
570  !
571  js = j
572  ibi = ibi + 1
573  gridd(i,js) = .true.
574  !
575  xbpi(ibi) = xa
576  ybpi(ibi) = ya
577  isbpi(ibi) = mapfs(iy,ix)
578  !
579  tstore(ibi, 0) = js
580  !
581  ! notes:
582  ! To maintain perfect consistency with old code, we would make code such that:
583  ! - point 1 in GSU goes to point 1 in RDBPI, TSTORE
584  ! - point 2 in GSU goes to point 2 in RDBPI, TSTORE
585  ! - point 4 in GSU goes to point 3 in RDBPI, TSTORE
586  ! - point 3 in GSU goes to point 4 in RDBPI, TSTORE
587  ! Instead, here, we map point 4 in GSU goes to point 4 in RDBPI, TSTORE, etc.
588  ! Thus the ordering of RDBPI, TSTORE has changed.
589  ! I have no reason to believe that the ordering in RDBPI, TSTORE is important.
590  ! I have gone through test case mww3_test_02 for gridsets a,b,c,d and found
591  ! no change in result vs v4.00.
592 
593  DO kver=1,4
594  IF (kver .LE. nbrelevant) THEN
595  IF ( abs(grids(j)%MAPSTA(jver(kver),iver(kver))).GE.1 &
596  .AND. rw(kver) .GT.0.05 ) THEN
597  rdbpi(ibi,kver) = rw(kver)
598  tstore(ibi,kver) = grids(j)%MAPFS(jver(kver),iver(kver))
599  ELSE
600  rdbpi(ibi,kver) = 0.
601  tstore(ibi,kver) = 0
602  END IF
603  ELSE
604  rdbpi(ibi,kver) = 0.
605  tstore(ibi,kver) = 0
606  END IF
607 
608  END DO
609 
610  !
611  ! .....normalize weights to give sum(R)=1
612  rdbpi(ibi,:) = rdbpi(ibi,:) / sum(rdbpi(ibi,:))
613  !
614  ! Search was successful, so no need to search through other grids, so exit loop
615  EXIT
616  END DO ! "DO J=..."
617  !
618  IF ( js.EQ.0 .AND. improc.EQ.nmperr ) &
619  WRITE (mdse,1020) i, ix, iy, xa, ya
620  !
621  END IF ! If a boundary point...
622 
623  END DO ! "DO IX=..."
624  END DO ! "DO IY=..."
625 
626  !
627  ! 2.d Error checks
628  !
629  IF ( ibi .EQ. 0 ) THEN
630  rfile(i) = .true.
631  IF ( improc .EQ. nmperr ) WRITE (mdse,1021)
632  DEALLOCATE ( outpts(i)%OUT5%IPBPI, outpts(i)%OUT5%ISBPI, &
633  outpts(i)%OUT5%XBPI, outpts(i)%OUT5%YBPI, &
634  outpts(i)%OUT5%RDBPI, stat=istat )
635  check_dealloc_status( istat )
636  cycle
637  ELSE IF ( ibi .NE. outpts(i)%OUT5%NBI ) THEN
638  CALL extcde ( 1020 )
639  ENDIF
640  !
641  ! 2.e Sort spectra by grid, fill IPBPI, and get NBI2 and ....
642  !
643 
644  ipbpi = 0
645  nbi2 = 0
646  !
647  DO j=1, nrgrd
648  DO i1=1, nbi
649  IF ( tstore(i1,0) .NE. j ) cycle
650  DO j1=1, 4
651  IF ( tstore(i1,j1).NE.0 .AND. ipbpi(i1,j1).EQ.0 ) THEN
652  nbi2 = nbi2 + 1
653  ipbpi(i1,j1) = nbi2
654  DO i2=i1, nbi
655  IF ( tstore(i2,0) .NE. j ) cycle
656  DO j2=1, 4
657  IF ( tstore(i2,j2) .EQ. tstore(i1,j1) ) &
658  ipbpi(i2,j2) = nbi2
659  END DO
660  END DO
661  END IF
662  END DO
663  END DO
664  END DO
665  !
666  ! 2.f Set up spectral storage and cross-grid mapping
667  !
668  CALL w3dmo5 ( i, mdse, mdst, 3 )
669  !
670  ALLOCATE ( mdatas(i)%NBI2S(nbi2,2), stat=istat )
671  check_alloc_status( istat )
672  nbi2s => mdatas(i)%NBI2S
673  !
674  DO i1=1, nbi
675  DO j1=1, 4
676  IF ( ipbpi(i1,j1) .NE. 0 ) THEN
677  nbi2s(ipbpi(i1,j1),1) = tstore(i1,0)
678  nbi2s(ipbpi(i1,j1),2) = tstore(i1,j1)
679  END IF
680  END DO
681  END DO
682  !
683  DO i1=1, nbi2
684  nbi2g(i,nbi2s(i1,1)) = nbi2g(i,nbi2s(i1,1)) + 1
685  END DO
686  !
687  ! 2.g Test output
688  !
689 #ifdef W3_T1
690  WRITE (mdst,9023)
691  DO j=1, nbi
692  WRITE (mdst,9024) j, isbpi(j), factor*xbpi(j), &
693  factor*ybpi(j), ipbpi(j,:), rdbpi(j,:), tstore(j,:)
694  END DO
695 #endif
696  !
697 #ifdef W3_T2
698  WRITE (mdst,9025)
699  DO j=1, nbi2
700  WRITE (mdst,9026) j, nbi2s(j,:)
701  END DO
702 #endif
703  !
704 #ifdef W3_T9
705  ALLOCATE ( tmap(nx,ny), stat=istat )
706  check_alloc_status( istat )
707 #endif
708  !
709 #ifdef W3_T9
710  DO ix=1, nx
711  DO iy=1, ny
712  IF ( abs(mapsta(iy,ix)) .EQ. 0 ) then
713  tmap(ix,iy) = '/'
714  ELSE IF ( abs(mapsta(iy,ix)) .EQ. 1 ) then
715  tmap(ix,iy) = '-'
716  ELSE IF ( abs(mapsta(iy,ix)) .EQ. 2 ) then
717  tmap(ix,iy) = 'X'
718  END IF
719  END DO
720  END DO
721 #endif
722  !
723 #ifdef W3_T9
724  DO j=1, nbi
725  ix = mapsf(isbpi(j),1)
726  iy = mapsf(isbpi(j),2)
727  WRITE (tmap(ix,iy),'(I1)') tstore(j,0)
728  END DO
729 #endif
730  !
731 #ifdef W3_T9
732  DO j=1, 1+(nx-1)/130
733  WRITE (mdst,9029) i, j
734  DO iy=ny, 1, -1
735  i1 = j*130-129
736  i2 = min( nx , j*130 )
737  WRITE (mdst,'(1X,130A1)') tmap(i1:i2,iy)
738  END DO
739  END DO
740 #endif
741  !
742 #ifdef W3_T9
743  DEALLOCATE ( tmap, stat=istat )
744  check_dealloc_status( istat )
745 #endif
746  !
747  DEALLOCATE ( tstore, stat=istat )
748  check_dealloc_status( istat )
749  !
750  END DO
751  !
752 #ifdef W3_T
753  WRITE (mdst,9027)
754  DO i=1, nrgrd
755  WRITE (mdst,9028) outpts(i)%OUT5%NBI, outpts(i)%OUT5%NBI2, &
756  rfile(i), nbi2g(i,:)
757  END DO
758 #endif
759  !
760  ! -------------------------------------------------------------------- /
761  ! 3. Finalyze grid dependencies in GRDLOW
762  ! 3.a Get size of array and dimension
763  !
764 
765  ! notes:
766  ! GRIDD(I,J) indicates whether grid I is dependent on lower ranked grid J
767  ! JS counts the number of grids J that grid I is dependent on
768  ! GRDLOW is sized to accomodate the grid with the largest JS
769 
770  jtot = 0
771  DO i=1, nrgrd
772  js = 0
773  DO j=1, nrgrd
774  IF ( gridd(i,j) ) js = js + 1
775  END DO
776  jtot = max( jtot , js )
777  END DO
778  !
779  IF ( ALLOCATED(grdlow) ) THEN
780  DEALLOCATE ( grdlow, stat=istat )
781  check_dealloc_status( istat )
782  END IF
783  ALLOCATE ( grdlow(nrgrd,0:jtot), stat=istat )
784  check_alloc_status( istat )
785  grdlow = 0
786  !
787 #ifdef W3_T
788  WRITE (mdst,9030) jtot
789 #endif
790  !
791  ! 3.b Fill array
792  !
793  flagok = .true.
794  !
795  DO i=1, nrgrd
796  jtot = 0
797  DO j=1, nrgrd
798  IF ( gridd(i,j) ) THEN
799  jtot = jtot + 1
800  grdlow(i,jtot) = j
801  ! ... error checking: catch situation where ranks are inconsistent with
802  ! resolution
803 
804  ! notes:
805  ! old code: SXJ=GRIDS(J)%SX
806  ! SXI=GRIDS(I)%SX
807  ! SYJ=GRIDS(J)%SY
808  ! SYI=GRIDS(I)%SY
809  ! also, old code did not need to check both min and max,
810  ! since they were the same
811  ! new code:
812  ! SXI(:,:) ==> GRIDS(I)%HPFAC ! resolution in higher rank grid I
813  ! (approximate in case of irregular grids)
814  ! SYI(:,:) ==> GRIDS(I)%HQFAC ! viz.
815  ! SXJ(:,:) ==> GRIDS(J)%HPFAC ! resolution in lower rank grid J
816  ! (approximate in case of irregular grids)
817  ! SYJ(:,:) ==> GRIDS(J)%HQFAC ! viz.
818 
819  ! notes:
820  ! for irregular grids, we require
821  ! 1) smallest cell in low rank grid is larger than smallest cell
822  ! in high rank grid
823  ! 2) largest cell in low rank grid is larger than largest cell
824  ! in high rank grid
825  ! Each dimension (along i/p and j/q axes) is checked separately,
826  ! making 4 checks total.
827  ! This is strict, and may generate "false positives" in error checking
828  ! here. In this case, the user may wish to disable this error checking.
829  ! For case of regular grids, we cannot use HPFAC, since it goes to zero
830  ! at pole. We instead use good ol' SX and SY
831 
832  IF ( grids(i)%GTYPE .EQ. clgtype ) THEN
833  dx_min_gridi=minval(grids(i)%HPFAC)
834  dy_min_gridi=minval(grids(i)%HQFAC)
835  dx_max_gridi=maxval(grids(i)%HPFAC)
836  dy_max_gridi=maxval(grids(i)%HQFAC)
837  ELSEIF ( grids(i)%GTYPE .EQ. rlgtype .OR. &
838  grids(i)%GTYPE .EQ. smctype ) THEN
839  !!Li SMC grid shares mesh with regular grid. 22Mar2021
840  dx_min_gridi=grids(i)%SX
841  dy_min_gridi=grids(i)%SY
842  dx_max_gridi=grids(i)%SX
843  dy_max_gridi=grids(i)%SY
844  ELSEIF ( grids(i)%GTYPE .EQ. ungtype ) THEN
845  isfirst=1
846  dist_max=0
847  dist_min=0
848  DO itri=1,grids(i)%NTRI
849  DO it=1,3
850  IF (it.EQ.3) THEN
851  jt=1
852  ELSE
853  jt=it+1
854  END IF
855  im1=grids(i)%TRIGP(it,itri)
856  im2=grids(i)%TRIGP(jt,itri)
857  edist=w3dist(flagll, real(grids(i)%XGRD(1,im1)), &
858  REAL(GRIDS(I)%YGRD(1,IM1)), REAL(GRIDS(I)%XGRD(1,IM2)), &
859  REAL(GRIDS(I)%YGRD(1,IM2)))
860  IF (isfirst.EQ.1) THEN
861  dist_max=edist
862  dist_min=edist
863  isfirst=0
864  ELSE
865  IF (edist.GT.dist_max) THEN
866  dist_max=edist
867  END IF
868  IF (edist.LT.dist_min) THEN
869  dist_min=edist
870  END IF
871  END IF
872  END DO
873  END DO
874  dx_min_gridi=dist_min
875  dy_min_gridi=dist_min
876  dx_max_gridi=dist_max
877  dy_max_gridi=dist_max
878  ELSE
879  CALL extcde ( 601 )
880  END IF
881 
882  IF ( grids(j)%GTYPE .EQ. clgtype ) THEN
883  dx_min_gridj=minval(grids(j)%HPFAC)
884  dy_min_gridj=minval(grids(j)%HQFAC)
885  dx_max_gridj=maxval(grids(j)%HPFAC)
886  dy_max_gridj=maxval(grids(j)%HQFAC)
887  ELSEIF ( grids(j)%GTYPE .EQ. rlgtype .OR. &
888  grids(j)%GTYPE .EQ. smctype ) THEN
889  !!Li SMC grid shares mesh with regular grid. 22Mar2021
890  dx_min_gridj=grids(j)%SX
891  dy_min_gridj=grids(j)%SY
892  dx_max_gridj=grids(j)%SX
893  dy_max_gridj=grids(j)%SY
894  ELSEIF ( grids(j)%GTYPE .EQ. ungtype ) THEN
895  isfirst=1
896  dist_max=0
897  dist_min=0
898  DO itri=1,grids(j)%NTRI
899  DO it=1,3
900  IF (it.EQ.3) THEN
901  jt=1
902  ELSE
903  jt=it+1
904  END IF
905  im1=grids(j)%TRIGP(it,itri)
906  im2=grids(j)%TRIGP(jt,itri)
907  edist=w3dist(flagll, real(grids(j)%XGRD(1,im1)), &
908  REAL(GRIDS(J)%YGRD(1,IM1)), REAL(GRIDS(J)%XGRD(1,IM2)), &
909  REAL(GRIDS(J)%YGRD(1,IM2)))
910  IF (isfirst.EQ.1) THEN
911  dist_max=edist
912  dist_min=edist
913  isfirst=0
914  ELSE
915  IF (edist.GT.dist_max) THEN
916  dist_max=edist
917  END IF
918  IF (edist.LT.dist_min) THEN
919  dist_min=edist
920  END IF
921  END IF
922  END DO
923  END DO
924  dx_min_gridj=dist_min
925  dy_min_gridj=dist_min
926  dx_max_gridj=dist_max
927  dy_max_gridj=dist_max
928  ELSE
929  CALL extcde ( 602 )
930  END IF
931 
932  resol_check=.false.
933 #ifdef W3_T38
934  resol_check=.true.
935 #endif
936  IF (resol_check) THEN
937  IF ( dx_min_gridj .LT. 0.99*dx_min_gridi .OR. &
938  dy_min_gridj .LT. 0.99*dy_min_gridi .OR. &
939  dx_max_gridj .LT. 0.99*dx_max_gridi .OR. &
940  dy_max_gridj .LT. 0.99*dy_max_gridi ) THEN
941  print *, 'DX_MIN_GRID I=', dx_min_gridi, ' J=', dx_min_gridj
942  print *, 'DX_MAX_GRID I=', dx_max_gridi, ' J=', dx_max_gridj
943  IF ( improc.EQ.nmperr ) WRITE (mdse,1030) &
944  j, grank(j), dx_min_gridj, dy_min_gridj, &
945  dx_max_gridj, dy_max_gridj, &
946  i, grank(i), dx_min_gridi, dy_min_gridi, &
947  dx_max_gridi, dy_max_gridi
948  flagok = .false.
949  END IF
950  END IF
951 
952  END IF ! IF ( GRIDD(I,J) ) THEN
953 
954  END DO ! DO J=...
955  grdlow(i,0) = jtot
956  END DO ! DO I=...
957  !
958 #ifdef W3_T
959  WRITE (mdst,9031)
960  DO i=1, nrgrd
961  WRITE (mdst,9032) i, grdlow(i,0:grdlow(i,0))
962  END DO
963 #endif
964  !
965  IF ( .NOT. flagok ) CALL extcde ( 1030 )
966  !
967  ! -------------------------------------------------------------------- /
968  ! 4. Finalyze grid dependencies in GRDHGH
969  ! 4.a Get size of array and dimension
970  !
971  jtot = 0
972  DO i=1, nrgrd
973  js = 0
974  DO j=1, nrgrd
975  IF ( gridd(j,i) ) js = js + 1
976  END DO
977  jtot = max( jtot , js )
978  END DO
979  !
980  IF ( ALLOCATED(grdhgh) ) THEN
981  DEALLOCATE ( grdhgh, stat=istat )
982  check_dealloc_status( istat )
983  END IF
984  ALLOCATE ( grdhgh(nrgrd,0:jtot), stat=istat )
985  check_alloc_status( istat )
986  grdhgh = 0
987  !
988 #ifdef W3_T
989  WRITE (mdst,9040) jtot
990 #endif
991  !
992  ! 4.b Fill array
993  !
994  DO i=1, nrgrd ! low rank grid
995  jtot = 0
996  DO j=1, nrgrd
997  IF ( gridd(j,i) ) THEN ! grid j is of higher rank than grid i
998  ! *and* there is dependency
999  jtot = jtot + 1 ! count the number of grids of higher
1000  ! rank than grid i
1001  grdhgh(i,jtot) = j ! save the grid number of the higher rank grid
1002  END IF
1003  END DO
1004  grdhgh(i,0) = jtot ! save the count of higher ranked grids
1005  END DO
1006  !
1007 #ifdef W3_T
1008  WRITE (mdst,9041)
1009  DO i=1, nrgrd
1010  WRITE (mdst,9042) i, grdhgh(i,0:grdhgh(i,0))
1011  END DO
1012 #endif
1013  !
1014  ! -------------------------------------------------------------------- /
1015  ! 5. Export file flags
1016  !
1017  IF ( PRESENT(flrbpi) ) flrbpi = rfile
1018  !
1019  RETURN
1020  !
1021  ! Formats
1022  !
1023 1000 FORMAT (/' *** WAVEWATCH III ERROR IN WMGLOW : *** '/ &
1024  ' GRID NOT INITIALIZED, GRID NR',i4 /)
1025  !
1026 1020 FORMAT (/' *** WAVEWATCH III ERROR IN WMGLOW : *** '/ &
1027  ' CANNOT FIND SOURCE FOR BOUNDARY DATA '/ &
1028  ' GRID, IX, IY, X, Y:',3i6,2e12.4/)
1029  !
1030 1021 FORMAT (/' *** WAVEWATCH III ERROR IN WMGLOW : *** '/ &
1031  ' NONE OF BOUNDARY POINTS CAN BE MAPPED'/ &
1032  ' READING FROM FILE INSTEAD'/)
1033  !
1034 1030 FORMAT (/' *** WAVEWATCH III ERROR IN WMGLOW : *** '/ &
1035  ' RANKS AND RESOLUTIONS INCONSISTENT'/ &
1036  ' GRID',i4,' RANK',i4,' RESOLUTION :',4e10.3/ &
1037  ' GRID',i4,' RANK',i4,' RESOLUTION :',4e10.3/)
1038  !
1039 2000 FORMAT (/' *** WAVEWATCH-III WARNING : BOUNDARY POINT'/ &
1040  ' NOT FOUND IN LOWER RANK GRID : ',2f10.3/ &
1041  ' POINT SKIPPED '/)
1042  !
1043 2001 FORMAT (/' *** WAVEWATCH-III WARNING : BOUNDARY POINT'/ &
1044  ' NOT FOUND IN LOWER RANK GRID : ',2e10.3/ &
1045  ' POINT SKIPPED '/)
1046  !
1047 #ifdef W3_T
1048 9010 FORMAT ( ' TEST WMGLOW : ALL GRIDS INITIALIZED')
1049 #endif
1050  !
1051 #ifdef W3_T
1052 9020 FORMAT ( ' TEST WMGLOW : STARTING LOOP OVER GRIDS')
1053 9021 FORMAT ( ' TEST WMGLOW : I, RANK, NBI :',2i4,i6)
1054 9022 FORMAT ( ' ',a)
1055 #endif
1056 #ifdef W3_T1
1057 9023 FORMAT (' TEST WMGLOW : POINT DATA ')
1058 9024 FORMAT (i5,i8,2f6.1,4i5,4f5.2,i3,4i8)
1059 #endif
1060 #ifdef W3_T2
1061 9025 FORMAT (' TEST WMGLOW : NBI2S ')
1062 9026 FORMAT (' ',2i4,2x,i8)
1063 #endif
1064 #ifdef W3_T
1065 9027 FORMAT (' TEST WMGLOW : NBI, NBI2, RFILE, NBI2G ')
1066 9028 FORMAT (' ',2i5,l2,' : ',20i5)
1067 #endif
1068 #ifdef W3_T9
1069 9029 FORMAT (' TEST WMGLOW : SOURCE MAP GRID',i3,' PART',i3)
1070 #endif
1071  !
1072 #ifdef W3_T
1073 9030 FORMAT ( ' TEST WMGLOW : GRDLOW DIMENSIONED AT ',i2)
1074 9031 FORMAT ( ' TEST WMGLOW : GRDLOW :')
1075 9032 FORMAT ( ' ',2i4,' : ',20i3)
1076 #endif
1077  !
1078 #ifdef W3_T
1079 9040 FORMAT ( ' TEST WMGLOW : GRDHGH DIMENSIONED AT ',i2)
1080 9041 FORMAT ( ' TEST WMGLOW : GRDHGH :')
1081 9042 FORMAT ( ' ',2i4,' : ',20i3)
1082 #endif
1083  !/
1084  !/ End of WMGLOW ----------------------------------------------------- /
1085  !/

References w3gdatmd::clgtype, w3servmd::extcde(), w3gdatmd::flagll, wmmdatmd::grank, wmmdatmd::grdhgh, wmmdatmd::grdlow, w3gdatmd::grids, w3odatmd::iaproc, wmmdatmd::improc, include(), w3parall::init_get_jsea_isproc(), w3odatmd::ipbpi, w3triamd::is_in_ungrid(), w3odatmd::isbpi, w3gdatmd::mapfs, w3gdatmd::mapsf, w3gdatmd::mapsta, wmmdatmd::mdatas, wmmdatmd::mdse, wmmdatmd::mdst, wmmdatmd::mpi_comm_mwave, w3odatmd::naperr, w3odatmd::nbi, w3odatmd::nbi2, wmmdatmd::nbi2g, wmmdatmd::nbi2s, w3odatmd::ndse, w3gdatmd::nk, wmmdatmd::nmperr, w3gdatmd::nsea, w3gdatmd::nx, w3gdatmd::ny, w3odatmd::outpts, w3odatmd::rdbpi, w3gdatmd::rlgtype, w3gdatmd::sgrds, w3gdatmd::smctype, w3servmd::strace(), w3gdatmd::ungtype, w3odatmd::w3dmo5(), w3gdatmd::w3setg(), w3odatmd::w3seto(), w3odatmd::xbpi, w3gdatmd::xgrd, w3odatmd::ybpi, and w3gdatmd::ygrd.

Referenced by wminitmd::wminit(), and wminitmd::wminitnml().

◆ wmrspc()

subroutine wmgridmd::wmrspc

Generate map with flags for need of spectral grid conversion between models.

Test of parameters as introduced before in W3IOBC.

Author
H. L. Tolman
Date
10-Dec-2014

Definition at line 5139 of file wmgridmd.F90.

5139  !/
5140  !/ +-----------------------------------+
5141  !/ | WAVEWATCH III NOAA/NCEP |
5142  !/ | H. L. Tolman |
5143  !/ | FORTRAN 90 |
5144  !/ | Last update : 10-Dec-2014 !
5145  !/ +-----------------------------------+
5146  !/
5147  !/ 22-Sep-2005 : Origination. ( version 3.08 )
5148  !/ 25-Jul-2006 : Point output grid added. ( version 3.10 )
5149  !/ 30-Oct-2009 : Implement run-time grid selection. ( version 3.14 )
5150  !/ (W. E. Rogers & T. J. Campbell, NRL)
5151  !/ 10-Dec-2014 : Add checks for allocate status ( version 5.04 )
5152  !/
5153  ! 1. Purpose :
5154  !
5155  ! Generate map with flogs for need of spectral grid conversion
5156  ! between models.
5157  !
5158  ! 2. Method :
5159  !
5160  ! Test of parameters as introduced before in W3IOBC.
5161  !
5162  ! 3. Parameters :
5163  !
5164  ! 4. Subroutines used :
5165  !
5166  ! Name Type Module Description
5167  ! ----------------------------------------------------------------
5168  ! STRACE Sur. W3SERVMD Subroutine tracing.
5169  ! EXTCDE Subr. Id. Program abort.
5170  ! ----------------------------------------------------------------
5171  !
5172  ! 5. Called by :
5173  !
5174  ! Name Type Module Description
5175  ! ----------------------------------------------------------------
5176  ! WMINIT Subr WMINITMD Multi-grid model initialization.
5177  ! ----------------------------------------------------------------
5178  !
5179  ! 6. Error messages :
5180  !
5181  ! 7. Remarks :
5182  !
5183  ! 8. Structure :
5184  !
5185  ! See source code.
5186  !
5187  ! 9. Switches :
5188  !
5189  ! !/S Enable subroutine tracing.
5190  ! !/T Enable test output
5191  !
5192  ! 10. Source code :
5193  !
5194  !/ ------------------------------------------------------------------- /
5195  !
5196  USE w3servmd, ONLY: extcde
5197 #ifdef W3_S
5198  USE w3servmd, ONLY: strace
5199 #endif
5200  !
5201  USE w3gdatmd
5202  USE w3odatmd, ONLY: unipts
5203  USE wmmdatmd
5204  !
5205  IMPLICIT NONE
5206  !/
5207  !/ ------------------------------------------------------------------- /
5208  !/ Parameter list
5209  !/
5210  !/ ------------------------------------------------------------------- /
5211  !/ Local parameters
5212  !/
5213  INTEGER :: I, J, LOW
5214 #ifdef W3_S
5215  INTEGER, SAVE :: IENT = 0
5216 #endif
5217  !/
5218 #ifdef W3_S
5219  CALL strace (ient, 'WMRSPC')
5220 #endif
5221  !
5222  ! -------------------------------------------------------------------- /
5223  ! 0. Initializations
5224  !
5225  IF ( unipts ) THEN
5226  low = 0
5227  ELSE
5228  low = 1
5229  END IF
5230  IF ( .NOT. ALLOCATED(respec) ) THEN
5231  ALLOCATE ( respec(low:nrgrd,low:nrgrd), stat=istat )
5232  check_alloc_status( istat )
5233  END IF
5234  respec = .false.
5235  !
5236  ! -------------------------------------------------------------------- /
5237  ! 1. Fill map with flags
5238  !
5239  DO i=low, nrgrd
5240  DO j=i+1, nrgrd
5241  respec(i,j) = sgrds(i)%NK .NE. sgrds(j)%NK .OR. &
5242  sgrds(i)%NTH .NE. sgrds(j)%NTH .OR. &
5243  sgrds(i)%XFR .NE. sgrds(j)%XFR .OR. &
5244  sgrds(i)%FR1 .NE. sgrds(j)%FR1 .OR. &
5245  sgrds(i)%TH(1) .NE. sgrds(j)%TH(1)
5246  respec(j,i) = respec(i,j)
5247  END DO
5248  END DO
5249  !
5250  ! -------------------------------------------------------------------- /
5251  ! 2. Test output
5252  !
5253 #ifdef W3_T
5254  WRITE (mdst,9000)
5255  DO i=low, nrgrd
5256  WRITE (mdst,9001) i, respec(i,:)
5257  END DO
5258 #endif
5259  !
5260  RETURN
5261  !
5262  ! Formats
5263  !
5264 #ifdef W3_T
5265 9000 FORMAT ( 'TEST WMRSPC : MAP RESPEC FILLED ')
5266 9001 FORMAT ( ' ',i4,' : ',20l2)
5267 #endif
5268  !/
5269  !/ End of WMRSPC ----------------------------------------------------- /
5270  !/

References w3servmd::extcde(), wmmdatmd::mdst, wmmdatmd::nrgrd, wmmdatmd::respec, w3gdatmd::sgrds, w3servmd::strace(), and w3odatmd::unipts.

Referenced by wminitmd::wminit(), and wminitmd::wminitnml().

◆ wmsmceql()

subroutine wmgridmd::wmsmceql

Determine relations to same ranked SMC grids for each grid.

Set boundary points update for regular grid in same ranked group.

Cross mapping of grid points, use nearest sea points and no interpolation is required so far.

Author
J G Li
Date
12-Apr-2021

Definition at line 5285 of file wmgridmd.F90.

5285  !!
5286  !! Adapted from multi-grid sub WMGEQL for set up equal ranked SMC
5287  !! grid boundary points. JGLi10Aug2020
5288  !! Move boundary point matching to sub-grid root PEs and broadcast to
5289  !! all other PEs. JGLi02Dec2020
5290  !! Clear bugs for 3 sub-grids case and finalise output messages.
5291  !! JGLi26Jan2021
5292  !! Add regular grid to SMC grid same ranked group.
5293  !! JGLi12Apr2021
5294  !!
5295  ! 1. Purpose :
5296  !
5297  ! Determine relations to same ranked SMC grids for each grid.
5298  ! Set boundary points update for regular grid in same ranked group.
5299  !
5300  ! 2. Method :
5301  !
5302  ! Cross mapping of grid points, use nearest sea points and no
5303  ! interpolation is required so far.
5304  !
5305  ! 3. Parameters :
5306  !
5307  ! 4. Subroutines used :
5308  !
5309  ! Name Type Module Description
5310  ! ----------------------------------------------------------------
5311  ! W3SETG, W3SETO, WMSETM
5312  ! Subr. W3GDATMD Manage data structures.
5313  ! W3SMCGMP, Subr. W3PSMCMD Mapping Lon-Lat points to SMC grid cells.
5314  ! W3SMCELL, Subr. W3PSMCMD Find Lon-Lat for SMC grid cell centre.
5315  ! STRACE Subr. W3SERVMD Subroutine tracing.
5316  ! EXTCDE Subr. Id. Program abort.
5317  ! ----------------------------------------------------------------
5318  !
5319  ! 5. Called by :
5320  !
5321  ! 6. Error messages :
5322  !
5323  ! 7. Remarks :
5324  !
5325  ! SMC J sub-grid has own boundary cell number W3GDATMD's NBSMC and
5326  ! their ID list are stored in W3GDATMD's GRIDS(J)%ISMCBP(NBSMC),
5327  ! which are the global ISEA values of the NBSMC boundary cells.
5328  ! So there is no need to look for boundary points, but just
5329  ! fetching the boundary cell list from each SMC sub-grid.
5330  ! No interpolation is required as one to one correspondance is
5331  ! assumed among SMC sub-grid boundary points. JGLi06Nov2020
5332  ! Sub WMIOEG and WMIOES are modified to use the new EQSTGE array
5333  ! for same ranked SMC sub-grids only. JGLi26Jan2021
5334  !
5335  ! 8. Structure :
5336  !
5337  ! 9. Switches :
5338  !
5339  ! !/PRn Propagation scheme.
5340  ! !/SMC For SMC grid.
5341  !
5342  ! !/S Enable subroutine tracing.
5343  ! !/T Enable test output.
5344  !
5345  ! !/MPI Distribbuted memory management.
5346  ! !/SHRD Shared memory case.
5347  !
5348  ! 10. Source code :
5349  !
5350  !/ ------------------------------------------------------------------- /
5351  !
5352  USE constants
5353  USE w3gdatmd
5354  USE w3odatmd
5355  USE w3adatmd
5356  USE wmmdatmd
5357  !
5358  USE w3servmd, ONLY: extcde
5359 #ifdef W3_SMC
5360  USE w3psmcmd, ONLY: w3smcgmp, w3smcell
5361 #endif
5362 
5363 #ifdef W3_S
5364  USE w3servmd, ONLY: strace
5365 #endif
5366  !
5367  IMPLICIT NONE
5368  !
5369 #ifdef W3_MPI
5370  include "mpif.h"
5371 #endif
5372  !/
5373  !/ ------------------------------------------------------------------- /
5374  !/ Parameter list
5375  !/
5376  !/ ------------------------------------------------------------------- /
5377  !/ Local parameters
5378  !/
5379  INTEGER :: I, J, IX, IY, IXY, JX, JY, NPJ, &
5380  NR, NT, NA, NTL, JJ, NIT, NG, NOUT, &
5381  ISEA, JSEA, IPRC, ITAG, TGRP, NPMX, &
5382  IP, NP, ICROOT, JCROOT, IEER
5383 
5384 #ifdef W3_MPI
5385  INTEGER, Dimension(MPI_STATUS_SIZE):: MPIState
5386 #endif
5387 
5388 #ifdef W3_S
5389  INTEGER, SAVE :: IENT = 0
5390 #endif
5391  INTEGER, ALLOCATABLE :: NREC(:), NSND(:), NTPP(:), &
5392  IBPTS(:), JBPTS(:), IPBPT(:)
5393  REAL, PARAMETER :: ODIMAX = 25.
5394  REAL, ALLOCATABLE :: XLon(:), YLat(:)
5395  LOGICAL :: CHANGE
5396  LOGICAL, ALLOCATABLE :: SHRANK(:,:), DOGRID(:)
5397 #ifdef W3_T5
5398  CHARACTER(LEN=18), ALLOCATABLE :: TSTR(:)
5399  CHARACTER(LEN=18) :: DSTR
5400 #endif
5401  !
5402  TYPE store
5403  INTEGER :: NTOT, NFIN
5404  INTEGER, POINTER :: ICVBP(:), MSDBP(:), ISS(:), JSS(:), &
5405  JCVBP(:), IPCVB(:), IPS(:), ITG(:)
5406  LOGICAL, POINTER :: FLA(:)
5407  LOGICAL :: INIT
5408  END TYPE store
5409  !
5410  TYPE(STORE), ALLOCATABLE :: STORES(:,:)
5411  !/
5412 #ifdef W3_S
5413  CALL strace (ient, 'WMSMCEQL ')
5414 #endif
5415  !
5416  ! -------------------------------------------------------------------- /
5417  ! 0. Initializations
5418  !
5419  ALLOCATE ( shrank(nrgrd,nrgrd), stores(nrgrd,nrgrd), &
5420  dogrid(nrgrd), stat=istat )
5421  check_alloc_status( istat )
5422  !
5423  shrank = .false.
5424  !
5425  DO i=1, nrgrd
5426 
5427  DO j=1, nrgrd
5428  stores(i,j)%INIT = .false.
5429  stores(i,j)%NTOT = 0
5430  stores(i,j)%NFIN = 0
5431  END DO
5432  END DO
5433  !
5434  itag = 0
5435  !
5436  ! -------------------------------------------------------------------- /
5437  ! 1. Grid point relations and temp data storage
5438  ! 1.a Outer loop over all grids
5439  !
5440 #ifdef W3_T
5441  WRITE (mdst,9010)
5442 #endif
5443  !
5444  DO i=1, nrgrd
5445 
5446 #ifdef W3_T
5447  WRITE (mdst,9011) i, grank(i)
5448 #endif
5449  !
5450  ! 1.b Find sub grids with same rank
5451  !
5452  nr = 0
5453  !
5454  DO j=1, nrgrd
5455  IF( (grank(i).NE.grank(j)) .OR. (i.EQ.j) ) cycle
5456  shrank(i,j) = .true.
5457  nr = nr + 1
5458  END DO
5459  !
5460  dogrid(i) = nr .GT. 0
5461  !
5462  IF( nr .EQ. 0 ) cycle
5463  !
5464  CALL w3setg( i, mdse, mdst )
5465  !
5466  ! Find local root PE and NAPROC for I grid.
5467 #ifdef W3_SHRD
5468  icroot = 1
5469 #endif
5470 #ifdef W3_MPI
5471  icroot = mdatas(i)%CROOT
5472 #endif
5473  np = outpts(i)%NAPROC
5474  !
5475  ! 1.c Fetch Grid I boundary points.
5476  !
5477  nt = 0
5478  IF( grids(i)%GTYPE .EQ. rlgtype ) THEN
5479  ! 1.c.1 Regular grid I boundary points are stored in NBI.
5480  nt = outpts(i)%OUT5%NBI
5481 #ifdef W3_MPI
5482  IF( improc .EQ. icroot ) THEN
5483 #endif
5484  WRITE(mdse,*) "ICROOT, NT are", icroot, nt
5485 #ifdef W3_MPI
5486  ENDIF
5487 #endif
5488  !
5489  ! 1.c.2 SMC grid I boundary cell ids are saved in NBSMC.
5490 #ifdef W3_SMC
5491  ELSEIF( grids(i)%GTYPE .EQ. smctype ) THEN
5492 #endif
5493 #ifdef W3_MPI
5494 #ifdef W3_SMC
5495  IF( improc .EQ. icroot ) THEN
5496 #endif
5497 #endif
5498 #ifdef W3_SMC
5499  nt = grids(i)%NBSMC
5500  WRITE(mdse,*) "ICROOT, NT are", icroot, nt
5501 #endif
5502 #ifdef W3_MPI
5503 #ifdef W3_SMC
5504  ENDIF
5505 #endif
5506 #endif
5507 
5508 #ifdef W3_MPI
5509 #ifdef W3_SMC
5510  CALL mpi_bcast( nt, 1, mpi_integer, &
5511  icroot-1, mpi_comm_mwave, ieer)
5512 #endif
5513 #endif
5514 
5515  ! Need to wait for all PEs get these values.
5516 #ifdef W3_MPI
5517 #ifdef W3_SMC
5518  CALL mpi_barrier (mpi_comm_mwave,ieer)
5519 #endif
5520 #endif
5521  !
5522  ENDIF !! GTYPE .EQ. RLGTYPE
5523  !
5524  IF( nt .EQ. 0 ) cycle
5525 
5526  IF( nt > 0 ) THEN
5527  ALLOCATE( ibpts(nt), jbpts(nt), ipbpt(nt), &
5528  xlon(nt), ylat(nt), stat=istat )
5529  check_alloc_status( istat )
5530 
5531  ! Use saved I-grid boundary cell list.
5532 #ifdef W3_MPI
5533  IF( improc .EQ. icroot ) THEN
5534 #endif
5535  IF( grids(i)%GTYPE .EQ. rlgtype ) THEN
5536  !! Loop over regular grid mesh to find boundary points.
5537  ixy = 0
5538  DO isea=1, nsea
5539  ix = mapsf(isea, 1)
5540  iy = mapsf(isea, 2)
5541  IF( abs(mapsta(iy,ix)) .EQ. 2 ) THEN
5542  ixy = ixy + 1
5543  xlon(ixy) = real(xgrd(iy,ix))
5544  ylat(ixy) = real(ygrd(iy,ix))
5545  ibpts(ixy) = isea
5546  jbpts(ixy) = 1 + (isea - 1)/np
5547  ipbpt(ixy) = icroot-1 + isea-(jbpts(ixy)-1)*np
5548  ENDIF
5549  ENDDO
5550  !
5551 #ifdef W3_SMC
5552  ELSEIF( grids(i)%GTYPE .EQ. smctype ) THEN
5553 
5554  ibpts = grids(i)%ISMCBP(1:nt)
5555  CALL w3smcell( i, nt, ibpts, xlon, ylat )
5556  DO ix = 1, nt
5557 #endif
5558  ! Global processor IPBPT and local JSEA, for ISEA spectrum in I grid.
5559 #ifdef W3_SMC
5560  isea = ibpts(ix)
5561  jsea = 1 + (isea - 1)/np
5562  ipbpt(ix) = icroot - 1 + isea - (jsea - 1)*np
5563  jbpts(ix) = jsea
5564  ENDDO
5565 #endif
5566  !
5567  ENDIF !! RLGTYPE
5568 #ifdef W3_MPI
5569  ENDIF !! ICROOT
5570 #endif
5571  !
5572  ! All have to wait for ICROOT finishes conversion of cell ids to XLon-YLat
5573 #ifdef W3_MPI
5574  CALL mpi_barrier (mpi_comm_mwave,ieer)
5575 #endif
5576  !
5577  ! Then broadcast IBPTS, IPBPT, XLon, and YLat to all PEs
5578 #ifdef W3_MPI
5579  CALL mpi_bcast( ibpts(1), nt, mpi_integer, &
5580  icroot-1, mpi_comm_mwave, ieer)
5581  CALL mpi_bcast( jbpts(1), nt, mpi_integer, &
5582  icroot-1, mpi_comm_mwave, ieer)
5583  CALL mpi_bcast( ipbpt(1), nt, mpi_integer, &
5584  icroot-1, mpi_comm_mwave, ieer)
5585  CALL mpi_bcast( xlon(1), nt, mpi_real, &
5586  icroot-1, mpi_comm_mwave, ieer)
5587  CALL mpi_bcast( ylat(1), nt, mpi_real, &
5588  icroot-1, mpi_comm_mwave, ieer)
5589 #endif
5590 
5591  ! 1.d Loop over J grids, select same rank
5592  !
5593  DO j=1, nrgrd
5594 
5595  IF( .NOT. shrank(i,j) ) cycle
5596  !! Only SMC J-grid provides boundary spectra for I-Grid.
5597  IF( grids(j)%GTYPE .NE. smctype ) cycle
5598  !
5599  ! Find local root PE and NAPROC for J grid.
5600 #ifdef W3_SHRD
5601  jcroot = 1
5602 #endif
5603 #ifdef W3_MPI
5604  jcroot = mdatas(j)%CROOT
5605 #endif
5606  npj = outpts(j)%NAPROC
5607  !
5608  ! Find out whether any I-grid boundary points matched in J-Grid.
5609  !
5610  stores(i,j)%INIT = .true.
5611  ALLOCATE( stores(i,j)%ICVBP(nt), stores(i,j)%MSDBP(nt), &
5612  stores(i,j)%JCVBP(nt), stores(i,j)%IPCVB(nt), &
5613  stores(i,j)%ISS(nt), stores(i,j)%JSS(nt), &
5614  stores(i,j)%IPS(nt), stores(i,j)%ITG(nt), &
5615  stores(i,j)%FLA(nt), stat=istat )
5616  check_alloc_status( istat )
5617  stores(i,j)%ICVBP = 0
5618  stores(i,j)%JCVBP = 0
5619  stores(i,j)%IPCVB = 0
5620  stores(i,j)%MSDBP = 0
5621  stores(i,j)%ISS = 0
5622  stores(i,j)%JSS = 0
5623  stores(i,j)%IPS = 0
5624  stores(i,j)%ITG = 0
5625  stores(i,j)%FLA = .false.
5626  !
5627  ! Work out which I-grid bounary points are matched in J-grid on JCROOT.
5628 #ifdef W3_MPI
5629 #ifdef W3_SMC
5630  IF( improc .EQ. jcroot ) THEN
5631 #endif
5632 #endif
5633 #ifdef W3_SMC
5634  CALL w3smcgmp( j, nt, xlon, ylat, stores(i,j)%MSDBP )
5635 #endif
5636 #ifdef W3_MPI
5637 #ifdef W3_SMC
5638  ENDIF
5639 #endif
5640 #endif
5641  !
5642  ! Then broadcast the results to all PEs
5643 #ifdef W3_MPI
5644 #ifdef W3_SMC
5645  CALL mpi_bcast( stores(i,j)%MSDBP(1), nt, mpi_integer, &
5646  jcroot-1, mpi_comm_mwave, ieer)
5647 #endif
5648 #endif
5649  !
5650  ! Need to wait for all PEs get these values.
5651 #ifdef W3_MPI
5652 #ifdef W3_SMC
5653  CALL mpi_barrier( mpi_comm_mwave, ieer)
5654 #endif
5655 #endif
5656  !
5657 #ifdef W3_SMC
5658  stores(i,j)%ICVBP = ibpts
5659  stores(i,j)%JCVBP = jbpts
5660  stores(i,j)%IPCVB = ipbpt
5661 #endif
5662  !
5663  ! Check which I-grid boundary points matched inside J-Grid
5664  ntl= 0
5665  DO jx=1, nt
5666  IF( stores(i,j)%MSDBP(jx) .EQ. 0 ) cycle
5667 
5668  ! Process J-grid send point if it matches I-grid boundary point.
5669  ntl = ntl + 1
5670  itag = itag + 1
5671  isea = stores(i,j)%MSDBP(jx)
5672  ! Find global processor IPRC and local JSEA on J-grid, holding ISEA spectrum.
5673  jsea = 1 + (isea - 1)/npj
5674  iprc = jcroot - 1 + isea - (jsea - 1)*npj
5675  ! Store these spectral location info in STORES.
5676  stores(i,j)%ISS(jx) = isea
5677  stores(i,j)%JSS(jx) = jsea
5678  stores(i,j)%IPS(jx) = iprc
5679  stores(i,j)%ITG(jx) = itag
5680  stores(i,j)%FLA(jx) = .true.
5681  END DO
5682  !
5683  ! SMC grid boundary points are supposed to be 1 to 1 correspondant
5684  ! so there is no need for interpolation. JGLi03Nov2020
5685  !
5686  stores(i,j)%NTOT = nt
5687  stores(i,j)%NFIN = ntl
5688  !
5689 #ifdef W3_MPI
5690 #ifdef W3_SMC
5691  IF( improc .EQ. nmperr ) &
5692 #endif
5693 #endif
5694 #ifdef W3_SMC
5695  WRITE(mdse,1060) i, nt, j, ntl
5696 #endif
5697  !
5698  ! ... End of loops J in 1.c
5699  END DO
5700  !
5701  !! Free temporary space for I-grid.
5702  DEALLOCATE( ibpts, jbpts, ipbpt, xlon, ylat, stat=istat )
5703  check_dealloc_status( istat )
5704 
5705  END IF ! NT > 0
5706  !
5707  ! ... End of 1.a loop I grid.
5708  END DO
5709  !
5710  ! -------------------------------------------------------------------- /
5711  ! 3. Final data base (full data base, scratched at end of routine)
5712  ! 3.a Loop over grids
5713  !
5714  ALLOCATE( nrec(nrgrd), nsnd(nrgrd), ntpp(nmproc), stat=istat )
5715  check_alloc_status( istat )
5716  !
5717  DO i=1, nrgrd
5718  IF ( .NOT. dogrid(i) ) cycle
5719 #ifdef W3_T
5720  WRITE (mdst,9030) i
5721 #endif
5722  !
5723  CALL w3setg ( i, mdse, mdst )
5724  CALL w3seto ( i, mdse, mdst )
5725  CALL wmsetm ( i, mdse, mdst )
5726  !
5727  nrec = 0
5728  nsnd = 0
5729  !
5730  ! Find local root PE and maximum PE for I grid.
5731 #ifdef W3_SHRD
5732  icroot = 1
5733 #endif
5734 #ifdef W3_MPI
5735  icroot = mdatas(i)%CROOT
5736 #endif
5737  npmx = outpts(i)%NAPROC + icroot - 1
5738  !
5739  ! 3.b Filling NREC and NSND for grid I
5740  !
5741  !! Work out how many I-grid boundary points to be updated by other grids.
5742  !! Use matched J-grid points to selected I-grid points. JGLi26Jan2021
5743  DO j=1, nrgrd
5744  IF( .NOT. shrank(i,j) ) cycle
5745  IF( stores(i,j)%NFIN > 0 ) THEN
5746  DO ix = 1, stores(i,j)%NTOT
5747  IF( stores(i,j)%MSDBP(ix) > 0 .AND. &
5748  stores(i,j)%IPCVB(ix) .EQ. improc ) THEN
5749  nrec(i) = nrec(i) + 1
5750  nrec(j) = nrec(j) + 1
5751  END IF
5752  END DO
5753  END IF
5754  END DO
5755 
5756  ! Accumulate all related I-Grid points to be send to other sub-grids.
5757  ! Add IPRC range check to ensure sending from I-grid. JGLi22Jan2021
5758  DO j=1, nrgrd
5759  IF( .NOT. shrank(j,i) ) cycle
5760  IF( stores(j,i)%NFIN > 0 ) THEN
5761  DO iy=1, stores(j,i)%NTOT
5762  IF( stores(j,i)%MSDBP(iy) > 0 .AND. &
5763  stores(j,i)%IPS( iy) .EQ. improc ) THEN
5764  nsnd(j) = nsnd(j) + 1
5765  ENDIF
5766  END DO
5767  END IF
5768  END DO
5769  !
5770  ! -------------------------------------------------------------------- /
5771  ! 4. Save data base as needed in EQSTGE
5772  !
5773  ! 4.a ALLOCATE storage
5774  ! 4.a.1 Local counters, weights and sea counters (grid 'I')
5775  !
5776  IF( eqstge(i,i)%NREC .NE. 0 ) THEN
5777  DEALLOCATE (eqstge(i,i)%ISEA, eqstge(i,i)%JSEA , &
5778  eqstge(i,i)%WGHT, stat=istat )
5779  check_dealloc_status( istat )
5780  eqstge(i,i)%NREC = 0
5781 #ifdef W3_T
5782  WRITE (mdst,9040) i, i
5783 #endif
5784  END IF
5785  !
5786  IF( nrec(i) .GT. 0 ) THEN
5787  ALLOCATE( eqstge(i,i)%ISEA(nrec(i)), &
5788  eqstge(i,i)%JSEA(nrec(i)), &
5789  eqstge(i,i)%WGHT(nrec(i)), stat=istat )
5790  check_alloc_status( istat )
5791  eqstge(i,i)%NREC = nrec(i)
5792 #ifdef W3_T
5793  WRITE (mdst,9041) i, i, nrec(i)
5794 #endif
5795  END IF
5796  !
5797  !! Initial NTOT for grid I before summing over other grids. JGLi18Jan2021
5798  eqstge(i,i)%NTOT = 0
5799  !
5800  ! 4.a.1 Local counters, arrays weights etc. (grid 'J' receive)
5801  !
5802  DO j=1, nrgrd
5803  IF( i .EQ. j ) cycle
5804  !
5805  !! Looks strange to store in EQSTGE(I,I) as other J-grid may
5806  !! overwrite the value. Should be suspended? JGLi30Dec2020
5807  ! EQSTGE(I,I)%NTOT = STORES(I,J)%NFIN
5808  !! Changed to summation ove all other J-grids NFIN. Not sure where
5809  !! NTOT is used but keep it anyway. JGLi18Jan2021
5810  eqstge(i,i)%NTOT = eqstge(i,i)%NTOT + stores(i,j)%NFIN
5811  !
5812  IF( eqstge(i,j)%NREC .NE. 0 ) THEN
5813  DEALLOCATE( eqstge(i,j)%ISEA , eqstge(i,j)%JSEA , &
5814  eqstge(i,j)%WGHT , eqstge(i,j)%SEQL , &
5815  eqstge(i,j)%NAVG , eqstge(i,j)%WAVG , &
5816  eqstge(i,j)%RIP , eqstge(i,j)%RTG, &
5817  stat=istat )
5818  check_dealloc_status( istat )
5819  eqstge(i,j)%NREC = 0
5820  eqstge(i,j)%NAVMAX = 1
5821  END IF
5822  !
5823  IF( nrec(j) .GT. 0 ) THEN
5824  na = 1
5825  eqstge(i,j)%NAVMAX = na
5826  ALLOCATE( eqstge(i,j)%ISEA(nrec(j)), &
5827  eqstge(i,j)%JSEA(nrec(j)), &
5828  eqstge(i,j)%WGHT(nrec(j)), &
5829  eqstge(i,j)%SEQL(sgrds(j)%NSPEC,nrec(j),na), &
5830  eqstge(i,j)%NAVG(nrec(j)), &
5831  eqstge(i,j)%WAVG(nrec(j),na), &
5832  eqstge(i,j)%RIP( nrec(j),na), &
5833  eqstge(i,j)%RTG( nrec(j),na), stat=istat )
5834  check_alloc_status( istat )
5835  eqstge(i,j)%NREC = nrec(j)
5836  END IF
5837  !
5838  IF( eqstge(j,i)%NSND .NE. 0 ) THEN
5839  DEALLOCATE( eqstge(j,i)%SIS, eqstge(j,i)%SJS , &
5840  eqstge(j,i)%SI1, eqstge(j,i)%SI2 , &
5841  eqstge(j,i)%SIP, eqstge(j,i)%STG, stat=istat)
5842  check_dealloc_status( istat )
5843  eqstge(j,i)%NSND = 0
5844  END IF
5845  !
5846  IF( nsnd(j) .GT. 0 ) THEN
5847  ALLOCATE( eqstge(j,i)%SIS(nsnd(j)), &
5848  eqstge(j,i)%SJS(nsnd(j)), &
5849  eqstge(j,i)%SI1(nsnd(j)), &
5850  eqstge(j,i)%SI2(nsnd(j)), &
5851  eqstge(j,i)%SIP(nsnd(j)), &
5852  eqstge(j,i)%STG(nsnd(j)), stat=istat )
5853  check_alloc_status( istat )
5854  eqstge(j,i)%NSND = nsnd(j)
5855  END IF
5856  !
5857  END DO
5858  !
5859  ! 4.b Store data in EQSTGE
5860  ! 4.b.1 Grid I (JSEA and weight only) also filled in J-Grid loop
5861  ! but it accumulates all points received by I-grid.
5862  nt = 0
5863  !
5864  ! 4.b.2 Info for I-grid receiving from all other grids
5865  DO j=1, nrgrd
5866  IF( .NOT. shrank(i,j) ) cycle
5867  IF( eqstge(i,j)%NREC .EQ. 0 ) cycle
5868  ntl = 0
5869  DO ix=1, stores(i,j)%NTOT
5870  IF( stores(i,j)%MSDBP(ix) > 0 .AND. &
5871  stores(i,j)%IPCVB(ix) .EQ. improc ) THEN
5872  ! All points received by I-grid accumulated from each J-grid.
5873  nt = nt + 1
5874  eqstge(i,i)%ISEA(nt) = stores(i,j)%ICVBP(ix)
5875  eqstge(i,i)%JSEA(nt) = stores(i,j)%JCVBP(ix)
5876  ! No need to alter local spectra for SMC grid. JGLi08Dec2020
5877  eqstge(i,i)%WGHT(nt) = 1.0
5878 
5879  ! Boundary points received by I-grid from J-grid.
5880  ntl = ntl + 1
5881  eqstge(i,j)%ISEA(ntl) = stores(i,j)%ICVBP(ix)
5882  eqstge(i,j)%JSEA(ntl) = stores(i,j)%JCVBP(ix)
5883  !! Boundary spectra will be substituted fully. JGLi08Dec2020
5884  eqstge(i,j)%WGHT(ntl) = 1.0
5885  eqstge(i,j)%NAVG(ntl) = 1
5886  eqstge(i,j)%WAVG(ntl,1) = 1.0
5887  eqstge(i,j)%RIP (ntl,1) = stores(i,j)%IPS(ix)
5888  eqstge(i,j)%RTG (ntl,1) = stores(i,j)%ITG(ix)
5889  END IF
5890  END DO
5891 
5892  END DO
5893  !
5894  ! 4.b.3 All other grids, info for sending
5895  !
5896  DO j=1, nrgrd
5897  IF ( .NOT. shrank(j,i) ) cycle
5898  IF ( eqstge(j,i)%NSND .EQ. 0 ) cycle
5899  ntpp = 0
5900  ntl = 0
5901  DO iy =1, stores(j,i)%NTOT
5902  IF( stores(j,i)%MSDBP(iy) > 0 ) THEN
5903  iprc=stores(j,i)%IPS( iy)
5904  ntpp(iprc) = ntpp(iprc) + 1
5905  IF( iprc .EQ. improc ) THEN
5906  ntl = ntl + 1
5907  eqstge(j,i)%SIS(ntl) = stores(j,i)%ISS(iy)
5908  eqstge(j,i)%SJS(ntl) = stores(j,i)%JSS(iy)
5909  eqstge(j,i)%SI1(ntl) = ntpp(iprc)
5910  eqstge(j,i)%SI2(ntl) = 1
5911  eqstge(j,i)%SIP(ntl) = stores(j,i)%IPCVB(iy)
5912  eqstge(j,i)%STG(ntl) = stores(j,i)%ITG(iy)
5913  END IF
5914  END IF
5915  END DO
5916  !
5917  END DO
5918  !
5919  ! End of 3.a loop for I grid.
5920  END DO
5921  !
5922  ! -------------------------------------------------------------------- /
5923  ! 5. Generate GRDEQL
5924  ! 5.a Size of array
5925  !
5926  nrec = 0
5927  !
5928  DO i=1, nrgrd
5929  DO j=1, nrgrd
5930  IF ( i.EQ.j .OR. stores(i,j)%NFIN.EQ.0 ) cycle
5931  nrec(i) = nrec(i) + 1
5932  END DO
5933  END DO
5934  !
5935  na = maxval(nrec)
5936  ALLOCATE( grdeql(nrgrd,0:na), stat=istat )
5937  check_alloc_status( istat )
5938  grdeql = 0
5939  !
5940 #ifdef W3_T
5941  WRITE (mdst,9050) na
5942 #endif
5943  !
5944  ! 5.b Fill array
5945  !
5946  DO i=1, nrgrd
5947  grdeql(i,0) = nrec(i)
5948  jj = 0
5949  DO j=1, nrgrd
5950  IF ( i.EQ.j .OR. stores(i,j)%NFIN.EQ.0 ) cycle
5951  jj = jj + 1
5952  grdeql(i,jj) = j
5953  END DO
5954  END DO
5955  !
5956 #ifdef W3_T
5957  WRITE (mdst,9051)
5958  DO i=1, nrgrd
5959  WRITE (mdst,9052) i, grdeql(i,0:grdeql(i,0))
5960  END DO
5961 #endif
5962  !
5963  ! 5.d Group number test
5964  !
5965  DO i=1, nrgrd
5966  IF( grdeql(i,0) .GE. 2 ) THEN
5967  tgrp = grgrp(grdeql(i,1))
5968  DO j=2, grdeql(i,0)
5969  IF( grgrp(grdeql(i,j)) .NE. tgrp ) THEN
5970  IF( improc .EQ. nmperr ) WRITE(mdse,1051) &
5971  grdeql(i,1), grgrp(grdeql(i,1)), &
5972  grdeql(i,j), grgrp(grdeql(i,j))
5973  CALL extcde ( 1051 )
5974  END IF
5975  END DO
5976  END IF
5977  END DO
5978  !
5979  ! Wait all PEs finishing EQSTGE setup before clean up. JGLi20Jan2021
5980 #ifdef W3_MPI
5981 #ifdef W3_SMC
5982  CALL mpi_barrier (mpi_comm_mwave,ieer)
5983 #endif
5984 #endif
5985  ! -------------------------------------------------------------------- /
5986  ! 6. Final clean up
5987  !
5988  DO i=1, nrgrd
5989  DO j=1, nrgrd
5990  IF( stores(i,j)%INIT ) THEN
5991  DEALLOCATE( stores(i,j)%ICVBP, stores(i,j)%MSDBP, &
5992  stores(i,j)%JCVBP, stores(i,j)%IPCVB, &
5993  stores(i,j)%ISS , stores(i,j)%JSS , &
5994  stores(i,j)%IPS , stores(i,j)%ITG , &
5995  stores(i,j)%FLA , stat=istat )
5996  check_dealloc_status( istat )
5997  END IF
5998  END DO
5999  END DO
6000  !
6001  DEALLOCATE( shrank, stores, nrec, nsnd, ntpp, stat=istat )
6002  check_dealloc_status( istat )
6003  !
6004 #ifdef W3_MPI
6005 #ifdef W3_SMC
6006  IF( improc .EQ. nmperr ) &
6007 #endif
6008 #endif
6009 #ifdef W3_SMC
6010  WRITE(mdse,*) " *** WMSMCEQL completed from PE ", improc
6011 #endif
6012 
6013  RETURN
6014  !
6015  ! Formats
6016  !
6017 1000 FORMAT (/' *** WAVEWATCH III ERROR IN WMSMCEQL : *** '/ &
6018  ' UNCOVERED EDGE POINTS FOR GRID',i4,' (',i6,')'/)
6019 1001 FORMAT ( ' GRID',i4,' POINT',2i5,' NOT COVERED (WMGEQL)')
6020 1002 FORMAT ( ' DIAGNOSTICS IX AND IY RANGE:',4i6)
6021 1003 FORMAT (/' SHOWING ',a/)
6022 1004 FORMAT (2x,65i2)
6023 1005 FORMAT (/' SHOWING IX RANGE ',2i6)
6024 1006 FORMAT ( ' (WILL NOT PRINT ANY MORE UNCOVERED POINTS)')
6025  !
6026 1020 FORMAT (/' *** WAVEWATCH III WARNING WMSMCEQL : *** '/ &
6027  ' REMOVED BOUNDARY POINT FROM OPEN EDGE DISTANCE MAP'/ &
6028  ' GRID, IX, IY :',3i6)
6029  !
6030 1050 FORMAT (/' *** WAVEWATCH III ERROR IN WMSMCEQL : *** '/ &
6031  ' GRID INCREMENTS TOO DIFFERENT '/ &
6032  ' GRID',i4,' INCREMENTS ',2f8.2/ &
6033  ' GRID',i4,' INCREMENTS ',2f8.2/)
6034 1051 FORMAT (/' *** WAVEWATCH III ERROR IN WMSMCEQL : *** '/ &
6035  ' OVERLAPPING GRIDS NEED TO BE IN SAME GROUP '/ &
6036  ' GRID',i4,' IN GROUP',i4/ &
6037  ' GRID',i4,' IN GROUP',i4/)
6038 1060 FORMAT (' Grid NBPI from',2i6,' found in',2i6)
6039 
6040  !
6041 #ifdef W3_T
6042 9010 FORMAT ( ' TEST WMSMCEQL : STARTING LOOP OVER GRIDS')
6043 9011 FORMAT ( ' TEST WMSMCEQL : I, RANK :',2i4)
6044 9012 FORMAT ( ' GRID ',i3,' HAS SAME RANK')
6045 9013 FORMAT ( ' ',a)
6046 #endif
6047  !
6048 #ifdef W3_T
6049 9020 FORMAT ( ' TEST WMSMCEQL : GENERATING DISTANCE MAP GRID ',i3)
6050 9024 FORMAT ( ' TEST WMSMCEQL : FINAL MAP FOR X RANGE ',2i6)
6051 9025 FORMAT (2x,65i2)
6052 #endif
6053  !
6054 #ifdef W3_T
6055 9030 FORMAT ( ' TEST WMSMCEQL : DEPENDENCE INFORMATION GRID ',i3)
6056 9031 FORMAT ( ' CHECKING GRID ',i3)
6057 9032 FORMAT ( ' POINTS USED/AVAIL :',2i6)
6058 9033 FORMAT ( ' TOTAL/GRIDS/OUT :',3i6)
6059 9034 FORMAT ( ' LOCAL PER GRID :',15i6)
6060 9035 FORMAT ( ' SENDING PER GRID :',15i6)
6061 9036 FORMAT ( ' TEST WMSMCEQL : NUMBER OF CONTRIBUTING GRIDS MAP')
6062 9037 FORMAT (2x,65i2)
6063 #endif
6064  !
6065 #ifdef W3_T
6066 9040 FORMAT ( ' TEST WMSMCEQL : GRID ',i2,'-',i2,' CLEAR STORAGE')
6067 9041 FORMAT ( ' TEST WMSMCEQL : GRID ',i2,'-',i2,' STORAGE SIZE',i6)
6068 9042 FORMAT ( ' RECV ',i2,'-',i2,' CLEAR STORAGE')
6069 9043 FORMAT ( ' RECV ',i2,'-',i2,' STORAGE SIZE',2i6)
6070 9044 FORMAT ( ' SEND ',i2,'-',i2,' CLEAR STORAGE')
6071 9045 FORMAT ( ' SEND ',i2,'-',i2,' STORAGE SIZE',i6)
6072 #endif
6073  !
6074 #ifdef W3_T
6075 9050 FORMAT ( ' TEST WMSMCEQL : GRDEQL DIMENSIONED AT ',i2)
6076 9051 FORMAT ( ' TEST WMSMCEQL : GRDEQL :')
6077 9052 FORMAT ( ' ',2i4,' : ',20i3)
6078 #endif
6079  !
6080  !/
6081  !/ End of WMSMCEQL -------------------------------------------------- /
6082  !/

References wmmdatmd::eqstge, w3servmd::extcde(), wmmdatmd::grank, wmmdatmd::grdeql, wmmdatmd::grgrp, w3gdatmd::grids, wmmdatmd::improc, include(), w3gdatmd::mapsf, w3gdatmd::mapsta, wmmdatmd::mdatas, wmmdatmd::mdse, wmmdatmd::mdst, wmmdatmd::mpi_comm_mwave, wmmdatmd::nmperr, wmmdatmd::nmproc, wmmdatmd::nrgrd, w3gdatmd::nsea, w3odatmd::outpts, w3gdatmd::rlgtype, w3gdatmd::sgrds, w3gdatmd::smctype, w3servmd::strace(), w3gdatmd::w3setg(), w3odatmd::w3seto(), w3psmcmd::w3smcell(), w3psmcmd::w3smcgmp(), wmmdatmd::wmsetm(), w3gdatmd::xgrd, and w3gdatmd::ygrd.

Referenced by wminitmd::wminit(), and wminitmd::wminitnml().

w3gdatmd::nk
integer, pointer nk
Definition: w3gdatmd.F90:1230
wmmdatmd::nbi2s
integer, dimension(:,:), pointer nbi2s
NBI2S.
Definition: wmmdatmd.F90:539
wmmdatmd::respec
logical, dimension(:,:), allocatable respec
RESPEC.
Definition: wmmdatmd.F90:381
include
cmake src_list cmake include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/check_switches.cmake) check_switches("$
Definition: CMakeLists.txt:15
wmmdatmd::mdse
integer mdse
MDSE.
Definition: wmmdatmd.F90:316
w3tidemd::nr
integer, parameter nr
Definition: w3tidemd.F90:92
w3triamd
Reads triangle and unstructured grid information.
Definition: w3triamd.F90:21
w3gdatmd::ygrd
double precision, dimension(:,:), pointer ygrd
Definition: w3gdatmd.F90:1205
w3adatmd
Define data structures to set up wave model auxiliary data for several models simultaneously.
Definition: w3adatmd.F90:26
w3triamd::is_in_ungrid
subroutine is_in_ungrid(IMOD, XTIN, YTIN, ITOUT, IS, JS, RW)
Determine whether a point is inside or outside an unstructured grid, and returns index of triangle an...
Definition: w3triamd.F90:1605
w3gdatmd::sgrds
type(sgrd), dimension(:), allocatable, target sgrds
Definition: w3gdatmd.F90:1089
constants::dera
real, parameter dera
DERA Conversion factor from degrees to radians.
Definition: constants.F90:77
w3gdatmd::flagst
logical, dimension(:), pointer flagst
Definition: w3gdatmd.F90:1221
w3gdatmd::ungtype
integer, parameter ungtype
Definition: w3gdatmd.F90:626
wmmdatmd::init_get_jsea_isproc_glob
subroutine init_get_jsea_isproc_glob(ISEA, J, JSEA, ISPROC)
Introduce mapping for ISPROC and JSEA when using PDLIB in the Multigrid approach.
Definition: wmmdatmd.F90:1333
wmmdatmd::croot
integer, pointer croot
CROOT.
Definition: wmmdatmd.F90:545
w3gdatmd::rlgtype
integer, parameter rlgtype
Definition: w3gdatmd.F90:624
wmmdatmd::hgstge
type(hgst), dimension(:,:), allocatable, target hgstge
HGSTGE.
Definition: wmmdatmd.F90:530
w3gsrumd
Definition: w3gsrumd.F90:17
w3gdatmd::sig
real, dimension(:), pointer sig
Definition: w3gdatmd.F90:1234
w3gdatmd::xgrd
double precision, dimension(:,:), pointer xgrd
Definition: w3gdatmd.F90:1205
w3gdatmd::sy
real, pointer sy
Definition: w3gdatmd.F90:1183
w3odatmd::iaproc
integer, pointer iaproc
Definition: w3odatmd.F90:457
wmmdatmd::flgbdi
logical flgbdi
FLGBDI.
Definition: wmmdatmd.F90:378
w3gdatmd::grids
type(grid), dimension(:), allocatable, target grids
Definition: w3gdatmd.F90:1088
w3odatmd::unipts
logical unipts
Definition: w3odatmd.F90:333
w3odatmd::ybpi
real, dimension(:), pointer ybpi
Definition: w3odatmd.F90:541
w3gdatmd::ny
integer, pointer ny
Definition: w3gdatmd.F90:1097
wmmdatmd::grdeql
integer, dimension(:,:), allocatable grdeql
GRDEQL.
Definition: wmmdatmd.F90:357
wmmdatmd::mapbdi
real, dimension(:,:), pointer mapbdi
MAPBDI.
Definition: wmmdatmd.F90:553
w3odatmd::nbi
integer, pointer nbi
Definition: w3odatmd.F90:530
wmmdatmd::improc
integer improc
IMPROC.
Definition: wmmdatmd.F90:322
w3gdatmd::iclose_none
integer, parameter iclose_none
Definition: w3gdatmd.F90:629
w3gdatmd::hqfac
real, dimension(:,:), pointer hqfac
Definition: w3gdatmd.F90:1212
w3gdatmd::w3setg
subroutine w3setg(IMOD, NDSE, NDST)
Definition: w3gdatmd.F90:2152
wmmdatmd::grdhgh
integer, dimension(:,:), allocatable grdhgh
GRDHGH.
Definition: wmmdatmd.F90:356
scrip_timers::status
character(len=8), dimension(max_timers), save status
Definition: scrip_timers.f:63
w3odatmd::ndse
integer, pointer ndse
Definition: w3odatmd.F90:456
wmmdatmd::nmproc
integer nmproc
NMPROC.
Definition: wmmdatmd.F90:321
w3odatmd::nbi2
integer, pointer nbi2
Definition: w3odatmd.F90:530
w3gdatmd::mapfs
integer, dimension(:,:), pointer mapfs
Definition: w3gdatmd.F90:1163
w3sbt9md::ng
subroutine ng(SIGMA, H_WDEPTH, DTILDE, ZETA, SBLTM, GAMMA, WK, WKDR, DISS)
Compute dissipation by viscous fluid mud using Ng (2000).
Definition: w3sbt9md.F90:430
wmmdatmd::flghg1
logical flghg1
FLGHG1.
Definition: wmmdatmd.F90:379
w3odatmd::naperr
integer, pointer naperr
Definition: w3odatmd.F90:457
wmmdatmd::mdatas
type(mdata), dimension(:), allocatable, target mdatas
MDATAS.
Definition: wmmdatmd.F90:528
w3odatmd::w3dmo5
subroutine w3dmo5(IMOD, NDSE, NDST, IBLOCK)
Definition: w3odatmd.F90:1321
w3gdatmd::x0
real, pointer x0
Definition: w3gdatmd.F90:1183
scrip_interface
Definition: scrip_interface.F90:2
w3gdatmd::nsea
integer, pointer nsea
Definition: w3gdatmd.F90:1097
wmmdatmd::mapmsk
integer, dimension(:,:), pointer mapmsk
MAPMSK.
Definition: wmmdatmd.F90:540
w3gdatmd::clgtype
integer, parameter clgtype
Definition: w3gdatmd.F90:625
w3servmd
Definition: w3servmd.F90:3
wmmdatmd::nrgrd
integer nrgrd
NRGRD.
Definition: wmmdatmd.F90:330
wmmdatmd::nbi2g
integer, dimension(:,:), allocatable nbi2g
NBI2G.
Definition: wmmdatmd.F90:367
w3odatmd::ipbpi
integer, dimension(:,:), pointer ipbpi
Definition: w3odatmd.F90:535
w3odatmd::w3seto
subroutine w3seto(IMOD, NDSERR, NDSTST)
Definition: w3odatmd.F90:1523
wmscrpmd::scrip_wrapper
subroutine scrip_wrapper(ID_SRC, ID_DST, MAPSTA_SRC, MAPST2_SRC, FLAGLL, GRIDSHIFT, L_MASTER, L_READ, L_TEST)
Compute grid information required by SCRIP.
Definition: wmscrpmd.F90:115
w3odatmd
Definition: w3odatmd.F90:3
wmmdatmd::grdlow
integer, dimension(:,:), allocatable grdlow
GRDLOW.
Definition: wmmdatmd.F90:359
wmmdatmd::eqstge
type(eqst), dimension(:,:), allocatable, target eqstge
EQSTGE.
Definition: wmmdatmd.F90:531
w3gdatmd::mapsf
integer, dimension(:,:), pointer mapsf
Definition: w3gdatmd.F90:1163
w3odatmd::naproc
integer, pointer naproc
Definition: w3odatmd.F90:457
wmmdatmd::nmperr
integer nmperr
NMPERR.
Definition: wmmdatmd.F90:326
wmmdatmd::grgrp
integer, dimension(:), allocatable grgrp
GRGRP.
Definition: wmmdatmd.F90:354
w3odatmd::xbpi
real, dimension(:), pointer xbpi
Definition: w3odatmd.F90:541
w3gdatmd::smctype
integer, parameter smctype
Definition: w3gdatmd.F90:627
file
file(STRINGS ${CMAKE_BINARY_DIR}/switch switch_strings) separate_arguments(switches UNIX_COMMAND $
Definition: CMakeLists.txt:3
scrip_interface::wgtdata
type(weight_data), dimension(:), allocatable wgtdata
Definition: scrip_interface.F90:73
constants::radius
real, parameter radius
RADIUS Radius of the earth (m).
Definition: constants.F90:79
wmmdatmd::mdst
integer mdst
MDST.
Definition: wmmdatmd.F90:315
w3gdatmd::iclose
integer, pointer iclose
Definition: w3gdatmd.F90:1096
w3servmd::strace
subroutine strace(IENT, SNAME)
Definition: w3servmd.F90:148
w3odatmd::rdbpi
real, dimension(:,:), pointer rdbpi
Definition: w3odatmd.F90:541
wmmdatmd::wmsetm
subroutine wmsetm(IMOD, NDSE, NDST)
Select one of the WAVEWATCH III grids / models.
Definition: wmmdatmd.F90:1169
w3gdatmd::gtype
integer, pointer gtype
Definition: w3gdatmd.F90:1094
wmmdatmd::grank
integer, dimension(:), allocatable grank
GRANK.
Definition: wmmdatmd.F90:353
w3gdatmd::y0
real, pointer y0
Definition: w3gdatmd.F90:1183
w3psmcmd
Spherical Multiple-Cell (SMC) grid routines.
Definition: w3psmcmd.F90:18
w3gdatmd::hpfac
real, dimension(:,:), pointer hpfac
Definition: w3gdatmd.F90:1211
w3parall::init_get_jsea_isproc
subroutine init_get_jsea_isproc(ISEA, JSEA, ISPROC)
Set JSEA for all schemes.
Definition: w3parall.F90:1163
wmscrpmd
Routines to determine and process grid dependencies in the multi-grid wave model.
Definition: wmscrpmd.F90:23
w3gdatmd::sx
real, pointer sx
Definition: w3gdatmd.F90:1183
constants
Define some much-used constants for global use (all defined as PARAMETER).
Definition: constants.F90:20
w3gdatmd
Definition: w3gdatmd.F90:16
wmmdatmd
Define data structures to set up wave model dynamic data for several models simultaneously.
Definition: wmmdatmd.F90:16
w3gdatmd::iclose_trpl
integer, parameter iclose_trpl
Definition: w3gdatmd.F90:631
w3servmd::extcde
subroutine extcde(IEXIT, UNIT, MSG, FILE, LINE, COMM)
Definition: w3servmd.F90:736
w3odatmd::outpts
type(output), dimension(:), allocatable, target outpts
Definition: w3odatmd.F90:452
w3psmcmd::w3smcell
subroutine w3smcell(IMOD, NC, IDCl, XLon, YLat)
Calculate cell centre lat-lon for given ids.
Definition: w3psmcmd.F90:3660
w3odatmd::isbpi
integer, dimension(:), pointer isbpi
Definition: w3odatmd.F90:535
w3gdatmd::nx
integer, pointer nx
Definition: w3gdatmd.F90:1097
wmmdatmd::mapodi
real, dimension(:,:), pointer mapodi
MAPODI.
Definition: wmmdatmd.F90:554
w3parall
Parallel routines for implicit solver.
Definition: w3parall.F90:22
w3gdatmd::dtcfl
real, pointer dtcfl
Definition: w3gdatmd.F90:1183
w3psmcmd::w3smcgmp
subroutine w3smcgmp(IMOD, NC, XLon, YLat, IDCl)
Map lat-lon points to SMC grid cells.
Definition: w3psmcmd.F90:3804
w3gdatmd::mapsta
integer, dimension(:,:), pointer mapsta
Definition: w3gdatmd.F90:1163
constants::grav
real, parameter grav
GRAV Acc.
Definition: constants.F90:61
w3gdatmd::mapst2
integer, dimension(:,:), pointer mapst2
Definition: w3gdatmd.F90:1163
w3gdatmd::dtmax
real, pointer dtmax
Definition: w3gdatmd.F90:1183
wmmdatmd::mpi_comm_mwave
integer mpi_comm_mwave
MPI_COMM_MWAVE.
Definition: wmmdatmd.F90:344
w3gdatmd::flagll
logical, pointer flagll
Definition: w3gdatmd.F90:1219