WAVEWATCH III  beta 0.0.1
wmgridmd.F90
Go to the documentation of this file.
1 
8 
9 #include "w3macros.h"
10 !/ ------------------------------------------------------------------- /
19 MODULE wmgridmd
20  !/
21  !/ +-----------------------------------+
22  !/ | WAVEWATCH III NOAA/NCEP |
23  !/ | H. L. Tolman |
24  !/ | W. E. Rogers |
25  !/ | FORTRAN 90 |
26  !/ | Last update : 10-Dec-2014 |
27  !/ +-----------------------------------+
28  !/
29  !/ 28-Dec-2005 : Origination WMGLOW, WMGHGH, WMRSPC. ( version 3.08 )
30  !/ 09-Mar-2006 : Carry land mask in WMGHGH. ( version 3.09 )
31  !/ 24-Apr-2006 : Origination WMGEQL. ( version 3.09 )
32  !/ 25-Jul-2006 : Point output grid in WMRSPC. ( version 3.10 )
33  !/ 23-Dec-2006 : Adding group test in WMGEQL. ( version 3.10 )
34  !/ 28-Dec-2006 : Simplify NIT for partial comm. ( version 3.10 )
35  !/ 22-Jan-2007 : Add saving of NAVMAX in WMGEQL. ( version 3.10 )
36  !/ 02-Feb-2007 : Setting FLAGST in WMGEQL. ( version 3.10 )
37  !/ 07-Feb-2007 : Setting FLAGST in WMGHGH. ( version 3.10 )
38  !/ 15-Feb-2007 : Tweaking MAPODI algorithm in WMGEQL.( version 3.10 )
39  !/ 11-Apr-2008 : Bug fix active edges WMGEQL. ( version 3.13 )
40  !/ 14-Apr-2008 : Bug fix for global grids WMGEQL. ( version 3.13 )
41  !/ 26-Mar-2009 : Adding test output !/T9 to WMGLOW. ( version 3.14 )
42  !/ 20-May-2009 : Linking FLAGST and FLGHG1. ( version 3.14 )
43  !/ 26-May-2009 : Fix erroneous cyclic upd in WMGHGH. ( version 3.14 )
44  !/ 29-May-2009 : Preparing distribution version. ( version 3.14 )
45  !/ 30-Oct-2009 : Implement run-time grid selection. ( version 3.14 )
46  !/ (W. E. Rogers & T. J. Campbell, NRL)
47  !/ 06-Dec-2010 : Change from GLOBAL (logical) to ICLOSE (integer) to
48  !/ specify index closure for a grid. ( version 3.14 )
49  !/ (T. J. Campbell, NRL)
50  !/ 23-Dec-2010 : Fix HPFAC and HQFAC by including the COS(YGRD)
51  !/ factor with DXDP and DXDQ terms. ( version 3.14 )
52  !/ (T. J. Campbell, NRL)
53  !/ 12-Mar-2012 : Use MPI_COMM_NULL in checks. ( version 3.14 )
54  !/ 06-Jun-2012 : Porting bugfixes from 3.14 to 4.07 ( version 4.07 )
55  !/ 05-Sep-2012 : Implementation of UNGTYPE with SCRIP
56  !/ (Mathieu Dutour Sikiric, IRB; Aron Roland, Z&P)
57  !/ 21-Sep-2012 : Modify WMGHGH to support SCRIP remap( version 4.11 )
58  !/ write/read capabilities (K. Lind, NRL)
59  !/ 05-Aug-2013 : Change PR2/3 to UQ/UNO in distances.( version 4.12 )
60  !/ 10-Dec-2014 : Add checks for allocate status ( version 5.04 )
61  !/ 28-Oct-2020 : Add SMCTYPE for SMC sub-grid. JGLi ( version 7.13 )
62  !/ 26-Jan-2021 : Add WMSMCEQL for SMC sub-grid. JGLi ( version 7.13 )
63  !/
64  !/ Copyright 2009-2013 National Weather Service (NWS),
65  !/ National Oceanic and Atmospheric Administration. All rights
66  !/ reserved. WAVEWATCH III is a trademark of the NWS.
67  !/ No unauthorized use without permission.
68  !/
69  ! 1. Purpose :
70  !
71  ! Routines to determine and process grid dependencies in the
72  ! multi-grid wave model.
73  !
74  ! 2. Variables and types :
75  !
76  ! 3. Subroutines and functions :
77  !
78  ! Name Type Scope Description
79  ! ----------------------------------------------------------------
80  ! WMGLOW Subr. Public Dependencies to lower ranked grids.
81  ! WMGHGH Subr. Public Dependencies to higher ranked grids.
82  ! WMGEQL Subr. Public Dependencies to same ranked grids.
83  ! WMRSPC Subr. Public Make map of flags for spectral
84  ! conversion between grids.
85  ! WMSMCEQL Subr. Public Dependencies on same ranked SMC grids.
86  ! ----------------------------------------------------------------
87  !
88  ! 4. Subroutines and functions used :
89  !
90  ! Name Type Module Description
91  ! ----------------------------------------------------------------
92  ! W3SETO, W3SETG, W3DMO5, WMSETM
93  ! Subr. W3xDATMD Manage data structures.
94  !
95  ! STRACE Sur. W3SERVMD Subroutine tracing.
96  ! EXTCDE Subr. Id. Program abort.
97  !
98  ! MPI_BCAST, MPI_BARRIER
99  ! Subr. mpif.h Comunication routines.
100  ! ----------------------------------------------------------------
101  !
102  ! 5. Remarks :
103  !
104  ! - WMGLOW and WMGHGH need to be run in this order to
105  ! assure proper resolving of cross-dependencies.
106  ! - WMGLOW and WMGEQL, idem.
107  !
108  ! 6. Switches :
109  !
110  ! !/PRn propagation scheme.
111  ! !/UQ propagation scheme.
112  ! !/UNO propagation scheme.
113  ! !/SMC Enable SMC sub-grids.
114  !
115  ! !/SHRD Distributed memory approach
116  ! !/DIST
117  ! !/MPI
118  !
119  ! !/O12 Removed boundary points output WMGEQL (central).
120  ! !/O13 Removed boundary points output WMGEQL (edge).
121  !
122  ! !/S Enable subroutine tracing.
123  ! !/Tn Enable test output.
124  !
125  ! 7. Source code :
126  !
127  !/ ------------------------------------------------------------------- /
128  !/
129  !/ Specify default accessibility
130  !/
131  PUBLIC
132  !/
133  !/ Module private variable for checking error returns
134  !/
135  INTEGER, PRIVATE :: ISTAT
136  !/
137 CONTAINS
138  !/ ------------------------------------------------------------------- /
151  SUBROUTINE wmglow ( FLRBPI )
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  !/
1086  END SUBROUTINE wmglow
1087 
1088  !/ ------------------------------------------------------------------- /
1099  SUBROUTINE wmghgh
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  !/
3698  END SUBROUTINE wmghgh
3699  !/ ------------------------------------------------------------------- /
3708  SUBROUTINE wmgeql
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  !/
5128  END SUBROUTINE wmgeql
5129  !/ ------------------------------------------------------------------- /
5138  SUBROUTINE wmrspc
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  !/
5271  END SUBROUTINE wmrspc
5272  !/
5273  !!
5284  SUBROUTINE wmsmceql
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  !/
6083  END SUBROUTINE wmsmceql
6084  !!
6085 
6086  !/ End of module WMGRIDMD -------------------------------------------- /
6087  !/
6088 END MODULE wmgridmd
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
w3triamd
Reads triangle and unstructured grid information.
Definition: w3triamd.F90:21
wmgridmd::wmrspc
subroutine wmrspc
Generate map with flags for need of spectral grid conversion between models.
Definition: wmgridmd.F90:5139
w3gdatmd::ygrd
double precision, dimension(:,:), pointer ygrd
Definition: w3gdatmd.F90:1205
scrip_interface::weight_data
Definition: scrip_interface.F90:62
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
wmgridmd::wmglow
subroutine wmglow(FLRBPI)
Determine relations to lower ranked grids for each grid.
Definition: wmgridmd.F90:152
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
wmgridmd::wmgeql
subroutine wmgeql
Determine relations to same ranked grids for each grid.
Definition: wmgridmd.F90:3709
w3gdatmd::w3setg
subroutine w3setg(IMOD, NDSE, NDST)
Definition: w3gdatmd.F90:2152
wmmdatmd::grdhgh
integer, dimension(:,:), allocatable grdhgh
GRDHGH.
Definition: wmmdatmd.F90:356
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
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
wmgridmd::wmghgh
subroutine wmghgh
Determine relation to higher ranked grids for each grid.
Definition: wmgridmd.F90:1100
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
wmgridmd
Routines to determine and process grid dependencies in the multi-grid wave model.
Definition: wmgridmd.F90:19
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
wmgridmd::wmsmceql
subroutine wmsmceql
Determine relations to same ranked SMC grids for each grid.
Definition: wmgridmd.F90:5285
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