WAVEWATCH III  beta 0.0.1
w3triamd.F90
Go to the documentation of this file.
1 
8 
9 #include "w3macros.h"
10 !/ ------------------------------------------------------------------- /
11 
21 MODULE w3triamd
22  !/ -------------------------------------------------------------------
23  !/ +-----------------------------------+
24  !/ | WAVEWATCH III NOAA/NCEP |
25  !/ | F. Ardhuin and A. Roland |
26  !/ | FORTRAN 90 |
27  !/ | Last update : 26-Jan-2014|
28  !/ +-----------------------------------+
29  !/
30  !/ 15-Mar-2007 : Origination. ( version 3.13 )
31  !/ 25-Aug-2011 : Modification of boundary treatment ( version 4.04 )
32  !/ 30-Aug-2012 : Automatic detection of open BC ( version 4.08 )
33  !/ 02-Sep-2012 : Clean up of open BC for UG grids ( version 4.08 )
34  !/ 14-Oct-2013 : Correction of latitude factor ( version 4.12 )
35  !/ 26-Jan-2014 : Correction interpolation weights ( version 4.18 )
36  !/ 21-Apr-2016 : New algorithm to detect boundary ( version 5.12 )
37  !/
38  !
39  ! 1. Purpose :
40  !
41  ! Reads triangle and unstructured grid information
42  !
43  ! 2. Method :
44  !
45  ! Look for namelist with name NAME in unit NDS and read if found.
46  !
47  ! 3. Parameters :
48  !
49  !
50  ! 4. Subroutines used :
51  !
52  ! Name Type Module Description
53  ! ------------------------------------------------------------------------------------
54  ! READTRI Subr. Internal Read unstructured grid data from .grd .tri formatted files.
55  ! READMSH Subr. Id. Read unstructured grid data from MSH format
56  ! COUNT Subr. Internal Count connection.
57  ! SPATIAL_GRID Subr. Id. Calculate surfaces.
58  ! NVECTRI Subr. Id. Define cell normals and angles and edge length
59  ! COORDMAX Subr. Id. Calculate useful grid elements
60  ! AREA_SI Subr. Id. Define Connections
61  ! ------------------------------------------------------------------------------------
62  !
63  !
64  ! 5. Called by :
65  !
66  ! Program in which it is contained.
67  !
68  ! 6. Error messages :
69  !
70  ! 7. Remarks :
71  ! The only point index which is needed is IX and NX stands for the total number of grid point.
72  ! IY and NY are not needed anymore, they are set to 1 in the unstructured case
73  ! Some noticeable arrays are:
74  ! TRIGP : give the vertices of each triangle
75  ! 8. Structure :
76  !
77  ! 9. Switches :
78  ! !/PR3 : Enables unstructured meshes (temporary, will be replace by Unstructured switch)
79  ! 10. Source code :
80  !
81  !/ ------------------------------------------------------------------- /
82  PUBLIC
83  ! USE CONSTANTS
84  ! USE W3GDATMD, ONLY: W3NMOD, W3SETG
85  ! USE W3ODATMD, ONLY: W3NOUT, W3SETO, W3DMO5
86  ! USE W3IOGRMD, ONLY: W3IOGR
87  ! USE W3SERVMD, ONLY: ITRACE, NEXTLN, EXTCDE
88  ! USE W3ARRYMD, ONLY: INA2R, INA2I
89  ! USE W3DISPMD, ONLY: DISTAB
90  ! USE W3GDATMD
91  ! USE W3ODATMD, ONLY: NDSE, NDST, NDSO
92  ! USE W3ODATMD, ONLY: NBI, NBI2, NFBPO, NBO, NBO2, FLBPI, FLBPO, &
93  ! IPBPO, ISBPO, XBPO, YBPO, RDBPO, FNMPRE
94  !---------------------------------------------------------------------
95  !
96  !C
97  ! integer :: node_num
98  ! integer :: dim_num
99  ! integer :: triangle_order
100  ! integer :: triangle_num
101  ! integer :: bound_edge_num
102  ! integer :: bound_num
103  !C
104  ! logical,save, allocatable :: edge_boundary(:)
105  ! logical,save, allocatable :: node_boundary(:)
106  ! integer,save, allocatable :: edge_nums(:)
107  ! integer,save, allocatable :: boundary_node_index(:)
108  !C
109  ! integer,save, allocatable :: triangle_node(:,:)
110  ! integer,save, allocatable :: edge(:,:)
111  ! integer,save, allocatable :: edge_index(:,:)
112  ! integer,save, allocatable :: iobp_aux(:)
113 
114  INTEGER, SAVE :: n_outside_boundary
115  INTEGER, SAVE, ALLOCATABLE :: outside_boundary(:)
116 
117 CONTAINS
118  !/ -------------------------------------------------------------------/
119 
133  SUBROUTINE readmsh(NDS,FNAME)
134  !/ -------------------------------------------------------------------
135  !/ +-----------------------------------+
136  !/ | WAVEWATCH III NOAA/NCEP |
137  !/ | F. Ardhuin |
138  !/ | A. Roland |
139  !/ | FORTRAN 90 |
140  !/ | Last update : 06-Jun-2018|
141  !/ +-----------------------------------+
142  !/
143  !/ 15-Feb-2008 : Origination. ( version 3.13 )
144  !/ 25-Aug-2011 : Change of method for IOBPD ( version 4.04 )
145  !/ 06-Jun-2018 : Add DEBUGINIT/PDLIB/DEBUGSTP/DEBUGSETIOBP
146  !/ ( version 6.04 )
147  !/
148  !
149  ! 1. Purpose :
150  !
151  ! Reads triangle and unstructured grid information from GMSH files
152  ! Calls the subroutines needed to compute grid connectivity
153  !
154  ! 2. Method :
155  !
156  ! Look for namelist with name NAME in unit NDS and read if found.
157  !
158  ! 3. Parameters :
159  !
160  ! Parameter list
161  ! ----------------------------------------------------------------
162  ! NDS Int. I Data set number used for search.
163  ! NAME C*4 I Name of namelist.
164  ! STATUS C*20 O Status at end of routine,
165  ! '(default values) ' if no namelist found.
166  ! '(user def. values)' if namelist read.
167  ! ----------------------------------------------------------------
168  !
169  ! 4. Subroutines used :
170  !
171  ! Name Type Module Description
172  ! ------------------------------------------------------------------------------------
173  ! NEXTLN Subr.
174  ! COUNT Subr. Internal Count connection.
175  ! SPATIAL_GRID Subr. Id. Calculate surfaces.
176  ! NVECTRI Subr. Id. Define cell normals and angles and edge length
177  ! COORDMAX Subr. Id. Calculate useful grid elements
178  ! AREA_SI Subr. Id. Define Connections
179  ! ----------------------------------------------------------------
180  !
181  !
182  !
183  ! 5. Called by :
184  ! Name Type Module Description
185  ! ----------------------------------------------------------------
186  ! W3GRID Prog. Model configuration program
187  ! ----------------------------------------------------------------
188  !
189  ! 6. Error messages :
190  !
191  ! 7. Remarks :
192  ! The only point index which is needed is IX and NX stands for the total number of grid point.
193  ! IY and NY are not needed anymore, they are set to 1 in the unstructured case
194  ! Some noticeable arrays are:
195  ! TRIGP : give the vertices of each triangle
196  ! GMSH file gives too much information that is not necessarily required so data processing is needed (data sort and nesting).
197  ! 8. Structure :
198  !
199  ! 9. Switches :
200  !
201  ! 10. Source code :
202  !
203  !/ ------------------------------------------------------------------- /
204  USE w3odatmd, ONLY: ndse, ndst, ndso
205  USE w3gdatmd, ONLY: zb, xgrd, ygrd, ntri, nx, countot, trigp, nnz, w3dimug
206  USE w3servmd, ONLY: itrace, nextln, extcde
207  USE constants, only: lpdlib
208  USE w3odatmd, ONLY: iaproc
209  !
210  IMPLICIT NONE
211  !/
212  !/ Parameter list
213  !/
214  INTEGER, INTENT(IN) :: NDS
215  CHARACTER(60), INTENT(IN) :: FNAME
216  !/
217  !/ local parameters
218  !/
219  INTEGER :: i,j,k, NODES, NELTS, ID, KID
220  INTEGER :: ID1, ID2, KID1, ITMP(3)
221  INTEGER :: I1, I2, I3
222  INTEGER(KIND=4) :: Ind,eltype,ntag, INode
223  CHARACTER :: COMSTR*1, SPACE*1 = ' ', cels*64
224  REAL, ALLOCATABLE :: TAGS(:)
225  CHARACTER(LEN=64), ALLOCATABLE :: ELS(:)
226  CHARACTER(LEN=120) :: LINE
227  CHARACTER(LEN=50) :: CHTMP
228  CHARACTER(LEN=10) :: A, B, C
229  INTEGER,ALLOCATABLE :: NELS(:), TRIGPTMP1(:,:), TRIGPTMP2(:,:)
230  INTEGER(KIND=4),ALLOCATABLE :: IFOUND(:), VERTEX(:), BOUNDTMP(:)
231  DOUBLE PRECISION, ALLOCATABLE :: XYBTMP1(:,:),XYBTMP2(:,:)
232  REAL :: z
233 
234  OPEN(nds,file = fname,status='old')
235  READ (nds,'(A)') comstr
236  IF (comstr.EQ.' ') comstr = '$'
237  CALL nextln(comstr, nds, ndse)
238  READ(nds,*) i,j,k
239  CALL nextln(comstr, nds, ndse)
240  lpdlib = .false.
241 #ifdef W3_PDLIB
242  lpdlib = .true.
243 #endif
244  !
245  ! read number of nodes and nodes from Gmsh files
246  !
247  READ(nds,*) nodes
248  ALLOCATE(xybtmp1(3,nodes))
249  DO i= 1, nodes
250  READ(nds,*) j, xybtmp1(1,i), xybtmp1(2,i), xybtmp1(3,i)
251  END DO
252  !
253  ! read number of elements and elements from Gmsh files
254  !
255  ALLOCATE(boundtmp(nodes))
257  CALL nextln(comstr, nds, ndse)
258  READ(nds,*) nelts
259  ALLOCATE(trigptmp1(3,nelts))
260  j = 0
261  DO i= 1, nelts
262  READ(nds,'(A100)') line
263  READ(line,*) ind,eltype,ntag
264  ALLOCATE(tags(ntag))
265  SELECT CASE (eltype)
266  !
267  ! eltype = 15 : boundary points (this is used to make the difference
268  ! between the outside polygon and islands)
269  !
270  CASE(15)
271  READ(line,*) ind,eltype,ntag,tags,inode
273  boundtmp(n_outside_boundary)=inode
274  !
275  ! eltype = 2 : triangles
276  !
277  CASE (2)
278  j = j + 1
279  READ(line,*) ind,eltype,ntag,tags,itmp
280  trigptmp1(1:3,j) = itmp
281  END SELECT
282 
283  DEALLOCATE(tags)
284  END DO
285  !
286  ! organizes the grid data structure
287  !
289  outside_boundary(:) = boundtmp(1:n_outside_boundary)
290  ntri = j
291 
292  ALLOCATE(ifound(nodes))
293 
294  ifound = 0
295  !
296  ! Verifies that the nodes are used in at least one triangle
297  !
298  DO k = 1, ntri
299  i1 = trigptmp1(1,k)
300  i2 = trigptmp1(2,k)
301  i3 = trigptmp1(3,k)
302 
303  ifound(i1)= ifound(i1) + 1
304  ifound(i2)= ifound(i2) + 1
305  ifound(i3)= ifound(i3) + 1
306  END DO
307 
308  j = 0
309 
310  ALLOCATE(trigptmp2(3,ntri),vertex(nodes),xybtmp2(3,nodes))
311  vertex(:)=0
312  xybtmp2 = 0
313 
314  DO i = 1, nodes
315  IF( ifound(i) .GT. 0) THEN
316  j = j+1
317  xybtmp2(:,j) = xybtmp1(:,i)
318  vertex(i) = j
319  END IF
320  END DO
321  !
322  ! Number of nodes after clean up
323  !
324  nx = j
325  !
326  DO i = 1, ntri
327  i1 = trigptmp1(1,i)
328  i2 = trigptmp1(2,i)
329  i3 = trigptmp1(3,i)
330  trigptmp2(1,i) = vertex(i1)
331  trigptmp2(2,i) = vertex(i2)
332  trigptmp2(3,i) = vertex(i3)
333  END DO
334  !
335  DEALLOCATE(xybtmp1,ifound,trigptmp1)
336  DEALLOCATE(vertex)
337  !
338  !count points connections to allocate array in W3DIMUG
339  !
340  CALL count(trigptmp2)
341  CALL w3dimug ( 1, ntri, nx, countot, nnz, ndse, ndst )
342  !
343  ! fills arrays
344  !
345  DO i = 1, nx
346  xgrd(1,i) = xybtmp2(1,i)
347  ygrd(1,i) = xybtmp2(2,i)
348  zb(i) = xybtmp2(3,i)
349  END DO
350  !
351  DO i=1, ntri
352  itmp = trigptmp2(:,i)
353  trigp(:,i) = itmp
354  END DO
355  !
356  DEALLOCATE(trigptmp2,xybtmp2)
357  !
358  ! call the various routines which define the point spotting strategy
359  !
360  CALL spatial_grid
361  CALL nvectri
362  CALL coordmax
363 
364 #ifdef W3_PDLIB
365  IF(.false.) THEN
366 #endif
367  CALL area_si(1)
368 #ifdef W3_PDLIB
369  ENDIF
370 #endif
371  !
372  CLOSE(nds)
373  END SUBROUTINE readmsh
374  !/--------------------------------------------------------------------/
375 
388  SUBROUTINE readmsh_iobp(NDS,FNAME)
389  !/ -------------------------------------------------------------------
390  !/ +-----------------------------------+
391  !/ | WAVEWATCH III NOAA/NCEP |
392  !/ | A. Roland |
393  !/ | F. Ardhuin |
394  !/ | FORTRAN 90 |
395  !/ | Last update : 06-Jun-2018|
396  !/ +-----------------------------------+
397  !/
398  !/ 15-Feb-2008 : Origination. ( version 3.13 )
399  !/ 25-Aug-2011 : Change of method for IOBPD ( version 4.04 )
400  !/ 06-Jun-2018 : Add DEBUGINIT/PDLIB/DEBUGSTP/DEBUGSETIOBP
401  !/ ( version 6.04 )
402  !/
403  !
404  ! 1. Purpose :
405  !
406  ! Reads triangle and unstructured grid information from GMSH files
407  ! Calls the subroutines needed to compute grid connectivity
408  !
409  ! 2. Method :
410  !
411  ! Look for namelist with name NAME in unit NDS and read if found.
412  !
413  ! 3. Parameters :
414  !
415  ! Parameter list
416  ! ----------------------------------------------------------------
417  ! NDS Int. I Data set number used for search.
418  ! NAME C*4 I Name of namelist.
419  ! STATUS C*20 O Status at end of routine,
420  ! '(default values) ' if no namelist found.
421  ! '(user def. values)' if namelist read.
422  ! ----------------------------------------------------------------
423  !
424  ! 4. Subroutines used :
425  !
426  ! Name Type Module Description
427  ! ------------------------------------------------------------------------------------
428  ! NEXTLN Subr.
429  ! COUNT Subr. Internal Count connection.
430  ! SPATIAL_GRID Subr. Id. Calculate surfaces.
431  ! NVECTRI Subr. Id. Define cell normals and angles and edge length
432  ! COORDMAX Subr. Id. Calculate useful grid elements
433  ! AREA_SI Subr. Id. Define Connections
434  ! ----------------------------------------------------------------
435  !
436  !
437  !
438  ! 5. Called by :
439  ! Name Type Module Description
440  ! ----------------------------------------------------------------
441  ! W3GRID Prog. Model configuration program
442  ! ----------------------------------------------------------------
443  !
444  ! 6. Error messages :
445  !
446  ! 7. Remarks :
447  ! The only point index which is needed is IX and NX stands for the total number of grid point.
448  ! IY and NY are not needed anymore, they are set to 1 in the unstructured case
449  ! Some noticeable arrays are:
450  ! TRIGP : give the vertices of each triangle
451  ! GMSH file gives too much information that is not necessarily required so data processing is needed (data sort and nesting).
452  ! 8. Structure :
453  !
454  ! 9. Switches :
455  !
456  ! 10. Source code :
457  !
458  !/ ------------------------------------------------------------------- /
459  USE w3odatmd, ONLY: ndse, ndst, ndso
460  USE w3gdatmd
461  USE w3servmd, ONLY: itrace, nextln, extcde
462  USE constants, only: lpdlib
463  USE w3odatmd, ONLY: iaproc
464  !
465  IMPLICIT NONE
466  !/
467  !/ Parameter list
468  !/
469  INTEGER, INTENT(IN) :: NDS
470  CHARACTER(60), INTENT(IN) :: FNAME
471  !/
472  !/ local parameters
473  !/
474  INTEGER :: i,j,k, NODES
475  LOGICAL :: lfile_exists
476  CHARACTER :: COMSTR*1, SPACE*1 = ' ', cels*64
477  DOUBLE PRECISION, ALLOCATABLE :: XYBTMP1(:,:)
478 
479  INQUIRE(file=fname, exist=lfile_exists)
480  IF (.NOT. lfile_exists) RETURN
481  OPEN(nds,file = fname,status='old')
482  READ (nds,'(A)') comstr
483  IF (comstr.EQ.' ') comstr = '$'
484  CALL nextln(comstr, nds, ndse)
485  READ(nds,*) i,j,k
486  CALL nextln(comstr, nds, ndse)
487  !
488  ! read number of nodes and nodes from Gmsh files
489  !
490  READ(nds,*) nodes
491  ALLOCATE(xybtmp1(3,nodes))
492  DO i= 1, nodes
493  READ(nds,*) j, xybtmp1(1,i), xybtmp1(2,i), xybtmp1(3,i)
494  IF (int(xybtmp1(3,i)) .EQ. 3) iobp(i) = 3
495  END DO
496  !
497  CLOSE(nds)
498  END SUBROUTINE readmsh_iobp
499  !/--------------------------------------------------------------------/
500 
510  SUBROUTINE get_boundary_status(STATUS)
511  !/
512  !/ +-----------------------------------+
513  !/ | WAVEWATCH III NOAA/NCEP |
514  !/ | |
515  !/ | Mathieu Dutour-Sikiric (IRB) |
516  !/ | Aron Roland (BGS IT&E GmbH) |
517  !/ | |
518  !/ | FORTRAN 90 |
519  !/ | Last update : 01-Mai-2018 |
520  !/ +-----------------------------------+
521  !/
522  !/ 01-Mai-2018 : Origination. ( version 6.04 )
523  !/
524  ! 1. Purpose : boundary status (code duplication)
525  ! 2. Method :
526  ! 3. Parameters :
527  !
528  ! Parameter list
529  ! ----------------------------------------------------------------
530  ! ----------------------------------------------------------------
531  !
532  ! 4. Subroutines used :
533  !
534  ! Name Type Module Description
535  ! ----------------------------------------------------------------
536  ! STRACE Subr. W3SERVMD Subroutine tracing.
537  ! ----------------------------------------------------------------
538  !
539  ! 5. Called by :
540  !
541  ! Name Type Module Description
542  ! ----------------------------------------------------------------
543  ! ----------------------------------------------------------------
544  !
545  ! 6. Error messages :
546  ! 7. Remarks
547  ! 8. Structure :
548  ! 9. Switches :
549  !
550  ! !/S Enable subroutine tracing.
551  !
552  ! 10. Source code :
553  !
554  !/ ------------------------------------------------------------------- /
555 #ifdef W3_S
556  USE w3servmd, ONLY: strace
557 #endif
558  !
559 
560 #ifdef W3_PDLIB
561  use yowelementpool, only: ne_global
562  use yownodepool, only: np_global
563 #endif
564  USE w3gdatmd, ONLY : trigp, ntri, nx
565  IMPLICIT NONE
566  !/
567  !/ ------------------------------------------------------------------- /
568  !/ Parameter list
569  !/
570  !/ ------------------------------------------------------------------- /
571  !/ Local PARAMETERs
572  !/
573 #ifdef W3_S
574  INTEGER, SAVE :: IENT = 0
575 #endif
576  !/
577  !/ ------------------------------------------------------------------- /
578  !/
579  !
580  integer*2, intent(out) :: STATUS(NX)
581  INTEGER :: COLLECTED(NX), NEXTVERT(NX), PREVVERT(NX)
582  INTEGER :: ISFINISHED, INEXT, IPREV
583  INTEGER :: IPNEXT, IPPREV, ZNEXT, IP, I, IE
584 #ifdef W3_S
585  CALL strace (ient, 'VA_SETUP_IOBPD')
586 #endif
587  status(:) = 0
588  DO ie=1,ntri
589  DO i=1,3
590  IF (i.EQ.1) THEN
591  iprev=3
592  ELSE
593  iprev=i-1
594  END IF
595  IF (i.EQ.3) THEN
596  inext=1
597  ELSE
598  inext=i+1
599  END IF
600  ip=trigp(i,ie)
601  ipnext=trigp(inext,ie)
602  ipprev=trigp(iprev,ie)
603  IF (status(ip).EQ.0) THEN
604  status(ip)=1
605  prevvert(ip)=ipprev
606  nextvert(ip)=ipnext
607  END IF
608  END DO
609  END DO
610  status(:)=0
611  DO
612  collected(:)=0
613  DO ie=1,ntri
614  DO i=1,3
615  IF (i.EQ.1) THEN
616  iprev=3
617  ELSE
618  iprev=i-1
619  END IF
620  IF (i.EQ.3) THEN
621  inext=1
622  ELSE
623  inext=i+1
624  END IF
625  ip=trigp(i,ie)
626  ipnext=trigp(inext,ie)
627  ipprev=trigp(iprev,ie)
628  IF (status(ip).eq.0) THEN
629  znext=nextvert(ip)
630  IF (znext.eq.ipprev) THEN
631  collected(ip)=1
632  nextvert(ip)=ipnext
633  IF (nextvert(ip).eq.prevvert(ip)) THEN
634  status(ip)=1
635  END IF
636  END IF
637  END IF
638  END DO
639  END DO
640  isfinished=1
641  DO ip=1,nx
642  IF ((collected(ip).eq.0).and.(status(ip).eq.0)) THEN
643  status(ip)=-1
644  END IF
645  IF (status(ip).eq.0) THEN
646  isfinished=0
647  END IF
648  END DO
649  IF (isfinished.eq.1) THEN
650  EXIT
651  END IF
652  END DO
653  END SUBROUTINE get_boundary_status
654 
655  !/ -------------------------------------------------------------------/
656 
669  SUBROUTINE readmshobc(NDS, FNAME, TMPSTA, UGOBCOK)
670  !/ -------------------------------------------------------------------
671  !/ +-----------------------------------+
672  !/ | WAVEWATCH III NOAA/NCEP |
673  !/ | F. Ardhuin |
674  !/ | FORTRAN 90 |
675  !/ | Last update : 14-Mar-2018|
676  !/ +-----------------------------------+
677  !/
678  !/ 14-Mar-2018 : Origination. ( version 6.02 )
679  !/
680  !
681  ! 1. Purpose :
682  !
683  ! Reads open boundary information for UNST grids following GMESH type format
684  !
685  ! 2. Method :
686  !
687  ! Reads an ASCII file
688  !
689  ! 3. Parameters :
690  !
691  ! Parameter list
692  ! ----------------------------------------------------------------
693  ! NDS Int. I Data set number used for search.
694  ! FNAME Char*60 I File name
695  ! TMPSTA Char*60 I/O status map to be updated (for OBC, TMPSTA = 2)
696  ! UGOBCOK Logical O flag for proper reading of OBC file
697  ! ----------------------------------------------------------------
698  !
699  ! 4. Subroutines used : NONE
700  !
701  ! 5. Called by :
702  ! Name Type Module Description
703  ! ----------------------------------------------------------------
704  ! W3GRID Prog. Model configuration program
705  ! ----------------------------------------------------------------
706  !
707  ! 6. Error messages :
708  !
709  ! 7. Remarks :
710  !
711  ! 8. Structure :
712  !
713  ! 9. Switches :
714  !
715  ! 10. Source code :
716  !
717  !/ ------------------------------------------------------------------- /
718  USE w3gdatmd, ONLY: nx, ny, ccon , countcon
719  USE w3odatmd, ONLY: ndse, ndst, ndso
720  USE w3servmd, ONLY: itrace, nextln, extcde
721 #ifdef W3_S
722  USE w3servmd, ONLY: strace
723 #endif
724 
725  IMPLICIT NONE
726  !/ ------------------------------------------------------------------- /
727  !/ Parameter list
728  !/
729  INTEGER, INTENT(IN) :: NDS
730  CHARACTER(60), INTENT(IN) :: FNAME
731  INTEGER, INTENT(INOUT) :: TMPSTA(NY,NX)
732  LOGICAL, INTENT(OUT) :: UGOBCOK
733  !/
734  !/ local parameters
735  !/
736  INTEGER :: I, IERR
737  INTEGER(KIND=4) :: Ind,ntag, INode
738  CHARACTER :: COMSTR*1, SPACE*1 = ' ', cels*64
739  REAL, ALLOCATABLE :: TAGS(:)
740  CHARACTER(LEN=120) :: LINE
741 
742  ugobcok=.false.
743 
744  OPEN(nds,file = fname,status='old')
745  READ (nds,'(A)') comstr
746  IF (comstr.EQ.' ') comstr = '$'
747  CALL nextln(comstr, nds, ndse)
748  ierr = 0
749  DO WHILE (ierr.EQ.0)
750  READ (nds,'(A100)',END=2001,ERR=2002,IOSTAT=IERR) line
751  READ(line,*,iostat=ierr) ind,ntag
752  IF (ierr.EQ.0) THEN
753  ALLOCATE(tags(ntag))
754  READ(line,*,iostat=ierr) ind,ntag,tags,inode
755  IF (ierr.EQ.0) THEN
756  tmpsta(1,inode)=2
757  DEALLOCATE(tags)
758  ELSE
759  GOTO 2001
760  END IF
761  END IF
762  END DO
763  CLOSE(nds)
764  ugobcok=.true.
765  RETURN
766  !
767 2001 CONTINUE
768  WRITE (ndse,1001)
769  CALL extcde ( 61 )
770  !
771 2002 CONTINUE
772  WRITE (ndse,1002) ierr
773  CALL extcde ( 62 )
774 1001 FORMAT (/' *** WAVEWATCH III ERROR IN READMSHOBC : '/ &
775  ' PREMATURE END OF FILE IN READING ',a/)
776 1002 FORMAT (/' *** WAVEWATCH III ERROR IN READMSHOBC : '/ &
777  ' ERROR IN READING ',a,' IOSTAT =',i8/)
778 
779  END SUBROUTINE readmshobc
780  !/ ------------------------------------------------------------------- /
781 
782 
783  !/ ------------------------------------------------------------------- /
796  SUBROUTINE ug_getopenboundary(TMPSTA,ZBIN,ZLIM)
797  !/ +-----------------------------------+
798  !/ | WAVEWATCH III NOAA/NCEP |
799  !/ | F. Ardhuin |
800  !/ | FORTRAN 90 |
801  !/ | Last update : 30-Aug-2012|
802  !/ +-----------------------------------+
803  !/
804  !/ 30-Aug-2012 : Adpatation from SHOM-Ifremer program( version 4.07 )
805  !/
806  !
807  ! 1. purpose: defines open boundary points based on depth
808  ! 2. Method : a boundary node has more node around it than triangles
809  !
810  !
811  ! 3. Parameters :
812  ! TMPSTA: status map to be updated (for OBC, TMPSTA = 2)
813  !
814  ! 4. Subroutines used :
815  !
816  ! 5. Called by :
817  !
818  ! Name Type Module Description
819  ! ----------------------------------------------------------------
820  ! w3GRID Prog. Model configuration program
821  ! ----------------------------------------------------------------
822  !
823  ! 6. Error messages :
824  !
825  ! 7. Remarks :
826  !
827 
828  !
829  ! 8. Structure :
830  !
831  ! 9. Switches :
832  !
833  ! 10. Source code :
834  USE w3gdatmd, ONLY: nx, ny, ccon, countcon, iobp
835 
836 #ifdef W3_S
837  USE w3servmd, ONLY: strace
838 #endif
839 
840  IMPLICIT NONE
841  !/ ------------------------------------------------------------------- /
842  !/ Parameter list
843  !/
844  INTEGER, INTENT(INOUT) :: TMPSTA(NY,NX)
845 #ifdef W3_S
846  INTEGER, SAVE :: IENT = 0
847 #endif
848  REAL , INTENT(IN) :: ZBIN(NY,NX)
849  REAL , INTENT(IN) :: ZLIM
850  !/
851  !/ ------------------------------------------------------------------- /
852  !/ Local parameters
853  !/
854  INTEGER :: IBC, IX
855  INTEGER :: MASK(NX)
856  INTEGER*2 :: STATUS(NX)
857  !
858  mask(:)=1
859  CALL set_iobp (mask, status)
860  !
861 #ifdef W3_S
862  CALL strace (ient, 'UG_GETOPENBOUNDARY')
863 #endif
864  DO ibc = 1, n_outside_boundary
865  ix = outside_boundary(ibc)
866  !write(*,*) 'TEST1', IX, TMPSTA(1,IX), CCON(IX), COUNTCON(IX), ZBIN(1,IX), ZLIM
867  ! OUTSIDE_BOUNDARY(IBC) is defined over the full nodes NODES indexes
868  ! whereas TMPSTA and ZBIN are defined over the clean up list of nodes NX
869  IF ((ix.NE.0).AND.(ix.LE.nx)) THEN
870  IF ( (tmpsta(1,ix).EQ.1) .AND. (status(ix).EQ.0) .AND. (zbin(1,ix) .LT. zlim)) tmpsta(1,ix) = 2
871  END IF
872  END DO
873  !
874  END SUBROUTINE ug_getopenboundary
875  !/ ------------------------------------------------------------------- /
876 
877 
878  !/----------------------------------------------------------------------
879 
890  SUBROUTINE spatial_grid
891  !/ -------------------------------------------------------------------
892  !/ +-----------------------------------+
893  !/ | WAVEWATCH III NOAA/NCEP |
894  !/ | A. Roland (BGS IT&E GbmH) |
895  !/ | F. Ardhuin (IFREMER) |
896  !/ | FORTRAN 90 |
897  !/ | Last update : 31-Aug-2011|
898  !/ +-----------------------------------+
899  !/
900  !/ 15-May-2007 : Origination: adjustment from the WWM code ( version 3.13 )
901  !/ 31-Aug-2011 : Simplfies the cross products ( version 4.05 )
902  !/
903  !
904  ! 1. Purpose :
905  !
906  ! Calculates triangle areas and reorders the triangles to have them
907  ! oriented counterclockwise
908  !
909  ! 2. Method :
910  !
911  ! The triangle surface calculation is based on cross product.
912  !
913  ! 3. Parameters :
914  !
915  ! 4. Subroutines used :
916  !
917  ! 5. Called by :
918  !
919  ! Name Type Module Description
920  ! ----------------------------------------------------------------
921  ! READTRI Subr. Internal Unstructured mesh definition.
922  ! ----------------------------------------------------------------
923  !
924  ! 6. Error messages :
925  !
926  ! 7. Remarks :
927  !
928  ! This part of code is adapted from the WWM wave model develop at the Darmstadt University
929  ! (Aaron Roland)
930  !
931  ! 8. Structure :
932  !
933  ! 9. Switches :
934  !
935  ! 10. Source code :
936  !
937  !/ ------------------------------------------------------------------- /
938  USE w3gdatmd
939 #ifdef W3_S
940  USE w3servmd, ONLY: strace
941 #endif
942  USE w3odatmd, ONLY: ndse
943 
944  IMPLICIT NONE
945  !
946  !local parameters
947  !
948  REAL :: TL1, TL2, TL3, TMPTRIGP
949  INTEGER :: I1, I2, I3
950  INTEGER :: K
951  real*8 :: pt(3,2)
952 
953 #ifdef W3_S
954  INTEGER :: IENT = 0
955 #endif
956  !/ ------------------------------------------------------------------- /
957 #ifdef W3_S
958  CALL strace (ient, 'SPATIAL_GRID')
959 #endif
960 
961  DO k = 1, ntri
962 
963  i1 = trigp(1,k)
964  i2 = trigp(2,k)
965  i3 = trigp(3,k)
966 
967 !AR: todo call this only for global grid
968  CALL fix_periodcity(i1,i2,i3,xgrd,ygrd,pt)
969  !
970  ! cross product of edge-vector (orientated anticlockwise)
971  !
972  tria(k) = real( (pt(2,2)-pt(1,2)) &
973  *(pt(1,1)-pt(3,1)) &
974  +(pt(3,2)-pt(1,2)) &
975  *(pt(2,1)-pt(1,1)) )*0.5
976  !
977  ! test on negative triangle area, which means that the orientiation is not as assumed to be anticw.
978  ! therefore we swap the nodes !!!
979  !
980  IF (tria(k) .lt. tiny(1.)) THEN
981  tmptrigp = trigp(2,k)
982  trigp(2,k) = trigp(3,k)
983  trigp(3,k) = tmptrigp
984  i2 = trigp(2,k)
985  i3 = trigp(3,k)
986  tria(k) = -1.d0*tria(k)
987  END IF
988  END DO
989  END SUBROUTINE spatial_grid
990  !/--------------------------------------------------------------------/
991  !
992  !/--------------------------------------------------------------------/
993 
1003  SUBROUTINE nvectri
1004  !/ -------------------------------------------------------------------
1005  !/ +-----------------------------------+
1006  !/ | WAVEWATCH III NOAA/NCEP |
1007  !/ | A. Roland |
1008  !/ | FORTRAN 90 |
1009  !/ | Last update : 15-May-2008|
1010  !/ +-----------------------------------+
1011  !/
1012  !/ 15-May-2007 : Origination: adjustment from the WWM code ( version 3.13 )
1013  !/
1014  !
1015  ! 1. Purpose :
1016  !
1017  ! Calculate cell tools: inward normal, angles and length of edges.
1018  !
1019  ! 2. Method :
1020  ! To get inward pointing normals, triangle are glanced through anti-clockwisely
1021  !
1022  !
1023  ! 3. Parameters :
1024  !
1025  ! 4. Subroutines used :
1026  !
1027  ! 5. Called by :
1028  !
1029  ! Name Type Module Description
1030  ! ----------------------------------------------------------------
1031  ! READTRI Subr. Internal Unstructured mesh definition.
1032  ! ----------------------------------------------------------------
1033  !
1034  ! 6. Error messages :
1035  !
1036  ! 7. Remarks :
1037  !
1038  ! 8. Structure :
1039  !
1040  ! 9. Switches :
1041  !
1042  ! 10. Source code :
1043  !
1044  !/ ------------------------------------------------------------------- /
1045  USE w3gdatmd
1046 #ifdef W3_S
1047  USE w3servmd, ONLY: strace
1048 #endif
1049  USE constants
1050 
1051  IMPLICIT NONE
1052  !
1053  !local parameter
1054  !
1055  INTEGER :: IP, IE
1056  INTEGER :: I1, I2, I3, I11, I22, I33
1057  !
1058  real*8 :: p1(2), p2(2), p3(2)
1059  real*8 :: r1(2), r2(2), r3(2)
1060  real*8 :: n1(2), n2(2), n3(2)
1061  real*8 :: tmp(3)
1062  real*8 :: tmpinv(3)
1063  real*8 :: pt(3,2)
1064 #ifdef W3_S
1065  INTEGER :: IENT = 0
1066 #endif
1067  !/ ------------------------------------------------------------------- /
1068 #ifdef W3_S
1069  CALL strace (ient, 'NVECTRI')
1070 #endif
1071  !
1072  DO ie = 1, ntri
1073  !
1074  ! vertices
1075  !
1076  i1 = trigp(1,ie)
1077  i2 = trigp(2,ie)
1078  i3 = trigp(3,ie)
1079 
1080  CALL fix_periodcity(i1,i2,i3,xgrd,ygrd,pt)
1081 
1082  p1(1) = pt(1,1)
1083  p1(2) = pt(1,2)
1084  p2(1) = pt(2,1)
1085  p2(2) = pt(2,2)
1086  p3(1) = pt(3,1)
1087  p3(2) = pt(3,2)
1088  !
1089  ! I1 -> I2, I2 -> I3, I3 -> I1 (anticlockwise orientation is preserved)
1090  !
1091  r1 = p3-p2
1092  r2 = p1-p3
1093  r3 = p2-p1
1094 
1095  n1(1) = (-r1(2))
1096  n1(2) = ( r1(1))
1097  n2(1) = (-r2(2))
1098  n2(2) = ( r2(1))
1099  n3(1) = (-r3(2))
1100  n3(2) = ( r3(1))
1101  !
1102  ! edges length
1103  !
1104  len(ie,1) = dsqrt(r1(1)**2+r1(2)**2)
1105  len(ie,2) = dsqrt(r2(1)**2+r2(2)**2)
1106  len(ie,3) = dsqrt(r3(1)**2+r3(2)**2)
1107  !
1108  ! inward normal used for propagation (not normalized)
1109  !
1110  ien(ie,1) = n1(1)
1111  ien(ie,2) = n1(2)
1112  ien(ie,3) = n2(1)
1113  ien(ie,4) = n2(2)
1114  ien(ie,5) = n3(1)
1115  ien(ie,6) = n3(2)
1116 
1117  END DO
1118 
1119  END SUBROUTINE nvectri
1120  !/---------------------------------------------------------------------------
1121 
1122  !/------------------------------------------------------------------------
1123 
1134  SUBROUTINE count(TRIGPTEMP)
1135  !/ -------------------------------------------------------------------
1136  !/ +-----------------------------------+
1137  !/ | WAVEWATCH III NOAA/NCEP |
1138  !/ | A. Roland |
1139  !/ | F. Ardhuin |
1140  !/ | FORTRAN 90 |
1141  !/ | Last update : 15-May-2008|
1142  !/ +-----------------------------------+
1143  !/
1144  !/ 15-May-2007 : Origination. ( version 3.13 )
1145  !/
1146  !
1147  ! 1. Purpose :
1148  !
1149  ! Calculate global and maximum number of connection for array allocations .
1150  !
1151  ! 2. Method :
1152  !
1153  ! 3. Parameters :
1154  ! Parameter list
1155  ! ----------------------------------------------------------------
1156  ! NTRI Int. I Total number of triangle.
1157  ! TRIGPTEMP Int I Temporary array of triangle vertices
1158  ! COUNTRI Int O Maximum number of connected triangle
1159  ! for a given points
1160  ! COUNTOT Int O Global number of triangle connection
1161  ! for the whole grid.
1162  ! ----------------------------------------------------------------
1163  ! 4. Subroutines used :
1164  !
1165  ! 5. Called by :
1166  !
1167  ! Name Type Module Description
1168  ! ----------------------------------------------------------------
1169  ! READTRI Subr. Internal Unstructured mesh definition.
1170  ! ----------------------------------------------------------------
1171  !
1172  ! 6. Error messages :
1173  !
1174  ! 7. Remarks :
1175  !
1176  ! 8. Structure :
1177  !
1178  ! 9. Switches :
1179  !
1180  ! 10. Source code :
1181  !
1182  !/ ------------------------------------------------------------------- /
1183  USE w3gdatmd
1184 #ifdef W3_S
1185  USE w3servmd, ONLY: strace
1186 #endif
1187  IMPLICIT NONE
1188 
1189 
1190  !/ parameter list
1191 
1192  INTEGER,INTENT(IN) :: TRIGPTEMP(:,:)
1193  !/ ------------------------------------------------------------------- /
1194  !/ local parameter
1195 
1196  INTEGER :: CONN(NX)
1197  INTEGER :: COUNTER, IP, IE, I, J, N(3)
1198 #ifdef W3_S
1199  INTEGER :: IENT = 0
1200 #endif
1201  !/------------------------------------------------------------------------
1202 
1203 #ifdef W3_S
1204  CALL strace (ient, 'COUNT')
1205 #endif
1206 
1207  countri=0
1208  countot=0
1209  conn(:)= 0
1210 
1211  !
1212  !calculate the number of connected triangles for a given point.
1213  !
1214 
1215  DO ie = 1,ntri
1216  n(:) = 0.
1217  n(1) = trigptemp(1,ie)
1218  n(2) = trigptemp(2,ie)
1219  n(3) = trigptemp(3,ie)
1220  conn(n(1)) = conn(n(1)) + 1
1221  conn(n(2)) = conn(n(2)) + 1
1222  conn(n(3)) = conn(n(3)) + 1
1223  ENDDO
1224 
1225  countri = maxval(conn)
1226  !
1227  ! calculate the global number of connections available through the mesh
1228  !
1229  j=0
1230  DO ip=1,nx
1231  DO i=1,conn(ip)
1232  j=j+1
1233  ENDDO
1234  ENDDO
1235  countot=j
1236 
1237  END SUBROUTINE count
1238 
1239  !/----------------------------------------------------------------------------
1240 
1248  SUBROUTINE coordmax
1249  !/ -------------------------------------------------------------------
1250  !/ +-----------------------------------+
1251  !/ | WAVEWATCH III NOAA/NCEP |
1252  !/ | F. Ardhuin |
1253  !/ | FORTRAN 90 |
1254  !/ | Last update : 15-May-2008|
1255  !/ +-----------------------------------+
1256  !/
1257  !/ 15-May-2007 : Origination. ( version 3.13 )
1258  !/
1259  ! 1. Purpose :
1260  !
1261  ! Calculate first point and last point coordinates, and minimum and maximum edge length.
1262  !
1263  ! 2. Method :
1264  !
1265  ! 3. Parameters :
1266  !
1267  ! 4. Subroutines used :
1268  !
1269  ! 5. Called by :
1270  !
1271  ! Name Type Module Description
1272  ! ----------------------------------------------------------------
1273  ! READTRI Subr. Internal Unstructured mesh definition.
1274  ! ----------------------------------------------------------------
1275  !
1276  ! 6. Error messages :
1277  !
1278  ! 7. Remarks :
1279  !
1280  ! 8. Structure :
1281  !
1282  ! 9. Switches :
1283  !
1284  ! 10. Source code :
1285  !
1286  !/ ------------------------------------------------------------------- /
1287  USE w3gdatmd
1288 #ifdef W3_S
1289  USE w3servmd, ONLY: strace
1290 #endif
1291  IMPLICIT NONE
1292 #ifdef W3_S
1293  INTEGER :: IENT = 0
1294 #endif
1295 
1296 
1297 #ifdef W3_S
1298  CALL strace (ient, 'COORDMAX')
1299 #endif
1300  !
1301  ! maximum of coordinates s
1302  !
1303  maxx = maxval(xgrd(1,:))
1304  maxy = maxval(ygrd(1,:))
1305  !
1306  ! minimum of coordinates
1307  !
1308  x0 = minval(xgrd(1,:))
1309  y0 = minval(ygrd(1,:))
1310  !
1311  !maximum and minimum length of edges
1312  !
1313  dxymax = maxval(len(:,:))
1314  sx = minval(len(:,:))
1315  sy = sx
1316  !
1317  END SUBROUTINE coordmax
1318  !-------------------------------------------------------------------------
1319 
1336  SUBROUTINE area_si(IMOD)
1337  !/ -------------------------------------------------------------------
1338  !/ +-----------------------------------+
1339  !/ | WAVEWATCH III NOAA/NCEP |
1340  !/ | A. Roland |
1341  !/ | FORTRAN 90 |
1342  !/ | Last update : 23-Aug-2011|
1343  !/ +-----------------------------------+
1344  !/
1345  !/ 15-May-2007 : Origination: adjustment from the WWM code ( version 3.13 )
1346  !/ 23-Aug-2011 : Removes double entries in VNEIGH ( version 4.04 )
1347  !/
1348  !
1349  ! 1. Purpose :
1350  !
1351  ! Define optimized connection arrays (points and triangles) for spatial propagation schemes.
1352  !
1353  ! 2. Method :
1354  !
1355  ! 3. Parameters :
1356  !
1357  ! 4. Subroutines used :
1358  !
1359  ! 5. Called by :
1360  !
1361  ! Name Type Module Description
1362  ! ----------------------------------------------------------------
1363  ! READTRI Subr. Internal Unstructured mesh definition.
1364  ! ----------------------------------------------------------------
1365  !
1366  ! 6. Error messages :
1367  !
1368  ! 7. Remarks :
1369  !
1370  ! The storage is optimize especially considering the iterative solver used.
1371  ! The schemes used are vertex-centered, a point has to be considered within its
1372  ! median dual cell. For a given point, the surface of the dual cell is one third
1373  ! of the sum of the surface of connected triangles.
1374  ! This routine is from WWM developped in Darmstadt(Aaron Roland)
1375  !
1376  ! 8. Structure :
1377  !
1378  ! 9. Switches :
1379  !
1380  ! 10. Source code :
1381  !
1382  !/ ------------------------------------------------------------------- /
1383 
1384  USE w3gdatmd
1385 #ifdef W3_S
1386  USE w3servmd, ONLY: strace
1387 #endif
1388  IMPLICIT NONE
1389  !/ input
1390 
1391  INTEGER, INTENT(IN) :: IMOD
1392 
1393  !/ local parameters
1394 
1395  INTEGER :: COUNTER,ifound,alreadyfound
1396  INTEGER :: I, J, K, II
1397  INTEGER :: IP, IE, POS, POS_I, POS_J, POS_K, IP_I, IP_J, IP_K
1398  INTEGER :: I1, I2, I3, IP2, CHILF(NX)
1399  INTEGER :: TMP(NX), CELLVERTEX(NX,COUNTRI,2)
1400  INTEGER :: COUNT_MAX
1401  DOUBLE PRECISION :: TRIA03
1402  INTEGER, ALLOCATABLE :: PTABLE(:,:)
1403 
1404 #ifdef W3_S
1405  INTEGER :: IENT = 0
1406 #endif
1407  !/ ------------------------------------------------------------------- /
1408 
1409 #ifdef W3_S
1410  CALL strace (ient, 'AREA_SI')
1411 #endif
1412 
1413  si(:) = 0.d0
1414  !
1415  ccon(:) = 0 ! Number of connected Elements
1416  DO ie = 1, ntri
1417  i1 = trigp(1,ie)
1418  i2 = trigp(2,ie)
1419  i3 = trigp(3,ie)
1420  ccon(i1) = ccon(i1) + 1
1421  ccon(i2) = ccon(i2) + 1
1422  ccon(i3) = ccon(i3) + 1
1423  tria03 = 1./3. * tria(ie)
1424  si(i1) = si(i1) + tria03
1425  si(i2) = si(i2) + tria03
1426  si(i3) = si(i3) + tria03
1427  ENDDO
1428 
1429  cellvertex(:,:,:) = 0 ! Stores for each node the Elementnumbers of the connected Elements
1430  ! and the Position of the Node in the Element Index
1431 
1432  chilf = 0
1433 
1434  DO ie = 1, ntri
1435  DO j=1,3
1436  i = trigp(j,ie)!INE(J,IE)
1437  chilf(i) = chilf(i)+1
1438  cellvertex(i,chilf(i),1) = ie
1439  cellvertex(i,chilf(i),2) = j
1440  END DO
1441  ENDDO
1442  !
1443  ! Second step in storage, the initial 3D array CELLVERTEX, is transformed in a 1D array
1444  ! the global index is J . From now, all the computation step based on these arrays must
1445  ! abide by the conservation of the 2 loop algorithm (points + connected triangles)
1446  !
1447  index_cell(1)=1
1448  j = 0
1449  DO ip = 1, nx
1450  DO i = 1, ccon(ip)
1451  j = j + 1
1452  ie_cell(j) = cellvertex(ip,i,1)
1453  pos_cell(j) = cellvertex(ip,i,2)
1454  END DO
1455  index_cell(ip+1)=j+1
1456  END DO
1457 
1458  IF (.NOT. fsnimp) RETURN
1459 
1460  j = 0
1461  DO ip = 1, nx
1462  DO i = 1, ccon(ip)
1463  j = j + 1
1464  END DO
1465  END DO
1466 
1467  count_max = j
1468 
1469  ALLOCATE(ptable(count_max,7))
1470 
1471  j = 0
1472  ptable(:,:) = 0.
1473  DO ip = 1, nx
1474  DO i = 1, ccon(ip)
1475  j = j + 1
1476  ie = ie_cell(j)
1477  pos = pos_cell(j)
1478  i1 = trigp(1,ie)
1479  i2 = trigp(2,ie)
1480  i3 = trigp(3,ie)
1481  IF (pos == 1) THEN
1482  pos_j = 2
1483  pos_k = 3
1484  ELSE IF (pos == 2) THEN
1485  pos_j = 3
1486  pos_k = 1
1487  ELSE
1488  pos_j = 1
1489  pos_k = 2
1490  END IF
1491  ip_i = ip
1492  ip_j = trigp(pos_j,ie)
1493  ip_k = trigp(pos_k,ie)
1494  ptable(j,1) = ip_i
1495  ptable(j,2) = ip_j
1496  ptable(j,3) = ip_k
1497  ptable(j,4) = pos
1498  ptable(j,5) = pos_j
1499  ptable(j,6) = pos_k
1500  ptable(j,7) = ie
1501  END DO
1502  END DO
1503 
1504  ! WRITE(*,'("+TRACE......",A)') 'SET UP SPARSE MATRIX POINTER ... COUNT NONZERO ENTRY'
1505 
1506  j = 0
1507  k = 0
1508  DO ip = 1, nx
1509  tmp(:) = 0
1510  DO i = 1, ccon(ip)
1511  j = j + 1
1512  ip_j = ptable(j,2)
1513  ip_k = ptable(j,3)
1514  pos = ptable(j,4)
1515  tmp(ip) = 1
1516  tmp(ip_j) = 1
1517  tmp(ip_k) = 1
1518  END DO
1519  k = k + sum(tmp)
1520  END DO
1521 
1522  nnz => grids(imod)%NNZ
1523  nnz = k
1524 
1525  ! WRITE(*,'("+TRACE......",A)') 'SET UP SPARSE MATRIX POINTER ... SETUP POINTER'
1526 
1527  ALLOCATE (grids(imod)%JAA(nnz))
1528  ALLOCATE (grids(imod)%IAA(nx+1))
1529  ALLOCATE (grids(imod)%POSI(3,count_max))
1530  jaa => grids(imod)%JAA
1531  iaa => grids(imod)%IAA
1532  posi => grids(imod)%POSI
1533 
1534  j = 0
1535  k = 0
1536  iaa(1) = 1
1537  jaa = 0
1538  DO ip = 1, nx ! Run through all rows
1539  tmp = 0
1540  DO i = 1, ccon(ip) ! Check how many entries there are ...
1541  j = j + 1 ! this is the same J index as in IE_CELL
1542  ip_j = ptable(j,2)
1543  ip_k = ptable(j,3)
1544  tmp(ip) = 1
1545  tmp(ip_j) = 1
1546  tmp(ip_k) = 1
1547  END DO
1548  DO i = 1, nx ! Run through all columns
1549  IF (tmp(i) .GT. 0) THEN ! this is true only for the connected points
1550  k = k + 1
1551  jaa(k) = i
1552  END IF
1553  END DO
1554  iaa(ip + 1) = k + 1
1555  END DO
1556 
1557  posi = 0
1558  j = 0
1559  DO ip = 1, nx
1560  DO i = 1, ccon(ip)
1561  j = j + 1
1562  ip_j = ptable(j,2)
1563  ip_k = ptable(j,3)
1564  DO k = iaa(ip), iaa(ip+1) - 1
1565  IF (ip == jaa(k)) posi(1,j) = k
1566  IF (ip_j == jaa(k)) posi(2,j) = k
1567  IF (ip_k == jaa(k)) posi(3,j) = k
1568  IF (k == 0) THEN
1569  WRITE(*,*) .EQ.'ERROR IN AREA_SI K 0'
1570  stop
1571  END IF
1572  END DO
1573  END DO
1574  END DO
1575 
1576  DEALLOCATE(ptable)
1577 
1578  END SUBROUTINE area_si
1579 
1604  SUBROUTINE is_in_ungrid(IMOD, XTIN, YTIN, ITOUT, IS, JS, RW)
1605  !/ -------------------------------------------------------------------
1606  !/ +-----------------------------------+
1607  !/ | WAVEWATCH III NOAA/NCEP |
1608  !/ | Mathieu Dutour Sikiric, IRB |
1609  !/ | Aron Roland, Z&P |
1610  !/ | Fabrice Ardhuin |
1611  !/ | FORTRAN 90 |
1612  !/ | Last update : 26-Jan-2014|
1613  !/ +-----------------------------------+
1614  !/
1615  !/ Adapted from other subroutine
1616  !/ 15-Oct-2007 : Origination. ( version 3.13 )
1617  !/ 21-Sep-2012 : Uses same interpolation as regular ( version 4.08 )
1618  !/ 26-Jan-2014 : Correcting bug in RW ( version 4.18 )
1619  !/
1620  ! 1. Purpose :
1621  !
1622  ! Determine whether a point is inside or outside an unstructured grid,
1623  ! and returns index of triangle and interpolation weights
1624  ! This is the analogue for triangles of the FUNCTION W3GRMP
1625  !
1626  ! 2. Method :
1627  !
1628  ! Using barycentric coordinates defined as the ratio of triangle algebric areas
1629  ! which are positive or negative.
1630  ! Computes the 3 interpolation weights for each triangle until they are all positive
1631  !
1632  ! 3. Parameters :
1633  !
1634  ! Parameter list
1635  ! ----------------------------------------------------------------
1636  ! IMOD Int. I Model number to point to.
1637  ! XTIN Real I X-coordinate of target point.
1638  ! YTIN Real I Y-coordinate of target point.
1639  ! ITOUT Int. I Model number to point to.
1640  ! IS,JS I.A. O (I,J) indices of vertices of enclosing grid cell.
1641  ! RW R.A. O Array of interpolation weights.
1642  ! ----------------------------------------------------------------
1643  !
1644  ! 4. Subroutines used :
1645  !
1646  ! None
1647  !
1648  ! 5. Called by :
1649  !
1650  ! WMGLOW, W3IOPP, WMIOPP, WW3_GINT
1651  !
1652  ! 6. Error messages :
1653  !
1654  ! - Error checks on previous setting of variable.
1655  !
1656  ! 7. Remarks :
1657  !
1658  ! 8. Structure :
1659  !
1660  ! 9. Switches :
1661  !
1662  ! !/S Enable subroutine tracing.
1663  ! !/T Enable test output
1664  !
1665  ! 10. Source code :
1666  !
1667  ! 2. Method :
1668  !
1669  ! Using barycentric coordinates. Each coefficient depends on the mass of its related point in the interpolation.
1670  !
1671  ! 3. Parameters :
1672  !
1673  ! 4. Subroutines used :
1674  !
1675  ! 5. Called by :
1676  !
1677  ! Name Type Module Description
1678  ! ----------------------------------------------------------------
1679  ! W3IOPP Subr. Internal Preprocessing of point output.
1680  ! ----------------------------------------------------------------
1681  !
1682  ! 6. Error messages :
1683  !
1684  ! 7. Remarks :
1685  !
1686  ! This subroutine is adjusted from CREST code (Fabrice Ardhuin)
1687  ! For a given output point, the algorithm enable to glance through all the triangles
1688  ! to find the one the point belong to, and then make interpolation.
1689  !
1690  ! 8. Structure :
1691  !
1692  ! 9. Switches :
1693  !
1694  ! !/LLG Spherical grid.
1695  ! !/XYG Carthesian grid.
1696  !
1697  ! 10. Source code :
1698  !
1699  !/ ------------------------------------------------------------------- /
1700  USE w3gdatmd
1701  USE w3servmd, ONLY: extcde
1702 #ifdef W3_S
1703  USE w3servmd, ONLY: strace
1704 #endif
1705  USE w3odatmd, ONLY: ndse
1706  IMPLICIT NONE
1707 
1708  !/ ------------------------------------------------------------------- /
1709  ! Parameter list
1710 
1711  INTEGER, INTENT(IN) :: IMOD
1712  DOUBLE PRECISION, INTENT(IN) :: XTIN, YTIN
1713  INTEGER, INTENT(OUT) :: itout
1714  INTEGER, INTENT(OUT) :: IS(4), JS(4)
1715  REAL, INTENT(OUT) :: RW(4)
1716  !/ ------------------------------------------------------------------- /
1717  !local parameters
1718 
1719  DOUBLE PRECISION :: x1, x2, x3
1720  DOUBLE PRECISION :: y1, y2, y3
1721  DOUBLE PRECISION :: s1, s2, s3, sg1, sg2, sg3
1722  real*8 :: pt(3,2)
1723  INTEGER :: ITRI
1724  INTEGER :: I1, I2, I3
1725  INTEGER :: nbFound
1726 #ifdef W3_S
1727  INTEGER :: IENT = 0
1728  CALL strace (ient, 'IS_IN_UNGRID')
1729 #endif
1730 
1731  !
1732  itout = 0
1733  nbfound=0
1734  itri = 0
1735  DO WHILE (nbfound.EQ.0.AND.itri.LT.grids(imod)%NTRI)
1736  itri = itri +1
1737  i1=grids(imod)%TRIGP(1,itri)
1738  i2=grids(imod)%TRIGP(2,itri)
1739  i3=grids(imod)%TRIGP(3,itri)
1740 
1741  CALL fix_periodcity(i1,i2,i3,grids(imod)%XGRD,grids(imod)%YGRD,pt)
1742  ! coordinates of the first vertex A
1743  x1 = pt(1,1)
1744  y1 = pt(1,2)
1745  ! coordinates of the 2nd vertex B
1746  x2 = pt(2,1)
1747  y2 = pt(2,2)
1748  !coordinates of the 3rd vertex C
1749  x3 = pt(3,1)
1750  y3 = pt(3,2)
1751  !with M = (XTIN,YTIN) the target point ...
1752  !vector product of AB and AC
1753  sg3=(y3-y1)*(x2-x1)-(x3-x1)*(y2-y1)
1754  !vector product of AB and AM
1755  s3=(ytin-y1)*(x2-x1)-(xtin-x1)*(y2-y1)
1756  !vector product of BC and BA
1757  sg1=(y1-y2)*(x3-x2)-(x1-x2)*(y3-y2)
1758  !vector product of BC and BM
1759  s1=(ytin-y2)*(x3-x2)-(xtin-x2)*(y3-y2)
1760  !vector product of CA and CB
1761  sg2=(y2-y3)*(x1-x3)-(x2-x3)*(y1-y3)
1762  !vector product of CA and CM
1763  s2=(ytin-y3)*(x1-x3)-(xtin-x3)*(y1-y3)
1764  IF ((s1*sg1.GE.0).AND.(s2*sg2.GE.0).AND.(s3*sg3.GE.0)) THEN
1765  itout=itri
1766  nbfound=nbfound+1
1767  is(1)=i1
1768  is(2)=i2
1769  is(3)=i3
1770  is(4)=1
1771  js(:)=1
1772  rw(1)=s1/sg1
1773  rw(2)=s2/sg2
1774  rw(3)=1.-rw(1)-rw(2) !s3/sg3
1775  rw(4)=0.
1776  END IF
1777  ENDDO
1778  END SUBROUTINE is_in_ungrid
1779  !/ -------------------------------------------------------------------
1780 
1806  SUBROUTINE is_in_ungrid2(IMOD, XTIN, YTIN, FORCE, ITOUT, IS, JS, RW)
1807  !/ -------------------------------------------------------------------
1808  !/ +-----------------------------------+
1809  !/ | WAVEWATCH III NOAA/NCEP |
1810  !/ | Mathieu Dutour Sikiric, IRB |
1811  !/ | Aron Roland, Z&P |
1812  !/ | Fabrice Ardhuin |
1813  !/ | FORTRAN 90 |
1814  !/ | Last update : 26-Jan-2014|
1815  !/ +-----------------------------------+
1816  !/
1817  !/ Adapted from other subroutine
1818  !/ 15-Oct-2007 : Origination. ( version 3.13 )
1819  !/ 21-Sep-2012 : Uses same interpolation as regular ( version 4.08 )
1820  !/ 26-Jan-2014 : Correcting bug in RW ( version 4.18 )
1821  !/
1822  ! 1. Purpose :
1823  !
1824  ! Determine whether a point is inside or outside an unstructured grid,
1825  ! and returns index of triangle and interpolation weights
1826  ! This is the analogue for triangles of the FUNCTION W3GRMP
1827  !
1828  ! 2. Method :
1829  !
1830  ! Using barycentric coordinates defined as the ratio of triangle algebric areas
1831  ! which are positive or negative.
1832  ! Computes the 3 interpolation weights for each triangle until they are all positive
1833  !
1834  ! 3. Parameters :
1835  !
1836  ! Parameter list
1837  ! ----------------------------------------------------------------
1838  ! IMOD Int. I Model number to point to.
1839  ! XTIN Real I X-coordinate of target point.
1840  ! YTIN Real I Y-coordinate of target point.
1841  ! ITOUT Int. I Model number to point to.
1842  ! IS,JS I.A. O (I,J) indices of vertices of enclosing grid cell.
1843  ! RW R.A. O Array of interpolation weights.
1844  ! ----------------------------------------------------------------
1845  !
1846  ! 4. Subroutines used :
1847  !
1848  ! None
1849  !
1850  ! 5. Called by :
1851  !
1852  ! WMGLOW, W3IOPP, WMIOPP, WW3_GINT
1853  !
1854  ! 6. Error messages :
1855  !
1856  ! - Error checks on previous setting of variable.
1857  !
1858  ! 7. Remarks :
1859  !
1860  ! 8. Structure :
1861  !
1862  ! 9. Switches :
1863  !
1864  ! !/S Enable subroutine tracing.
1865  ! !/T Enable test output
1866  !
1867  ! 10. Source code :
1868  !
1869 
1870 
1871  ! 2. Method :
1872  !
1873  ! Using barycentric coordinates. Each coefficient depends on the mass of its related point in the interpolation.
1874  !
1875  ! 3. Parameters :
1876  !
1877  ! 4. Subroutines used :
1878  !
1879  ! 5. Called by :
1880  !
1881  ! Name Type Module Description
1882  ! ----------------------------------------------------------------
1883  ! W3IOPP Subr. Internal Preprocessing of point output.
1884  ! ----------------------------------------------------------------
1885  !
1886  ! 6. Error messages :
1887  !
1888  ! 7. Remarks :
1889  !
1890  ! This subroutine is adjusted from CREST code (Fabrice Ardhuin)
1891  ! For a given output point, the algorithm enable to glance through all the triangles
1892  ! to find the one the point belong to, and then make interpolation.
1893  !
1894  ! 8. Structure :
1895  !
1896  ! 9. Switches :
1897  !
1898  ! !/LLG Spherical grid.
1899  ! !/XYG Carthesian grid.
1900  !
1901  ! 10. Source code :
1902  !
1903  !/ ------------------------------------------------------------------- /
1904  USE w3gdatmd
1905  USE w3servmd, ONLY: extcde
1906 #ifdef W3_S
1907  USE w3servmd, ONLY: strace
1908 #endif
1909  USE w3odatmd, ONLY: ndse
1910  IMPLICIT NONE
1911 
1912  !/ ------------------------------------------------------------------- /
1913  ! Parameter list
1914 
1915  INTEGER, INTENT(IN) :: IMOD, FORCE
1916  DOUBLE PRECISION, INTENT(IN) :: XTIN, YTIN
1917  INTEGER, INTENT(OUT) :: itout
1918  INTEGER, INTENT(OUT) :: IS(4), JS(4)
1919  REAL, INTENT(OUT) :: RW(4)
1920  !/ ------------------------------------------------------------------- /
1921  !local parameters
1922 
1923  DOUBLE PRECISION :: x1, x2, x3, D1, D2, D3, DISTMIN, DDMIN
1924  DOUBLE PRECISION :: s1, s2, s3, sg1, sg2, sg3, smin, ssum
1925  DOUBLE PRECISION :: y1, y2, y3
1926  INTEGER :: ITRI, ITRIS
1927  INTEGER :: I1, I2, I3
1928  INTEGER :: nbFound
1929  LOGICAL :: MAPSTAOK
1930 #ifdef W3_S
1931  INTEGER :: IENT = 0
1932  CALL strace (ient, 'IS_IN_UNGRID2')
1933 #endif
1934 
1935  !
1936  itout = 0
1937  nbfound=0
1938  itri = 0
1939  itris = 1
1940  ssum = 0
1941  smin = 0
1942  DO WHILE (nbfound.EQ.0.AND.itri.LT.grids(imod)%NTRI)
1943  itri = itri +1
1944  i1=grids(imod)%TRIGP(1,itri)
1945  i2=grids(imod)%TRIGP(2,itri)
1946  i3=grids(imod)%TRIGP(3,itri)
1947  ! coordinates of the first vertex A
1948  x1=grids(imod)%XGRD(1,i1)
1949  y1=grids(imod)%YGRD(1,i1)
1950  ! coordinates of the 2nd vertex B
1951  x2=grids(imod)%XGRD(1,i2)
1952  y2=grids(imod)%XGRD(1,i2)
1953  !coordinates of the 3rd vertex C
1954  x3=grids(imod)%XGRD(1,i3)
1955  y3=grids(imod)%YGRD(1,i3)
1956  !with M = (XTIN,YTIN) the target point ...
1957  !vector product of AB and AC
1958  sg3=(y3-y1)*(x2-x1)-(x3-x1)*(y2-y1)
1959  !vector product of AB and AM
1960  s3=(ytin-y1)*(x2-x1)-(xtin-x1)*(y2-y1)
1961  !vector product of BC and BA
1962  sg1=(y1-y2)*(x3-x2)-(x1-x2)*(y3-y2)
1963  !vector product of BC and BM
1964  s1=(ytin-y2)*(x3-x2)-(xtin-x2)*(y3-y2)
1965  !vector product of CA and CB
1966  sg2=(y2-y3)*(x1-x3)-(x2-x3)*(y1-y3)
1967  !vector product of CA and CM
1968  s2=(ytin-y3)*(x1-x3)-(xtin-x3)*(y1-y3)
1969  ! ssum = ABS(s1*sg1)+ABS(s2*sg2)+ABS(s3*sg3)
1970  mapstaok = ((grids(imod)%MAPSTA(1,i1).GE.1).AND. &
1971  (grids(imod)%MAPSTA(1,i2).GE.1).AND.(grids(imod)%MAPSTA(1,i3).GE.1))
1972  IF (force.LT.2) mapstaok =.true.
1973  ssum = (xtin-(x1+x2+x3)/3.)**2+(ytin-(y1+y2+y2)/3.)**2
1974  IF (smin.EQ.0.AND. mapstaok ) smin=ssum
1975  !WRITE(6,*) 'ssum',ITRI,MAPSTAOK,ssum,smin
1976  IF (ssum.LT.smin .AND. mapstaok ) THEN
1977  smin=ssum
1978  itris=itri
1979  ENDIF
1980  IF ((s1*sg1.GE.0).AND.(s2*sg2.GE.0).AND.(s3*sg3.GE.0)) THEN
1981  itout=itri
1982  nbfound=nbfound+1
1983  is(1)=i1
1984  is(2)=i2
1985  is(3)=i3
1986  is(4)=1
1987  js(:)=1
1988  rw(1)=s1/sg1
1989  rw(2)=s2/sg2
1990  rw(3)=1.-rw(1)-rw(2) !s3/sg3
1991  rw(4)=0.
1992  END IF
1993  ENDDO
1994  IF (itout.EQ.0.AND.force.GT.0) THEN
1995  itri=itris
1996  i1=grids(imod)%TRIGP(1,itri)
1997  i2=grids(imod)%TRIGP(2,itri)
1998  i3=grids(imod)%TRIGP(3,itri)
1999  ! coordinates of the first vertex A
2000  x1=grids(imod)%XGRD(1,i1)
2001  y1=grids(imod)%YGRD(1,i1)
2002  ! coordinates of the 2nd vertex B
2003  x2=grids(imod)%XGRD(1,i2)
2004  y2=grids(imod)%YGRD(1,i2)
2005  !coordinates of the 3rd vertex C
2006  x3=grids(imod)%XGRD(1,i3)
2007  y3=grids(imod)%YGRD(1,i3)
2008  d1=(xtin-x1)**2+(ytin-y1)**2
2009  d2=(xtin-x2)**2+(ytin-y2)**2
2010  d3=(xtin-x3)**2+(ytin-y3)**2
2011  IF (d1.LE.d2.AND.d1.LE.d3) is(1)=i1
2012  IF (d2.LE.d1.AND.d2.LE.d3) is(1)=i2
2013  IF (d3.LE.d2.AND.d3.LE.d1) is(1)=i3
2014  is(2:4)=1
2015  js(:)=1
2016  rw(1)=1
2017  rw(2:4)=0.
2018  itout=itri
2019 
2020  ENDIF
2021  END SUBROUTINE is_in_ungrid2
2022  !/ ------------------------------------------------------------------- /
2023 
2038  SUBROUTINE ug_gradients (PARAM, DIFFX, DIFFY)
2039  !/ +-----------------------------------+
2040  !/ | WAVEWATCH III NOAA/NCEP |
2041  !/ | F. Ardhuin |
2042  !/ | A. Roland |
2043  !/ | FORTRAN 90 |
2044  !/ | Last update : 14-Oct-2013|
2045  !/ +-----------------------------------+
2046  !/
2047  !/ 15-Nov-2007 : Origination. ( version 3.13 )
2048  !/ 31-Oct-2010 : Merging of 4.03 with 3.14-Ifremer ( version 4.04 )
2049  !/ 08-Nov-2011 : Correction for zero grad. on contour( version 4.04 )
2050  !/ 14-Oct-2013 : Correction of latitude factor ( version 4.12 )
2051  !/ 01-Mai-2018 : Using linear shape function for gradients [ version 6.04)
2052  !/
2053  !
2054  ! 1. purpose: calculate gradients at a point via its connection.
2055  ! 2. Method : using linear shape function this is a basis on which
2056  ! all advection schemes in Roland (2008) are checked.
2057  !
2058  ! 3. Parameters :
2059  ! PARAM : depth or current field (indices 0 to NSEA)
2060  ! DIFFX : x gradient (indices 1 to NX)
2061  ! DIFFY : y gradient (indices 1 to NX)
2062  !
2063  ! 4. Subroutines used :
2064  !
2065  ! 5. Called by :
2066  !
2067  ! Name Type Module Description
2068  ! ----------------------------------------------------------------
2069  ! W3WAVE Subr. Actual wind wave routine
2070  ! ----------------------------------------------------------------
2071  !
2072  ! 6. Error messages :
2073  !
2074  ! 7. Remarks :
2075  !
2076  ! This subroutine is adjusted from WWM code (Aaron Roland)
2077  !
2078  ! 8. Structure :
2079  !
2080  ! 9. Switches :
2081  !
2082  ! 10. Source code :
2083  USE constants
2084  USE w3gdatmd, ONLY : trigp, ntri, nx, nsea, mapfs, clatis, &
2086  USE w3adatmd, ONLY : nsealm
2087 #ifdef W3_PDLIB
2088  USE yowelementpool
2089  use yownodepool, only: pdlib_ien, pdlib_tria, npa
2091 #endif
2092 
2093  IMPLICIT NONE
2094 
2095 
2096  REAL, INTENT(IN) :: PARAM(0:NSEA)
2097  REAL, INTENT(OUT) :: DIFFX(:,:), DIFFY(:,:)
2098 
2099  ! local parameters
2100 
2101  INTEGER :: VERTICES(3), NI(3), NI_GL(3)
2102  REAL :: TMP1(3), TMP2(3)
2103  INTEGER :: I, IX, IE, IE_GL
2104  REAL :: VAR(3), FACT, LATMEAN
2105  REAL :: DIFFXTMP, DIFFYTMP
2106  REAL :: DEDX(3), DEDY(3)
2107  REAL :: DVDXIE, DVDYIE
2108  REAL :: WEI(NX), WEI_LOCAL(NSEAL)
2109  real*8 :: rtmp(nseal)
2110 
2111  diffx = 0.
2112  diffy = 0.
2113  !
2114  IF (flagll) THEN
2115  fact=1./(dera*radius)
2116  ELSE
2117  fact=1.
2118  END IF
2119 
2120 #ifdef W3_PDLIB
2121  IF (.NOT. lpdlib) THEN
2122 #endif
2123  wei = 0.
2124  DO ie = 1, ntri
2125  ni = trigp(:,ie)
2126  latmean = 1./3. * sum(clatis(mapfs(1,ni)))
2127  wei(ni) = wei(ni) + 2.*tria(ie)
2128  dedx(1) = ien(ie,1)
2129  dedx(2) = ien(ie,3)
2130  dedx(3) = ien(ie,5)
2131  dedy(1) = ien(ie,2)
2132  dedy(2) = ien(ie,4)
2133  dedy(3) = ien(ie,6)
2134  var = param(mapfs(1,ni)) * fact
2135  dvdxie = dot_product( var,dedx)
2136  dvdyie = dot_product( var,dedy)
2137  diffx(1,ni) = diffx(1,ni) + dvdxie * latmean
2138  diffy(1,ni) = diffy(1,ni) + dvdyie
2139  END DO
2140  diffx(1,:) = diffx(1,:)/wei
2141  diffy(1,:) = diffy(1,:)/wei
2142 #ifdef W3_PDLIB
2143  ELSE
2144  wei_local = 0.
2145  DO ie = 1, ne
2146  ni = ine(:,ie)
2147  ie_gl = ielg(ie)
2148  ni_gl = trigp(:,ie_gl)
2149  latmean = 1./3. * sum(clatis(mapfs(1,ni_gl)))
2150  wei_local(ni) = wei_local(ni) + 2.*pdlib_tria(ie)
2151  dedx(1) = pdlib_ien(1,ie)
2152  dedx(2) = pdlib_ien(3,ie)
2153  dedx(3) = pdlib_ien(5,ie)
2154  dedy(1) = pdlib_ien(2,ie)
2155  dedy(2) = pdlib_ien(4,ie)
2156  dedy(3) = pdlib_ien(6,ie)
2157  var = param(mapfs(1,ni_gl)) * fact
2158  dvdxie = dot_product(var,dedx)
2159  dvdyie = dot_product(var,dedy)
2160  diffx(1,ni) = diffx(1,ni) + dvdxie * latmean
2161  diffy(1,ni) = diffy(1,ni) + dvdyie
2162  END DO
2163  diffx(1,:) = diffx(1,:)/wei_local
2164  diffy(1,:) = diffy(1,:)/wei_local
2165  ENDIF
2166  CALL pdlib_exchange1dreal(diffx(1,:))
2167  CALL pdlib_exchange1dreal(diffy(1,:))
2168 #endif
2169  !
2170  END SUBROUTINE ug_gradients
2171  !/ ------------------------------------------------------------------- /
2172 
2183  SUBROUTINE w3nestug(DISTMIN,FLOK)
2184  !/
2185  !/ +-----------------------------------+
2186  !/ | WAVEWATCH III NOAA/NCEP |
2187  !/ | |
2188  !/ | Aron Roland (BGS IT&E GmbH) |
2189  !/ | Mathieu Dutour-Sikiric (IRB) |
2190  !/ | |
2191  !/ | FORTRAN 90 |
2192  !/ | Last update : 01-June-2018 |
2193  !/ +-----------------------------------+
2194  !/
2195  !/ 01-June-2018 : Origination. ( version 6.04 )
2196  !/
2197  ! 1. Purpose : UGTYPE nesting initialization
2198  ! 2. Method :
2199  ! 3. Parameters :
2200  !
2201  ! Parameter list
2202  ! ----------------------------------------------------------------
2203  ! ----------------------------------------------------------------
2204  !
2205  ! 4. Subroutines used :
2206  !
2207  ! Name Type Module Description
2208  ! ----------------------------------------------------------------
2209  ! STRACE Subr. W3SERVMD Subroutine tracing.
2210  ! ----------------------------------------------------------------
2211  !
2212  ! 5. Called by :
2213  !
2214  ! Name Type Module Description
2215  ! ----------------------------------------------------------------
2216  ! ----------------------------------------------------------------
2217  !
2218  ! 6. Error messages :
2219  ! 7. Remarks
2220  ! 8. Structure :
2221  ! 9. Switches :
2222  !
2223  ! !/S Enable subroutine tracing.
2224  !
2225  ! 10. Source code :
2226  !
2227  !/ ------------------------------------------------------------------- /
2228 #ifdef W3_S
2229  USE w3servmd, ONLY: strace
2230 #endif
2231  !
2232  USE w3odatmd, ONLY: nbi, ndse, isbpi, xbpi, ybpi
2233  USE w3gdatmd, ONLY: nx, xgrd, ygrd, mapsta, mapfs, mapsf
2234 
2235 
2236  REAL, INTENT(IN) :: DISTMIN
2237  LOGICAL, INTENT(INOUT) :: FLOK
2238 
2239  INTEGER :: I, J, JMEMO, IS, IX, N, IX1(NBI)
2240  REAL :: DIST, DIST0
2241  !
2242  n = 0
2243  !
2244  !1. look for input boundary point index
2245  ! warning: if land points are included as boundary points to abide by the nest
2246  ! file, their status should be -2.
2247  !
2248  ix1 = 0
2249  isbpi = 1
2250  DO ix = 1, nx
2251  IF (abs(mapsta(1,ix)) .EQ. 2) THEN
2252  n = n + 1
2253  IF (n.GT.nbi) THEN
2254  WRITE(ndse,*) 'Error: boundary node index > NBI ... nest.ww3 file is not consistent with mod_def.ww3'
2255  stop
2256  ENDIF
2257  ix1(n) = ix
2258 #ifdef W3_T
2259  WRITE(ndse ,*)'ADDING BOUNDARY POINT:',n,ix
2260 #endif
2261  END IF
2262  END DO
2263  !
2264  !2. Matches the model grid points (where MAPSTA = 2) with the points in nest.ww3
2265  ! For this, we use the nearest point in the nest file.
2266  !
2267  DO i = 1, nbi
2268  dist0 = huge(1.)
2269  is = 1
2270  DO j = 1, n
2271  dist = (xbpi(i) - xgrd(1,ix1(j)))**2 + (ybpi(i) - ygrd(1,ix1(j)))**2
2272  IF (dist.LT.dist0) THEN
2273  is = mapfs(1,ix1(j))
2274  dist0 = dist
2275  jmemo = j
2276  END IF
2277  END DO
2278 
2279  dist0 = sqrt(dist0)
2280  IF (dist0.LE.distmin) THEN
2281  isbpi(i) = is
2282 #ifdef W3_T
2283  WRITE(ndse ,'(A,I6,A,I7,A,I6)') 'MATCHED BOUNDARY POINT:',i,'GRID POINT:', &
2284  mapsf(is,1),'INDEX IN nest.ww3:', jmemo
2285 #endif
2286  ELSE
2287  flok=.true.
2288  END IF
2289 
2290  END DO
2291 
2292  IF ( n .NE. nbi) THEN
2293  WRITE(ndse ,900) n, nbi
2294  DO j=1,n
2295  WRITE(6,*) 'THIS POINT HAS MAPSTA=2:',isbpi(j)
2296  END DO
2297  isbpi(n+1:nbi)=isbpi(1)
2298  END IF
2299 
2300 900 FORMAT (/' *** WAVEWATCH III ERROR IN W3IOBC : '/ &
2301  ' NUMBER OF MAPSTA=2 DIFFERS FROM NUMBER IN nest.ww3 '/ &
2302  ' CHECK nest.ww3 AND ww3_grid.inp ',2i8/)
2303  END SUBROUTINE w3nestug
2304 
2305 
2306  !/ ------------------------------------------------------------------- /
2307 
2318  SUBROUTINE set_iobp (MASK, STATUS)
2319  !/
2320  !/ +-----------------------------------+
2321  !/ | WAVEWATCH III NOAA/NCEP |
2322  !/ | |
2323  !/ | Aron Roland (BGS IT&E GmbH) |
2324  !/ | Mathieu Dutour-Sikiric (IRB) |
2325  !/ | |
2326  !/ | FORTRAN 90 |
2327  !/ | Last update : 01-June-2018 |
2328  !/ +-----------------------------------+
2329  !/
2330  !/ 01-June-2018 : Origination. ( version 6.04 )
2331  !/
2332  ! 1. Purpose : setup boundary pointer
2333  ! 2. Method :
2334  ! 3. Parameters :
2335  !
2336  ! Parameter list
2337  ! ----------------------------------------------------------------
2338  ! ----------------------------------------------------------------
2339  !
2340  ! 4. Subroutines used :
2341  !
2342  ! Name Type Module Description
2343  ! ----------------------------------------------------------------
2344  ! STRACE Subr. W3SERVMD Subroutine tracing.
2345  ! ----------------------------------------------------------------
2346  !
2347  ! 5. Called by :
2348  !
2349  ! Name Type Module Description
2350  ! ----------------------------------------------------------------
2351  ! ----------------------------------------------------------------
2352  !
2353  ! 6. Error messages :
2354  ! 7. Remarks
2355  ! 8. Structure :
2356  ! 9. Switches :
2357  !
2358  ! !/S Enable subroutine tracing.
2359  !
2360  ! 10. Source code :
2361  !
2362  !/ ------------------------------------------------------------------- /
2363 #ifdef W3_S
2364  USE w3servmd, ONLY: strace
2365 #endif
2366  !
2367  !/
2368  !
2369  USE constants
2370  !
2371  !
2372  USE w3gdatmd, ONLY: nx, ntri, trigp
2373  USE w3odatmd, ONLY: iaproc
2374 
2375 
2376  IMPLICIT NONE
2377 
2378  !/
2379  !/ ------------------------------------------------------------------- /
2380  !/ Parameter list
2381  !/
2382  INTEGER, INTENT(IN) :: MASK(NX)
2383  INTEGER*2, INTENT(OUT) :: STATUS(NX)
2384  !
2385  INTEGER :: COLLECTED(NX), NEXTVERT(NX), PREVVERT(NX)
2386  INTEGER :: ISFINISHED !, INEXT, IPREV
2387  INTEGER :: INEXT(3), IPREV(3)
2388  INTEGER :: ZNEXT, IP, I, IE, IPNEXT, IPPREV, COUNT
2389  integer nb0, nb1, nbM1
2390  status = -1
2391  inext=(/ 2, 3, 1 /) !IPREV=1+MOD(I+1,3)
2392  iprev=(/ 3, 1, 2 /) !INEXT=1+MOD(I,3)
2393  DO ie=1,ntri
2394  ! If one of the points of the triangle is masked out (land) then do as if triangle does not exist...
2395  ! IF ((MASK(TRIGP(1,IE)).GT.0).AND.(MASK(TRIGP(2,IE)).GT.0).AND.(MASK(TRIGP(3,IE)).GT.0)) THEN
2396  DO i=1,3
2397  ip=trigp(i,ie)
2398  CALL triang_indexes(i, ipnext, ipprev)
2399  !IPNEXT=TRIGP(INEXT(I),IE)
2400  !IPPREV=TRIGP(IPREV(I),IE)
2401  IF (status(ip).EQ.-1) THEN
2402  status(ip)=1
2403  prevvert(ip)=ipprev
2404  nextvert(ip)=ipnext
2405  END IF
2406  END DO
2407  ! ENDIF
2408  END DO
2409  status(:)=-1
2410  !
2411  count = 0
2412  DO
2413  count = count + 1
2414  collected(:)=0
2415  DO ie=1,ntri
2416  ! IF ((MASK(TRIGP(1,IE)).GT.0).AND.(MASK(TRIGP(2,IE)).GT.0).AND.(MASK(TRIGP(3,IE)).GT.0)) THEN
2417  DO i=1,3
2418  ip=trigp(i,ie)
2419  CALL triang_indexes(i, ipnext, ipprev)
2420  !IPNEXT=TRIGP(INEXT(I),IE)
2421  !IPPREV=TRIGP(IPREV(I),IE)
2422  IF (status(ip).EQ.-1) THEN
2423  znext=nextvert(ip)
2424  IF (znext.EQ.ipprev) THEN
2425  collected(ip)=1
2426  nextvert(ip)=ipnext
2427  IF (nextvert(ip).EQ.prevvert(ip)) THEN
2428  status(ip)=1
2429  END IF
2430  END IF
2431  END IF
2432  END DO
2433  ! END IF ! end of test on MASK
2434  END DO
2435  !
2436  ! Checks that all nodes have been treated ...
2437  !
2438  isfinished=1
2439  DO ip=1,nx
2440  IF (mask(ip).LE.0) THEN
2441  status(ip)=0
2442  ELSE
2443  IF ((collected(ip).EQ.0).AND.(status(ip).EQ.-1)) THEN
2444  status(ip)=0
2445  END IF
2446  IF (status(ip).eq.-1) THEN
2447  isfinished=0
2448  END IF
2449  ENDIF
2450  END DO
2451  IF (isfinished.EQ.1) THEN
2452  EXIT
2453  END IF
2454  END DO
2455 
2456  status = 1
2457  CALL get_boundary(nx, ntri, trigp, status, prevvert, nextvert)
2458 
2459  !#ifdef MPI_PARALL_GRID
2460  ! CALL exchange_p2di(STATUS)
2461  !#endif
2462  END SUBROUTINE set_iobp
2463  !/ ------------------------------------------------------------------- /
2464 
2479  SUBROUTINE get_boundary(MNP, MNE, TRIGP, IOBP, NEIGHBOR_PREV, &
2480  & NEIGHBOR_NEXT)
2481  !/
2482  !/ +-----------------------------------+
2483  !/ | WAVEWATCH III NOAA/NCEP |
2484  !/ | |
2485  !/ | Aron Roland (BGS IT&E GmbH) |
2486  !/ | Mathieu Dutour-Sikiric (IRB) |
2487  !/ | |
2488  !/ | FORTRAN 90 |
2489  !/ | Last update : 01-June-2018 |
2490  !/ +-----------------------------------+
2491  !/
2492  !/ 01-June-2018 : Origination. ( version 6.04 )
2493  !/
2494  ! 1. Purpose : find boundary points
2495  ! 2. Method :
2496  ! 3. Parameters :
2497  !
2498  ! Parameter list
2499  ! ----------------------------------------------------------------
2500  ! ----------------------------------------------------------------
2501  !
2502  ! 4. Subroutines used :
2503  !
2504  ! Name Type Module Description
2505  ! ----------------------------------------------------------------
2506  ! STRACE Subr. W3SERVMD Subroutine tracing.
2507  ! ----------------------------------------------------------------
2508  !
2509  ! 5. Called by :
2510  !
2511  ! Name Type Module Description
2512  ! ----------------------------------------------------------------
2513  ! ----------------------------------------------------------------
2514  !
2515  ! 6. Error messages :
2516  ! 7. Remarks
2517  ! 8. Structure :
2518  ! 9. Switches :
2519  !
2520  ! !/S Enable subroutine tracing.
2521  !
2522  ! 10. Source code :
2523  !
2524  !/ ------------------------------------------------------------------- /
2525 #ifdef W3_S
2526  USE w3servmd, ONLY: strace
2527 #endif
2528  !
2529  USE w3servmd, ONLY: extcde
2530  IMPLICIT NONE
2531  !/
2532  !/ ------------------------------------------------------------------- /
2533  !/ Parameter list
2534  !/
2535  !/ ------------------------------------------------------------------- /
2536  !/ Local PARAMETERs
2537  !/
2538 #ifdef W3_S
2539  INTEGER, SAVE :: IENT = 0
2540 #endif
2541 
2542  INTEGER, INTENT(IN) :: MNP, MNE, TRIGP(3,MNE)
2543  INTEGER*2, INTENT(INOUT) :: IOBP(MNP)
2544  INTEGER, INTENT(INOUT) :: NEIGHBOR_PREV(MNP)
2545  INTEGER, INTENT(INOUT) :: NEIGHBOR_NEXT(MNP)
2546 
2547  INTEGER, POINTER :: STATUS(:)
2548  INTEGER, POINTER :: COLLECTED(:)
2549  INTEGER, POINTER :: NEXTVERT(:)
2550  INTEGER, POINTER :: PREVVERT(:)
2551 
2552  INTEGER :: IE, I, IP, IP2, IP3
2553  INTEGER :: ISFINISHED, INEXT, IPREV, ISTAT
2554  INTEGER :: IPNEXT, IPPREV, ZNEXT, ZPREV
2555 #ifdef W3_S
2556  CALL strace (ient, 'GET_BOUNDARY')
2557 #endif
2558  ALLOCATE(status(mnp), stat=istat)
2559  check_alloc_status( istat )
2560  ALLOCATE(collected(mnp), stat=istat)
2561  check_alloc_status( istat )
2562  ALLOCATE(prevvert(mnp), stat=istat)
2563  check_alloc_status( istat )
2564  ALLOCATE(nextvert(mnp), stat=istat)
2565  check_alloc_status( istat )
2566  neighbor_next = 0
2567  neighbor_prev = 0
2568  ! Now computing the next items
2569  status = 0
2570  nextvert = 0
2571  prevvert = 0
2572 
2573  DO ie=1,mne
2574  DO i=1,3
2575  CALL triang_indexes(i, inext, iprev)
2576  ip=trigp(i,ie)
2577  ipnext=trigp(inext,ie)
2578  ipprev=trigp(iprev,ie)
2579  IF (status(ip).EQ.0) THEN
2580  status(ip)=1
2581  prevvert(ip)=ipprev
2582  nextvert(ip)=ipnext
2583  END IF
2584  END DO
2585  END DO
2586  status(:)=0
2587  DO
2588  collected(:)=0
2589  DO ie=1,mne
2590  DO i=1,3
2591  CALL triang_indexes(i, inext, iprev)
2592  ip=trigp(i,ie)
2593  ipnext=trigp(inext,ie)
2594  ipprev=trigp(iprev,ie)
2595  IF (status(ip).EQ.0) THEN
2596  znext=nextvert(ip)
2597  IF (znext.EQ.ipprev) THEN
2598  collected(ip)=1
2599  nextvert(ip)=ipnext
2600  IF (nextvert(ip).EQ.prevvert(ip)) THEN
2601  status(ip)=1
2602  END IF
2603  END IF
2604  END IF
2605  END DO
2606  END DO
2607 
2608  isfinished=1
2609  DO ip=1,mnp
2610  IF ((collected(ip).EQ.0).AND.(status(ip).EQ.0)) THEN
2611  status(ip)=-1
2612  neighbor_next(ip)=nextvert(ip)
2613  END IF
2614  IF (status(ip).EQ.0) THEN
2615  isfinished=0
2616  END IF
2617  END DO
2618  IF (isfinished.EQ.1) THEN
2619  EXIT
2620  END IF
2621  END DO
2622 
2623  ! Now computing the prev items
2624  status = 0
2625  nextvert = 0
2626  prevvert = 0
2627  DO ie=1,mne
2628  DO i=1,3
2629  CALL triang_indexes(i, inext, iprev)
2630  ip=trigp(i,ie)
2631  ipnext=trigp(inext,ie)
2632  ipprev=trigp(iprev,ie)
2633  IF (status(ip).EQ.0) THEN
2634  status(ip)=1
2635  prevvert(ip)=ipprev
2636  nextvert(ip)=ipnext
2637  END IF
2638  END DO
2639  END DO
2640  status(:)=0
2641  DO
2642  collected(:)=0
2643  DO ie=1,mne
2644  DO i=1,3
2645  CALL triang_indexes(i, inext, iprev)
2646  ip=trigp(i,ie)
2647  ipnext=trigp(inext,ie)
2648  ipprev=trigp(iprev,ie)
2649  IF (status(ip).EQ.0) THEN
2650  zprev=prevvert(ip)
2651  IF (zprev.EQ.ipnext) THEN
2652  collected(ip)=1
2653  prevvert(ip)=ipprev
2654  IF (prevvert(ip).EQ.nextvert(ip)) THEN
2655  status(ip)=1
2656  END IF
2657  END IF
2658  END IF
2659  END DO
2660  END DO
2661 
2662  isfinished=1
2663  DO ip=1,mnp
2664  IF ((collected(ip).EQ.0).AND.(status(ip).EQ.0)) THEN
2665  status(ip)=-1
2666  neighbor_prev(ip)=prevvert(ip) ! new code
2667  END IF
2668  IF (status(ip).EQ.0) THEN
2669  isfinished=0
2670  END IF
2671  END DO
2672  IF (isfinished.EQ.1) THEN
2673  EXIT
2674  END IF
2675  END DO
2676  ! Now making checks
2677  DO ip=1,mnp
2678  ip2=neighbor_next(ip)
2679  IF (ip2.GT.0) THEN
2680  ip3=neighbor_prev(ip2)
2681  IF (abs(ip3 - ip).GT.0) THEN
2682  WRITE(*,*) 'IP=', ip, ' IP2=', ip2, ' IP3=', ip3
2683  WRITE(*,*) 'We have a dramatic inconsistency'
2684  stop
2685  END IF
2686  END IF
2687  END DO
2688  ! Now assigning the boundary IOBP array
2689  DO ip=1,mnp
2690  IF (status(ip).EQ.-1 .AND. iobp(ip) .EQ. 1) THEN
2691  iobp(ip)=0
2692  END IF
2693  END DO
2694 
2695  DEALLOCATE(status, stat=istat)
2696  check_dealloc_status( istat )
2697  DEALLOCATE(collected, stat=istat)
2698  check_dealloc_status( istat )
2699  DEALLOCATE(nextvert, stat=istat)
2700  check_dealloc_status( istat )
2701  DEALLOCATE(prevvert, stat=istat)
2702  check_dealloc_status( istat )
2703 
2704  END SUBROUTINE get_boundary
2705 
2706  !/ ------------------------------------------------------------------- /
2707 
2719  SUBROUTINE triang_indexes(I, INEXT, IPREV)
2720  !/
2721  !/ +-----------------------------------+
2722  !/ | WAVEWATCH III NOAA/NCEP |
2723  !/ | |
2724  !/ | Aron Roland (BGS IT&E GmbH) |
2725  !/ | Mathieu Dutour-Sikiric (IRB) |
2726  !/ | |
2727  !/ | FORTRAN 90 |
2728  !/ | Last update : 01-June-2018 |
2729  !/ +-----------------------------------+
2730  !/
2731  !/ 01-June-2018 : Origination. ( version 6.04 )
2732  !/
2733  ! 1. Purpose : set indices of the triangle
2734  ! 2. Method :
2735  ! 3. Parameters :
2736  !
2737  ! Parameter list
2738  ! ----------------------------------------------------------------
2739  ! ----------------------------------------------------------------
2740  !
2741  ! 4. Subroutines used :
2742  !
2743  ! Name Type Module Description
2744  ! ----------------------------------------------------------------
2745  ! STRACE Subr. W3SERVMD Subroutine tracing.
2746  ! ----------------------------------------------------------------
2747  !
2748  ! 5. Called by :
2749  !
2750  ! Name Type Module Description
2751  ! ----------------------------------------------------------------
2752  ! ----------------------------------------------------------------
2753  !
2754  ! 6. Error messages :
2755  ! 7. Remarks
2756  ! 8. Structure :
2757  ! 9. Switches :
2758  !
2759  ! !/S Enable subroutine tracing.
2760  !
2761  ! 10. Source code :
2762  !
2763  !/ ------------------------------------------------------------------- /
2764 #ifdef W3_S
2765  USE w3servmd, ONLY: strace
2766 #endif
2767  IMPLICIT NONE
2768  !
2769  !/ ------------------------------------------------------------------- /
2770  !/ Parameter list
2771  !/
2772  !/ ------------------------------------------------------------------- /
2773  !/ Local PARAMETERs
2774  !/
2775 #ifdef W3_S
2776  INTEGER, SAVE :: IENT = 0
2777 #endif
2778  !/
2779  !/ ------------------------------------------------------------------- /
2780  !/
2781  INTEGER, INTENT(IN) :: I
2782  INTEGER, INTENT(OUT) :: INEXT, IPREV
2783 #ifdef W3_S
2784  CALL strace (ient, 'TRIANG_INDEXES')
2785 #endif
2786  IF (i.EQ.1) THEN
2787  inext=3
2788  ELSE
2789  inext=i-1
2790  END IF
2791  IF (i.EQ.3) THEN
2792  iprev=1
2793  ELSE
2794  iprev=i+1
2795  END IF
2796  END SUBROUTINE triang_indexes
2797 
2798  !/ ------------------------------------------------------------------- /
2799 
2810  SUBROUTINE set_ug_iobp()
2811  !/
2812  !/ +-----------------------------------+
2813  !/ | WAVEWATCH III NOAA/NCEP |
2814  !/ | Fabrice Ardhuin |
2815  !/ | Aron Roland |
2816  !/ | FORTRAN 90 |
2817  !/ | Last update : 17-Apr-2016 |
2818  !/ +-----------------------------------+
2819  !/
2820  !/ 23-Aug-2011 : Origination. ( version 4.04 )
2821  !/ 17-Apr-2016 : Uses optimized boundary detection ( version 5.10 )
2822  !/
2823  ! 1. Purpose :
2824  !
2825  ! Redefines the values of the boundary points and angle pointers
2826  ! based on the MAPSTA array
2827  !
2828  ! 2. Method :
2829  !
2830  ! Adapted boundary detection from A. Roland and M. Dutour (WWM code)
2831  !
2832  ! 3. Parameters :
2833  !
2834  ! Parameter list
2835  ! ----------------------------------------------------------------
2836  ! ----------------------------------------------------------------
2837  !
2838  ! Local variables.
2839  ! ----------------------------------------------------------------
2840  ! ----------------------------------------------------------------
2841  !
2842  ! 4. Subroutines used :
2843  !
2844 
2845  ! 5. Called by :
2846  !
2847  ! Name Type Module Description
2848  ! ----------------------------------------------------------------
2849  ! WW3_GRID Prog. WW3_GRID Grid preprocessor
2850  ! W3ULEV Subr. W3UPDTMD Water level update
2851  ! ----------------------------------------------------------------
2852  !
2853  ! 6. Error messages :
2854  !
2855  ! None.
2856  !
2857  ! 7. Remarks :
2858  !
2859  ! 8. Structure :
2860  !
2861  !
2862  ! 9. Switches :
2863  !
2864  ! !/S Enable subroutine tracing.
2865  !
2866  !
2867  ! 10. Source code :
2868  !/ ------------------------------------------------------------------- /
2869  !/
2870  !
2871  USE constants
2872  !
2873  !
2874  USE w3gdatmd, ONLY: nx, ny, nsea, mapfs, &
2875  nk, nth, dth, xfr, mapsta, countri, &
2876  ecos, esin, ien, ntri, trigp, &
2877  iobp,iobpd, iobpa, &
2878 #ifdef w3_ref1
2879  refpars, reflc, refld, &
2880 #endif
2881  angle0, angle
2882 
2883  USE w3odatmd, ONLY: tbpi0, tbpin, flbpi
2884  USE w3adatmd, ONLY: cg, cx, cy, atrnx, atrny, itime, cflxymax
2885  USE w3idatmd, ONLY: flcur
2886  USE w3odatmd, only : iaproc
2887 #ifdef W3_S
2888  USE w3servmd, ONLY: strace
2889 #endif
2890 
2891  IMPLICIT NONE
2892  !/ ------------------------------------------------------------------- /
2893  !/ Parameter list
2894  !/
2895  !/
2896  !/ ------------------------------------------------------------------- /
2897  !/ Local parameters
2898  !/
2899  INTEGER :: ITH, IX, I, J, IP, IE, NDIRSUM
2900  REAL (KIND = 8) :: cossum, sinsum
2901  REAL (KIND = 8) :: dirmin, dirmax, shift, tempo, dircoast
2902  REAL (KIND = 8) :: x1, x2, y1, y2, dxp1, dxp2, dxp3
2903  REAL (KIND = 8) :: dyp1, dyp2, dyp3, edet1, edet2, evx, evy
2904  REAL(KIND=8), parameter :: thr = tiny(1.)
2905  INTEGER :: I1, I2, I3
2906  INTEGER :: ITMP(NX), NEXTVERT(NX), PREVVERT(NX)
2907  CHARACTER(60) :: FNAME
2908 #ifdef W3_S
2909  INTEGER, SAVE :: IENT = 0
2910 #endif
2911  !/ ------------------------------------------------------------------- /
2912  !
2913  ! 1. Preparations --------------------------------------------------- *
2914  ! 1.a Set constants
2915  !
2916 #ifdef W3_S
2917  CALL strace (ient, 'SETUGIOBP')
2918 #endif
2919  !
2920  !--- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2921  ! 2. Searches for boundary points
2922  !
2923  itmp = mapsta(1,:)
2924  CALL set_iobp(itmp, iobp)
2925  fname = 'meshbnd.msh'
2926  CALL readmsh_iobp(23456,fname)
2927  !
2928  !--- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2929  ! 3. Defines directions pointing into land or sea
2930  !
2931  iobpd(:,:) = 0
2932  iobpa(:) = 0
2933  !
2934  DO ip=1,nx
2935  IF (mapsta(1,ip).EQ.2) THEN
2936  iobpa(ip) = 1
2937  iobp(ip) = 2
2938  ENDIF
2939  END DO
2940 
2941  DO ie = 1,ntri
2942  i1 = trigp(1,ie)
2943  i2 = trigp(2,ie)
2944  i3 = trigp(3,ie)
2945  dxp1 = ien(ie,6)
2946  dyp1 = - ien(ie,5)
2947  dxp2 = ien(ie,2)
2948  dyp2 = - ien(ie,1)
2949  dxp3 = ien(ie,4)
2950  dyp3 = - ien(ie,3)
2951  DO ith=1,nth
2952  evx=ecos(ith)
2953  evy=esin(ith)
2954  DO i=1,3
2955  IF (i.eq.1) THEN
2956  x1= dxp1
2957  y1= dyp1
2958  x2= - dxp3
2959  y2= - dyp3
2960  ip= i1
2961  END IF
2962  IF (i.eq.2) THEN
2963  x1 = dxp2
2964  y1 = dyp2
2965  x2 = - dxp1
2966  y2 = - dyp1
2967  ip = i2
2968  END IF
2969  IF (i.eq.3) THEN
2970  x1 = dxp3
2971  y1 = dyp3
2972  x2 = - dxp2
2973  y2 = - dyp2
2974  ip = i3
2975  END IF
2976  IF (iobp(ip) .eq. 0) THEN ! physical boundary
2977  edet1 = thr-x1*evy+y1*evx
2978  edet2 = thr+x2*evy-y2*evx
2979  IF ((edet1.gt.0.).and.(edet2.gt.0.)) THEN
2980  ! this is the case of waves going towards the boundary ...
2981  iobpd(ith,ip)=1
2982  ENDIF
2983  ELSE ! water ...
2984  iobpd(ith,ip)=1
2985  END IF
2986  END DO
2987  END DO
2988  END DO
2989  DO ip = 1, nx
2990  IF ( iobpa(ip) .eq. 1 .OR. iobp(ip) .eq. 3 .OR. iobp(ip) .eq. 4) iobpd(:,ip) = 1
2991  END DO
2992  !2do: recode for mpi
2993  ! IF (LBCWA .OR. LBCSP) THEN
2994  ! IF (.NOT. ANY(IOBP .EQ. 2)) THEN
2995  ! CALL WWM_ABORT('YOU IMPOSED BOUNDARY CONDITIONS BUT IN THE BOUNDARY FILE ARE NO NODES WITH FLAG = 2')
2996  ! ENDIF
2997  ! ENDIF
2998  !#ifdef MPI_PARALL_GRID
2999  ! CALL exchange_p2di(IOBWB)
3000  ! DO ID = 1, MDC
3001  ! iwild = IOBPD(ID,:)
3002  ! CALL exchange_p2di(iwild)
3003  ! IOBPD(ID,:) = iwild
3004  ! ENDDO
3005  !#endif
3006  !--- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3007  ! 3. Updates the reflection direction and sharp / flat shoreline angle
3008 
3009 #ifdef W3_REF1
3010  !
3011  ! Finds the shoreline direction from IOBPD
3012  !
3013  reflc(1,:)= 0.
3014  refld(:,:)= 1
3015  DO ip=1,nx
3016  IF (iobp(ip).EQ.0.AND.mapsta(1,ip).EQ.1) THEN
3017  cossum=0.
3018  sinsum=0.
3019  ndirsum=0.
3020  DO ith=1,nth
3021  cossum=cossum+iobpd(ith,ip)*ecos(ith)
3022  sinsum=sinsum+iobpd(ith,ip)*esin(ith)
3023  ndirsum=ndirsum+iobpd(ith,ip)
3024  END DO
3025  dircoast=atan2(sinsum, cossum)
3026  refld(1,mapfs(1,ip)) = 1+mod(nth+nint(dircoast/dth),nth)
3027  refld(2,mapfs(1,ip)) = 4-max(2,nint(4.*real(ndirsum)/real(nth)))
3028  reflc(1,mapfs(1,ip))= refpars(1)
3029  END IF
3030  END DO
3031 #endif
3032  !
3033  ! Recomputes the angles used in the gradients estimation
3034  !
3035  !
3036  RETURN
3037  END SUBROUTINE set_ug_iobp
3038  !/ ------------------------------------------------------------------- /
3039 
3058  SUBROUTINE fix_periodcity(I1,I2,I3,XGRD,YGRD,PT)
3059  !/
3060  !/ +-----------------------------------+
3061  !/ | WAVEWATCH III NOAA/NCEP |
3062  !/ | Steven Brus |
3063  !/ | Ali Abdolali |
3064  !/ | FORTRAN 90 |
3065  !/ | Last update : 21-May-2020 |
3066  !/ +-----------------------------------+
3067  !/
3068  !/ 21-May-2020 : Origination. ( version 6.07 )
3069  !/
3070  !/
3071  ! 1. Purpose :
3072  !
3073  ! Adjust element longitude coordinates for elements straddling the
3074  ! dateline with distance of ~360 degrees
3075  !
3076  ! 2. Method :
3077  !
3078  ! Detect if element has nodes on both sides of dateline and adjust
3079  ! coordinates so that all nodes have the same sign
3080  !
3081  ! 3. Parameters :
3082  !
3083  ! Parameter list
3084  ! ----------------------------------------------------------------
3085  IMPLICIT NONE
3086  INTEGER, INTENT(IN) :: I1, I2, I3
3087  DOUBLE PRECISION, INTENT(IN) :: XGRD(:,:), YGRD(:,:)
3088  real*8, INTENT(OUT) :: pt(3,2)
3089  ! ----------------------------------------------------------------
3090  !
3091  ! Local variables.
3092  ! ----------------------------------------------------------------
3093  INTEGER :: I
3094  INTEGER :: R1GT180, R2GT180, R3GT180
3095  ! ----------------------------------------------------------------
3096  !
3097  ! 4. Subroutines used :
3098  !
3099 
3100  ! 5. Called by :
3101  !
3102  ! Name Type Module Description
3103  ! ----------------------------------------------------------------
3104  ! SPATIAL_GRID Subr. W3TRIAM Triangle area calculation
3105  ! NVECTRI Subr. W3TRIAM Edge length, angle, normal calcuation
3106  ! IS_IN_UNGRID Subr. W3TRIAM Point in element calculation
3107  ! ----------------------------------------------------------------
3108  !
3109  ! 6. Error messages :
3110  !
3111  ! None.
3112  !
3113  ! 7. Remarks :
3114  !
3115  ! 8. Structure :
3116  !
3117  ! 9. Switches :
3118  !
3119  ! 10. Source code :
3120  !/ ------------------------------------------------------------------- /
3121 
3122  pt(1,1) = xgrd(1,i1)
3123  pt(1,2) = ygrd(1,i1)
3124  pt(2,1) = xgrd(1,i2)
3125  pt(2,2) = ygrd(1,i2)
3126  pt(3,1) = xgrd(1,i3)
3127  pt(3,2) = ygrd(1,i3)
3128 
3129 
3130  r1gt180 = merge(1, 0, abs(pt(3,1)-pt(2,1)).GT.180)
3131  r2gt180 = merge(1, 0, abs(pt(1,1)-pt(3,1)).GT.180)
3132  r3gt180 = merge(1, 0, abs(pt(2,1)-pt(1,1)).GT.180)
3133  ! if R1GT180+R2GT180+R3GT180 .eq. 0 the element does not cross the dateline
3134  ! if R1GT180+R2GT180+R3GT180 .eq. 1 the element contains the pole
3135  ! if R1GT180+R2GT180+R3GT180 .eq. 2 the element crosses the dateline
3136 
3137 
3138  IF ( r1gt180 + r2gt180 == 2 ) THEN
3139  pt(3,1)=pt(3,1)-sign(360.0d0,(pt(3,1)-pt(2,1)))
3140  ELSE IF ( r2gt180 + r3gt180 == 2 ) THEN
3141  pt(1,1)=pt(1,1)-sign(360.0d0,(pt(1,1)-pt(2,1)))
3142  ELSE IF ( r1gt180 + r3gt180 == 2 ) THEN
3143  pt(2,1)=pt(2,1)-sign(360.0d0,(pt(2,1)-pt(3,1)))
3144  ENDIF
3145 
3146  RETURN
3147  END SUBROUTINE fix_periodcity
3148 END MODULE w3triamd
w3gdatmd::nk
integer, pointer nk
Definition: w3gdatmd.F90:1230
w3gdatmd::trigp
integer, dimension(:,:), pointer trigp
Definition: w3gdatmd.F90:1111
w3gdatmd::nseal
integer, pointer nseal
Definition: w3gdatmd.F90:1097
w3odatmd::tbpi0
integer, dimension(:), pointer tbpi0
Definition: w3odatmd.F90:464
w3triamd::triang_indexes
subroutine triang_indexes(I, INEXT, IPREV)
Set indices of the triangle.
Definition: w3triamd.F90:2720
w3servmd::nextln
subroutine nextln(CHCKC, NDSI, NDSE)
Definition: w3servmd.F90:222
w3triamd::ug_gradients
subroutine ug_gradients(PARAM, DIFFX, DIFFY)
Calculate gradients at a point via its connection.
Definition: w3triamd.F90:2039
w3gdatmd::iaa
integer, dimension(:), pointer iaa
Definition: w3gdatmd.F90:1124
yowelementpool::ielg
integer, dimension(:), allocatable, target, public ielg
global element array.
Definition: yowelementpool.F90:65
yowexchangemodule::pdlib_exchange1dreal
subroutine, public pdlib_exchange1dreal(U)
exchange values in U.
Definition: yowexchangeModule.F90:251
w3gdatmd::dth
real, pointer dth
Definition: w3gdatmd.F90:1232
w3adatmd::nsealm
integer, pointer nsealm
Definition: w3adatmd.F90:686
w3triamd
Reads triangle and unstructured grid information.
Definition: w3triamd.F90:21
w3triamd::readmsh
subroutine readmsh(NDS, FNAME)
Reads triangle and unstructured grid information from GMSH files.
Definition: w3triamd.F90:134
w3gdatmd::ygrd
double precision, dimension(:,:), pointer ygrd
Definition: w3gdatmd.F90:1205
yowelementpool
Definition: yowelementpool.F90:38
w3adatmd
Define data structures to set up wave model auxiliary data for several models simultaneously.
Definition: w3adatmd.F90:26
w3gdatmd::clatis
real, dimension(:), pointer clatis
Definition: w3gdatmd.F90:1197
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::zb
real, dimension(:), pointer zb
Definition: w3gdatmd.F90:1195
constants::dera
real, parameter dera
DERA Conversion factor from degrees to radians.
Definition: constants.F90:77
w3gdatmd::ntri
integer, pointer ntri
Definition: w3gdatmd.F90:1109
w3triamd::nvectri
subroutine nvectri
Calculate cell tools: inward normal, angles and length of edges.
Definition: w3triamd.F90:1004
w3adatmd::atrnx
real, dimension(:,:), pointer atrnx
Definition: w3adatmd.F90:578
w3adatmd::cflxymax
real, dimension(:), pointer cflxymax
Definition: w3adatmd.F90:620
w3gdatmd::maxx
real, pointer maxx
Definition: w3gdatmd.F90:1133
w3adatmd::cg
real, dimension(:,:), pointer cg
Definition: w3adatmd.F90:575
w3gdatmd::ie_cell
integer, dimension(:), pointer ie_cell
Definition: w3gdatmd.F90:1124
w3adatmd::atrny
real, dimension(:,:), pointer atrny
Definition: w3adatmd.F90:578
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
w3gdatmd::ecos
real, dimension(:), pointer ecos
Definition: w3gdatmd.F90:1234
w3triamd::w3nestug
subroutine w3nestug(DISTMIN, FLOK)
UGTYPE nesting initialization.
Definition: w3triamd.F90:2184
w3gdatmd::grids
type(grid), dimension(:), allocatable, target grids
Definition: w3gdatmd.F90:1088
w3odatmd::ybpi
real, dimension(:), pointer ybpi
Definition: w3odatmd.F90:541
w3triamd::is_in_ungrid2
subroutine is_in_ungrid2(IMOD, XTIN, YTIN, FORCE, ITOUT, IS, JS, RW)
Determine whether a point is inside or outside an unstructured grid, and returns index of triangle an...
Definition: w3triamd.F90:1807
w3triamd::coordmax
subroutine coordmax
Calculate first point and last point coordinates, and minimum and maximum edge length.
Definition: w3triamd.F90:1249
w3gdatmd::ny
integer, pointer ny
Definition: w3gdatmd.F90:1097
w3odatmd::tbpin
integer, dimension(:), pointer tbpin
Definition: w3odatmd.F90:464
yownodepool::npa
integer, public npa
number of ghost + resident nodes this partition holds
Definition: yownodepool.F90:99
w3odatmd::nbi
integer, pointer nbi
Definition: w3odatmd.F90:530
w3triamd::readmshobc
subroutine readmshobc(NDS, FNAME, TMPSTA, UGOBCOK)
Reads open boundary information for UNST grids following GMESH type format.
Definition: w3triamd.F90:670
w3gdatmd::iobpa
integer *1, dimension(:), pointer iobpa
Definition: w3gdatmd.F90:1130
w3odatmd::flbpi
logical, pointer flbpi
Definition: w3odatmd.F90:546
w3idatmd::flcur
logical, pointer flcur
Definition: w3idatmd.F90:261
w3gdatmd::countot
integer, pointer countot
Definition: w3gdatmd.F90:1109
w3triamd::get_boundary_status
subroutine get_boundary_status(STATUS)
Boundary status (code duplication).
Definition: w3triamd.F90:511
yowelementpool::ne
integer, public ne
number of local elements
Definition: yowelementpool.F90:48
yownodepool::np_global
integer, public np_global
number of nodes, global
Definition: yownodepool.F90:89
w3odatmd::ndse
integer, pointer ndse
Definition: w3odatmd.F90:456
w3gdatmd::len
real(8), dimension(:,:), pointer len
Definition: w3gdatmd.F90:1122
w3gdatmd::mapfs
integer, dimension(:,:), pointer mapfs
Definition: w3gdatmd.F90:1163
w3gdatmd::esin
real, dimension(:), pointer esin
Definition: w3gdatmd.F90:1234
w3triamd::outside_boundary
integer, dimension(:), allocatable, save outside_boundary
Definition: w3triamd.F90:115
yownodepool
Has data that belong to nodes.
Definition: yownodepool.F90:39
constants::lpdlib
logical lpdlib
LPDLIB Logical for using the PDLIB library.
Definition: constants.F90:101
w3triamd::fix_periodcity
subroutine fix_periodcity(I1, I2, I3, XGRD, YGRD, PT)
Adjust element longitude coordinates for elements straddling the dateline with distance of ~360 degre...
Definition: w3triamd.F90:3059
w3gdatmd::x0
real, pointer x0
Definition: w3gdatmd.F90:1183
w3gdatmd::nsea
integer, pointer nsea
Definition: w3gdatmd.F90:1097
w3servmd
Definition: w3servmd.F90:3
w3triamd::spatial_grid
subroutine spatial_grid
Calculates triangle areas and reorders the triangles to have them oriented counterclockwise.
Definition: w3triamd.F90:891
w3gdatmd::tria
real(8), dimension(:), pointer tria
Definition: w3gdatmd.F90:1131
w3gdatmd::nth
integer, pointer nth
Definition: w3gdatmd.F90:1230
w3odatmd
Definition: w3odatmd.F90:3
w3gdatmd::w3dimug
subroutine w3dimug(IMOD, MTRI, MX, COUNTOTA, NNZ, NDSE, NDST)
Definition: w3gdatmd.F90:3106
w3gdatmd::ien
real(8), dimension(:,:), pointer ien
Definition: w3gdatmd.F90:1122
w3adatmd::cy
real, dimension(:), pointer cy
Definition: w3adatmd.F90:584
w3gdatmd::mapsf
integer, dimension(:,:), pointer mapsf
Definition: w3gdatmd.F90:1163
w3triamd::area_si
subroutine area_si(IMOD)
Define optimized connection arrays (points and triangles) for spatial propagation schemes.
Definition: w3triamd.F90:1337
w3gdatmd::fsnimp
logical, pointer fsnimp
Definition: w3gdatmd.F90:1405
w3odatmd::xbpi
real, dimension(:), pointer xbpi
Definition: w3odatmd.F90:541
yowexchangemodule
Has only the ghost nodes assign to a neighbor domain.
Definition: yowexchangeModule.F90:39
file
file(STRINGS ${CMAKE_BINARY_DIR}/switch switch_strings) separate_arguments(switches UNIX_COMMAND $
Definition: CMakeLists.txt:3
constants::radius
real, parameter radius
RADIUS Radius of the earth (m).
Definition: constants.F90:79
w3gdatmd::countri
integer, pointer countri
Definition: w3gdatmd.F90:1109
w3gdatmd::iobpd
integer *1, dimension(:,:), pointer iobpd
Definition: w3gdatmd.F90:1130
w3gdatmd::nnz
integer, pointer nnz
Definition: w3gdatmd.F90:1109
w3gdatmd::jaa
integer, dimension(:), pointer jaa
Definition: w3gdatmd.F90:1124
w3gdatmd::maxy
real, pointer maxy
Definition: w3gdatmd.F90:1133
yowelementpool::ine
integer, dimension(:,:), allocatable, target, public ine
number of elements of the augmented domain
Definition: yowelementpool.F90:56
w3servmd::strace
subroutine strace(IENT, SNAME)
Definition: w3servmd.F90:148
w3idatmd
Define data structures to set up wave model input data for several models simultaneously.
Definition: w3idatmd.F90:16
w3odatmd::ndso
integer, pointer ndso
Definition: w3odatmd.F90:456
w3gdatmd::xfr
real, pointer xfr
Definition: w3gdatmd.F90:1232
w3gdatmd::y0
real, pointer y0
Definition: w3gdatmd.F90:1183
yowelementpool::ne_global
integer, public ne_global
number of elements, global
Definition: yowelementpool.F90:45
yownodepool::pdlib_tria
real(rkind), dimension(:), allocatable, target, public pdlib_tria
Definition: yownodepool.F90:80
w3gdatmd::dxymax
real, pointer dxymax
Definition: w3gdatmd.F90:1133
w3gdatmd::ccon
integer, dimension(:), pointer ccon
Definition: w3gdatmd.F90:1124
w3gdatmd::iobp
integer *2, dimension(:), pointer iobp
Definition: w3gdatmd.F90:1129
w3gdatmd::si
real(8), dimension(:), pointer si
Definition: w3gdatmd.F90:1122
w3gdatmd::sx
real, pointer sx
Definition: w3gdatmd.F90:1183
w3odatmd::ndst
integer, pointer ndst
Definition: w3odatmd.F90:456
constants
Define some much-used constants for global use (all defined as PARAMETER).
Definition: constants.F90:20
w3gdatmd
Definition: w3gdatmd.F90:16
w3triamd::ug_getopenboundary
subroutine ug_getopenboundary(TMPSTA, ZBIN, ZLIM)
Defines open boundary points based on depth.
Definition: w3triamd.F90:797
w3triamd::get_boundary
subroutine get_boundary(MNP, MNE, TRIGP, IOBP, NEIGHBOR_PREV, NEIGHBOR_NEXT)
Find boundary points.
Definition: w3triamd.F90:2481
w3gdatmd::angle
real, dimension(:,:), pointer angle
Definition: w3gdatmd.F90:1123
w3servmd::extcde
subroutine extcde(IEXIT, UNIT, MSG, FILE, LINE, COMM)
Definition: w3servmd.F90:736
yownodepool::pdlib_ien
real(rkind), dimension(:,:), allocatable, target, public pdlib_ien
Definition: yownodepool.F90:80
w3servmd::itrace
subroutine itrace(NDS, NMAX)
Definition: w3servmd.F90:91
w3gdatmd::countcon
integer, dimension(:), pointer countcon
Definition: w3gdatmd.F90:1124
w3triamd::readmsh_iobp
subroutine readmsh_iobp(NDS, FNAME)
Reads triangle and unstructured grid information from GMSH files.
Definition: w3triamd.F90:389
w3adatmd::itime
integer, pointer itime
Definition: w3adatmd.F90:686
w3gdatmd::index_cell
integer, dimension(:), pointer index_cell
Definition: w3gdatmd.F90:1124
w3odatmd::isbpi
integer, dimension(:), pointer isbpi
Definition: w3odatmd.F90:535
w3adatmd::cx
real, dimension(:), pointer cx
Definition: w3adatmd.F90:584
w3gdatmd::nx
integer, pointer nx
Definition: w3gdatmd.F90:1097
w3triamd::set_ug_iobp
subroutine set_ug_iobp()
Redefines the values of the boundary points and angle pointers based on the MAPSTA array.
Definition: w3triamd.F90:2811
w3gdatmd::pos_cell
integer, dimension(:), pointer pos_cell
Definition: w3gdatmd.F90:1124
w3triamd::count
subroutine count(TRIGPTEMP)
Calculate global and maximum number of connection for array allocations.
Definition: w3triamd.F90:1135
w3triamd::set_iobp
subroutine set_iobp(MASK, STATUS)
Setup boundary pointer.
Definition: w3triamd.F90:2319
w3gdatmd::mapsta
integer, dimension(:,:), pointer mapsta
Definition: w3gdatmd.F90:1163
w3triamd::n_outside_boundary
integer, save n_outside_boundary
Definition: w3triamd.F90:114
w3gdatmd::posi
integer, dimension(:,:), pointer posi
Definition: w3gdatmd.F90:1124
w3gdatmd::flagll
logical, pointer flagll
Definition: w3gdatmd.F90:1219