WAVEWATCH III  beta 0.0.1
w3partmd.F90
Go to the documentation of this file.
1 
7 #include "w3macros.h"
8 !/ ------------------------------------------------------------------- /
18 MODULE w3partmd
19  !/
20  !/ +-----------------------------------+
21  !/ | WAVEWATCH III USACE/NOAA |
22  !/ | Barbara Tracy |
23  !/ | H. L. Tolman |
24  !/ | FORTRAN 90 |
25  !/ | Last update : 23-Jul-2018 |
26  !/ +-----------------------------------+
27  !/
28  !/ 01-Nov-2006 : Origination. ( version 3.10 )
29  !/ 02-Nov-2006 : Adding tail to integration. ( version 3.10 )
30  !/ 24-Mar-2007 : Bug fix IMI, adding overall field ( version 3.11 )
31  !/ and sorting.
32  !/ 15-Apr-2008 : Clean up for distribution. ( version 3.14 )
33  !/ 02-Dec-2010 : Adding a mapping PMAP between ( version 3.14 )
34  !/ original and combined partitions
35  !/ ( M. Szyszka )
36  !/ 23-Jul-2018 : Added alternative partitioning ( version 6.05 )
37  !/ methods (C. Bunney, UKMO)
38  ! 1. Purpose :
39  !
40  ! Spectral partitioning according to the watershed method.
41  !
42  ! 2. Variables and types :
43  !
44  ! Name Type Scope Description
45  ! ----------------------------------------------------------------
46  ! MK, MTH Int. Private Dimensions of stored neighour array.
47  ! NEIGH I.A. Private Nearest Neighbor array.
48  ! ----------------------------------------------------------------
49  ! Note: IHMAX, HSPMIN, WSMULT, WSCUT and FLCOMB used from W3ODATMD.
50  !
51  ! 3. Subroutines and functions :
52  !
53  ! Name Type Scope Description
54  ! ----------------------------------------------------------------
55  ! W3PART Subr. Public Interface to watershed routines.
56  ! PTSORT Subr. Public Sort discretized image.
57  ! PTNGHB Subr. Public Defeine nearest neighbours.
58  ! PT_FLD Subr. Public Incremental flooding algorithm.
59  ! FIFO_ADD, FIFO_EMPTY, FIFO_FIRST
60  ! Subr. PT_FLD Queue management.
61  ! PTMEAN Subr. Public Compute mean parameters.
62  ! ----------------------------------------------------------------
63  !
64  ! 4. Subroutines and functions used :
65  !
66  ! Name Type Module Description
67  ! ----------------------------------------------------------------
68  ! STRACE Subr. W3SERVMD Subroutine traceing.
69  ! WAVNU1 Subr. W3DISPMD Wavenumber computation.
70  ! ----------------------------------------------------------------
71  !
72  ! 5. Remarks :
73  !
74  ! 6. Switches :
75  !
76  ! !/S Enable subroutine tracing.
77  ! !/T Enable test output
78  !
79  ! 7. Source code :
80  !
81  !/ ------------------------------------------------------------------- /
82  !
83  USE w3odatmd, ONLY: ihmax, hspmin, wsmult, dimp, ptmeth, ptfcut
84  !
85  PUBLIC
86  !
88  INTEGER, PRIVATE :: MK = -1
90  INTEGER, PRIVATE :: MTH = -1
92  INTEGER, ALLOCATABLE, PRIVATE :: NEIGH(:,:)
93  !/
94 CONTAINS
95  !/ ------------------------------------------------------------------- /
138  SUBROUTINE w3part ( SPEC, UABS, UDIR, DEPTH, WN, NP, XP, DIMXP )
139  !/
140  !/ +-----------------------------------+
141  !/ | WAVEWATCH III USACE/NOAA |
142  !/ | Barbara Tracy |
143  !/ | H. L. Tolman |
144  !/ | FORTRAN 90 |
145  !/ | Last update : 02-Dec-2010 !
146  !/ +-----------------------------------+
147  !/
148  !/ 28-Oct-2006 : Origination. ( version 3.10 )
149  !/ 02-Dec-2010 : Adding a mapping PMAP between ( version 3.14 )
150  !/ original and combined partitions
151  !/ ( M. Szyszka )
152  !/
153  ! 1. Purpose :
154  !
155  ! Interface to watershed partitioning routines.
156  !
157  ! 2. Method :
158  !
159  ! Watershed Algorithm of Vincent and Soille, 1991, implemented by
160  ! Barbara Tracy (USACE/ERDC) for NOAA/NCEP.
161  !
162  ! 3. Parameters :
163  !
164  ! Parameter list
165  ! ----------------------------------------------------------------
166  ! SPEC R.A. I 2-D spectrum E(f,theta).
167  ! UABS Real I Wind speed.
168  ! UDIR Real I Wind direction.
169  ! DEPTH Real I Water depth.
170  ! WN R.A. I Wavenumebers for each frequency.
171  ! NP Int. O Number of partitions.
172  ! -1 : Spectrum without minumum energy.
173  ! 0 : Spectrum with minumum energy.
174  ! but no partitions.
175  ! XP R.A. O Parameters describing partitions.
176  ! Entry '0' contains entire spectrum.
177  ! DIMXP Int. I Second dimension of XP.
178  ! ----------------------------------------------------------------
179  !
180  ! 4. Subroutines used :
181  !
182  ! Name Type Module Description
183  ! ----------------------------------------------------------------
184  ! STRACE Sur. W3SERVMD Subroutine tracing.
185  ! ----------------------------------------------------------------
186  !
187  ! 5. Called by :
188  !
189  ! 6. Error messages :
190  !
191  ! 7. Remarks :
192  !
193  ! - To achieve minimum storage but guaranteed storage of all
194  ! partitions DIMXP = ((NK+1)/2) * ((NTH-1)/2) unless specified
195  ! otherwise below.
196  !
197  ! This version of W3PART contains alternate Met Office partitioning
198  ! methods, selected at runtime using the PTMETH namlist variable:
199  ! 1) Standard WW3 partitioning
200  ! 2) Met Office extended partitioning using split-partitions
201  ! (removes the wind sea part of any swell partiton and combines
202  ! with total wind sea partition).
203  ! 3) Met Office "wave systems" - no classification or combining of
204  ! wind sea partitions. All partitions output and ordered simply
205  ! by wave height.
206  ! 4) Classic, simple wave age based partitioning generating
207  ! a single wind sea and swell partition. [DIMXP = 2]
208  ! 5) 2-band partitioning; produces hi and low freqency band partitions
209  ! using a user-defined cutoff frequency (PTFCUT). [DIMXP = 2]
210  !
211  ! (Chris Bunney, UK Met Office, Jul 2018)
212  !
213  ! 8. Structure :
214  !
215  ! 9. Switches :
216  !
217  ! !/S Enable subroutine tracing.
218  ! !/T Enable test output
219  !
220  ! 10. Source code :
221  !
222  !/ ------------------------------------------------------------------- /
223  !/
224  USE constants
225 #ifdef W3_S
226  USE w3servmd, ONLY: strace
227 #endif
228  !
229  USE w3gdatmd, ONLY: nk, nth, nspec, sig, th
230  USE w3odatmd, ONLY: wscut, flcomb
231  !
232  IMPLICIT NONE
233  !/
234  !/ ------------------------------------------------------------------- /
235  !/ Parameter list
236  !/
237  INTEGER, INTENT(OUT) :: NP
238  INTEGER, INTENT(IN) :: DIMXP
239  REAL, INTENT(IN) :: SPEC(NK,NTH), WN(NK), UABS, &
240  UDIR, DEPTH
241  REAL, INTENT(OUT) :: XP(DIMP,0:DIMXP)
242  !/
243  !/ ------------------------------------------------------------------- /
244  !/ Local parameters
245  !/
246  INTEGER :: ITH, IMI(NSPEC), IMD(NSPEC), &
247  IMO(NSPEC), IND(NSPEC), NP_MAX, &
248  IP, IT(1), INDEX(DIMXP), NWS, &
249  IPW, IPT, ISP
250  INTEGER :: PMAP(DIMXP)
251 #ifdef W3_S
252  INTEGER, SAVE :: IENT = 0
253 #endif
254  REAL :: ZP(NSPEC), ZMIN, ZMAX, Z(NSPEC), &
255  FACT, WSMAX, HSMAX
256  REAL :: TP(DIMP,DIMXP)
257  INTEGER :: IK, WIND_PART ! ChrisB; added for new
258  REAL :: C, UPAR, SIGCUT ! UKMO partioning methods
259  !/
260  !/ ------------------------------------------------------------------- /
261  ! 0. Initializations
262  !
263 #ifdef W3_S
264  CALL strace (ient, 'W3PART')
265 #endif
266  !
267  np = 0
268  xp = 0.
269  !
270  ! -------------------------------------------------------------------- /
271  ! 1. Process input spectrum
272  ! 1.a 2-D to 1-D spectrum
273  !
274  DO ith=1, nth
275  zp(1+(ith-1)*nk:ith*nk) = spec(:,ith)
276  END DO
277 
278  !
279  ! PTMETH == 4 : Do simple partitioning based solely on the
280  ! wave age criterion (produces one swell and one wind sea only):
281  !
282  IF( ptmeth .EQ. 4 ) THEN
283  DO ik=1, nk
284  DO ith=1, nth
285  isp = ik + (ith-1) * nk ! index into partition array IMO
286 
287  upar = wsmult * uabs * max(0.0, cos(th(ith)-dera*udir))
288  c = sig(ik) / wn(ik)
289 
290  IF( upar .LE. c ) THEN
291  ! Is swell:
292  imo(isp) = 2
293  ELSE
294  ! Is wind sea:
295  imo(isp) = 1
296  ENDIF
297  ENDDO
298  ENDDO
299 
300  ! We have a max of up to two partitions:
301  np_max=2
302 
303  ! Calculate mean parameters:
304  CALL ptmean ( np_max, imo, zp, depth, uabs, udir, wn, &
305  np, xp, dimxp, pmap )
306 
307  ! No more processing required, return:
308  RETURN
309  ENDIF ! PTMETH == 4
310  !
311  ! PTMETH == 5 : produce "high" and "low" band partitions
312  ! using a frequency cutoff:
313  !
314  IF( ptmeth .EQ. 5 ) THEN
315  sigcut = tpi * ptfcut
316  DO ik = 1, nk
317  ! If bin center <= freq cutoff then mark as "low band".
318  IF(sig(ik) .LE. sigcut) THEN
319  ip = 2
320  ELSE
321  ip = 1
322  ENDIF
323 
324  DO ith=1, nth
325  isp = ik + (ith-1) * nk ! index into partition array IMO
326  imo(isp) = ip
327  ENDDO
328  ENDDO
329 
330  ! We only ever have 2 partitions:
331  np_max=2
332 
333  ! Calculate mean parameters:
334  CALL ptmean ( np_max, imo, zp, depth, uabs, udir, wn, &
335  np, xp, dimxp, pmap )
336 
337  ! No more processing required, return:
338  RETURN
339  ENDIF ! PTMETH == 5
340  !
341  ! 1.b Invert spectrum and 'digitize'
342  !
343  zmin = minval( zp )
344  zmax = maxval( zp )
345  IF ( zmax-zmin .LT. 1.e-9 ) RETURN
346  !
347  z = zmax - zp
348  !
349  fact = real(ihmax-1) / ( zmax - zmin )
350  imi = max( 1 , min( ihmax , nint( 1. + z*fact ) ) )
351  !
352  ! 1.c Sort digitized image
353  !
354  CALL ptsort ( imi, ind, ihmax )
355  !
356  ! -------------------------------------------------------------------- /
357  ! 2. Perform partitioning
358  ! 2.a Update nearest neighbor info as needed.
359  !
360  CALL ptnghb
361  !
362  ! 2.b Incremental flooding
363  !
364  CALL pt_fld ( imi, ind, imo, zp, np_max )
365  !
366  ! 2.c Compute parameters per partition
367  ! NP and NX initialized inside routine.
368  !
369  CALL ptmean ( np_max, imo, zp, depth, uabs, udir, wn, &
370  np, xp, dimxp, pmap )
371  !
372  ! 2.d PTMETH == 2: move the wind sea part of the partitions into a
373  ! seperate partition and recalculate the mean parameters.
374  !
375  IF ( np .GT. 0 .AND. ptmeth .EQ. 2 ) THEN
376  wind_part = np_max
377 
378  DO ik=1, nk
379  DO ith=1, nth
380  isp = ik + (ith-1) * nk ! index into partition array IMO
381  upar = wsmult * uabs * max(0.0, cos(th(ith)-dera*udir))
382  c = sig(ik) / wn(ik)
383 
384  IF( c .LT. upar ) THEN
385  ! Bin is wind forced - mark as new wind partition:
386  wind_part = np_max + 1
387 
388  ! Update status map to show new wind partition
389  imo(isp) = wind_part
390  ENDIF
391  ENDDO
392  ENDDO
393 
394  IF( wind_part .NE. np_max ) THEN
395  ! Some bins were marked as wind sea - recalculate
396  ! integrated parameters:
397  np_max = wind_part
398  CALL ptmean ( np_max, imo, zp, depth, uabs, udir, wn, &
399  np, xp, dimxp, pmap )
400  ENDIF
401  ENDIF
402  !
403  ! -------------------------------------------------------------------- /
404  ! 3. Sort and recombine wind seas as needed
405  ! 3.a Sort by wind sea fraction
406  !
407  IF ( np .LE. 1 ) RETURN
408 
409  ! -----------------------------------------------------------------
410  ! PTMETH == 3: Don't classify or combine any partitions as wind sea.
411  ! Simply sort by HS and return.
412  ! -----------------------------------------------------------------
413  IF( ptmeth .EQ. 3 ) THEN
414  tp(:,1:np) = xp(:,1:np)
415  xp(:,1:np) = 0.
416 
417  DO ip=1, np
418  it = maxloc(tp(1,1:np))
419  xp(:,ip) = tp(:,it(1))
420  tp(1,it(1)) = -1.
421  END DO
422 
423  RETURN ! Don't process any further
424  ENDIF ! PTMETH == 3
425 
426  ! -----------------------------------------------------------------
427  ! PTMETH == 1: Default WW3 partitioning.
428  ! -----------------------------------------------------------------
429  tp(:,1:np) = xp(:,1:np)
430  xp(:,1:np) = 0.
431  index(1:np) = 0
432  nws = 0
433  !
434  DO ip=1, np
435  it = maxloc(tp(6,1:np))
436  index(ip) = it(1)
437  xp(:,ip) = tp(:,index(ip))
438  IF ( tp(6,it(1)) .GE. wscut ) nws = nws + 1
439  tp(6,it(1)) = -1.
440  END DO
441  !
442  ! 3.b Combine wind seas as needed and resort
443  !
444  IF ( nws.GT.1 .AND. flcomb ) THEN
445  ipw = pmap(index(1))
446  DO ip=2, nws
447  ipt = pmap(index(ip))
448  DO isp=1, nspec
449  IF ( imo(isp) .EQ. ipt ) imo(isp) = ipw
450  END DO
451  END DO
452  !
453  CALL ptmean ( np_max, imo, zp, depth, uabs, udir, wn, &
454  np, xp, dimxp, pmap )
455  IF ( np .LE. 1 ) RETURN
456  !
457  tp(:,1:np) = xp(:,1:np)
458  xp(:,1:np) = 0.
459  index(1:np) = 0
460  nws = 0
461  !
462  DO ip=1, np
463  it = maxloc(tp(6,1:np))
464  index(ip) = it(1)
465  xp(:,ip) = tp(:,index(ip))
466  IF ( tp(6,it(1)) .GE. wscut ) nws = nws + 1
467  tp(6,it(1)) = -1.
468  END DO
469  !
470  END IF
471  !
472  ! 3.c Sort remaining fields by wave height
473  !
474  nws = min( 1 , nws )
475  !
476  tp(:,1:np) = xp(:,1:np)
477  xp(:,1:np) = 0.
478  !
479  IF ( nws .GT. 0 ) THEN
480  xp(:,1) = tp(:,1)
481  tp(1,1) = -1.
482  nws = 1
483  END IF
484  !
485  DO ip=nws+1, np
486  it = maxloc(tp(1,1:np))
487  xp(:,ip) = tp(:,it(1))
488  tp(1,it(1)) = -1.
489  END DO
490  !
491  ! -------------------------------------------------------------------- /
492  ! 4. End of routine
493  !
494  RETURN
495  !/
496  !/ End of W3PART ----------------------------------------------------- /
497  !/
498  END SUBROUTINE w3part
499  !/ ------------------------------------------------------------------- /
512  SUBROUTINE ptsort ( IMI, IND, IHMAX )
513  !/
514  !/ +-----------------------------------+
515  !/ | WAVEWATCH III USACE/NOAA |
516  !/ | Barbara Tracy |
517  !/ | H. L. Tolman |
518  !/ | FORTRAN 90 |
519  !/ | Last update : 19-Oct-2006 !
520  !/ +-----------------------------------+
521  !/
522  !/ 19-Oct-2006 : Origination. ( version 3.10 )
523  !/
524  ! 1. Purpose :
525  !
526  ! This subroutine sorts the image data in ascending order.
527  ! This sort original to F.T.Tracy (2006)
528  !
529  ! 3. Parameters :
530  !
531  ! Parameter list
532  ! ----------------------------------------------------------------
533  ! IMI I.A. I Input discretized spectrum.
534  ! IND I.A. O Sorted data.
535  ! IHMAX Int. I Number of integer levels.
536  ! ----------------------------------------------------------------
537  !
538  ! 4. Subroutines used :
539  !
540  ! Name Type Module Description
541  ! ----------------------------------------------------------------
542  ! STRACE Sur. W3SERVMD Subroutine tracing.
543  ! ----------------------------------------------------------------
544  !
545  ! 10. Source code :
546  !
547  !/ ------------------------------------------------------------------- /
548  !
549 #ifdef W3_S
550  USE w3servmd, ONLY: strace
551 #endif
552  !
553  USE w3gdatmd, ONLY: nspec
554  !
555  IMPLICIT NONE
556  !/
557  !/ ------------------------------------------------------------------- /
558  !/ Parameter list
559  !/
560  INTEGER, INTENT(IN) :: IHMAX, IMI(NSPEC)
561  INTEGER, INTENT(OUT) :: IND(NSPEC)
562  !/
563  !/ ------------------------------------------------------------------- /
564  !/ Local parameters
565  !/
566  INTEGER :: I, IN, IV
567 #ifdef W3_S
568  INTEGER, SAVE :: IENT = 0
569 #endif
570  INTEGER :: NUMV(IHMAX), IADDR(IHMAX), &
571  IORDER(NSPEC)
572  !/
573 #ifdef W3_S
574  CALL strace (ient, 'PTSORT')
575 #endif
576  !
577  ! -------------------------------------------------------------------- /
578  ! 1. Occurences per height
579  !
580  numv = 0
581  DO i=1, nspec
582  numv(imi(i)) = numv(imi(i)) + 1
583  END DO
584  !
585  ! -------------------------------------------------------------------- /
586  ! 2. Starting address per height
587  !
588  iaddr(1) = 1
589  DO i=1, ihmax-1
590  iaddr(i+1) = iaddr(i) + numv(i)
591  END DO
592  !
593  ! -------------------------------------------------------------------- /
594  ! 3. Order points
595  !
596  DO i=1, nspec
597  iv = imi(i)
598  in = iaddr(iv)
599  iorder(i) = in
600  iaddr(iv) = in + 1
601  END DO
602  !
603  ! -------------------------------------------------------------------- /
604  ! 4. Sort points
605  !
606  DO i=1, nspec
607  ind(iorder(i)) = i
608  END DO
609  !
610  RETURN
611  !/
612  !/ End of PTSORT ----------------------------------------------------- /
613  !/
614  END SUBROUTINE ptsort
615  !/ ------------------------------------------------------------------- /
631  SUBROUTINE ptnghb
632  !/
633  !/ +-----------------------------------+
634  !/ | WAVEWATCH III USACE/NOAA |
635  !/ | Barbara Tracy |
636  !/ | H. L. Tolman |
637  !/ | FORTRAN 90 |
638  !/ | Last update : 20-Oct-2006 !
639  !/ +-----------------------------------+
640  !/
641  !/ 20-Oct-2006 : Origination. ( version 3.10 )
642  !/
643  ! 1. Purpose :
644  !
645  ! This subroutine computes the nearest neighbors for each grid
646  ! point. Wrapping of directional distribution (0 to 360)is taken
647  ! care of using the nearest neighbor system
648  !
649  ! 3. Parameters :
650  !
651  ! Parameter list
652  ! ----------------------------------------------------------------
653  ! IMI I.A. I Input discretized spectrum.
654  ! IMD I.A. O Sorted data.
655  ! IHMAX Int. I Number of integer levels.
656  ! ----------------------------------------------------------------
657  !
658  ! 4. Subroutines used :
659  !
660  ! Name Type Module Description
661  ! ----------------------------------------------------------------
662  ! STRACE Sur. W3SERVMD Subroutine tracing.
663  ! ----------------------------------------------------------------
664  !
665  ! 10. Source code :
666  !
667  !/ ------------------------------------------------------------------- /
668  !
669 #ifdef W3_S
670  USE w3servmd, ONLY: strace
671 #endif
672  !
673  USE w3gdatmd, ONLY: nk, nth, nspec
674  !
675  IMPLICIT NONE
676  !/
677  !/ ------------------------------------------------------------------- /
678  !/ Parameter list
679  !/
680  ! INTEGER, INTENT(IN) :: IHMAX, IMI(NSPEC)
681  ! INTEGER, INTENT(IN) :: IMD(NSPEC)
682  !/
683  !/ ------------------------------------------------------------------- /
684  !/ Local parameters
685  !/
686  INTEGER :: N, J, I, K
687 #ifdef W3_S
688  INTEGER, SAVE :: IENT = 0
689  CALL strace (ient, 'PTNGHB')
690 #endif
691  !
692  ! -------------------------------------------------------------------- /
693  ! 1. Check on need of processing
694  !
695  IF ( mk.EQ.nk .AND. mth.EQ.nth ) RETURN
696  !
697  IF ( mk.GT.0 ) DEALLOCATE ( neigh )
698  ALLOCATE ( neigh(9,nspec) )
699  mk = nk
700  mth = nth
701  !
702  ! -------------------------------------------------------------------- /
703  ! 2. Build map
704  !
705  neigh = 0
706  !
707  ! ... Base loop
708  !
709  DO n = 1, nspec
710  !
711  j = (n-1) / nk + 1
712  i = n - (j-1) * nk
713  k = 0
714  !
715  ! ... Point at the left(1)
716  !
717  IF ( i .NE. 1 ) THEN
718  k = k + 1
719  neigh(k, n) = n - 1
720  END IF
721  !
722  ! ... Point at the right (2)
723  !
724  IF ( i .NE. nk ) THEN
725  k = k + 1
726  neigh(k, n) = n + 1
727  END IF
728  !
729  ! ... Point at the bottom(3)
730  !
731  IF ( j .NE. 1 ) THEN
732  k = k + 1
733  neigh(k, n) = n - nk
734  END IF
735  !
736  ! ... ADD Point at bottom_wrap to top
737  !
738  IF ( j .EQ. 1 ) THEN
739  k = k + 1
740  neigh(k,n) = nspec - (nk-i)
741  END IF
742  !
743  ! ... Point at the top(4)
744  !
745  IF ( j .NE. nth ) THEN
746  k = k + 1
747  neigh(k, n) = n + nk
748  END IF
749  !
750  ! ... ADD Point to top_wrap to bottom
751  !
752  IF ( j .EQ. nth ) THEN
753  k = k + 1
754  neigh(k,n) = n - (nth-1) * nk
755  END IF
756  !
757  ! ... Point at the bottom, left(5)
758  !
759  IF ( (i.NE.1) .AND. (j.NE.1) ) THEN
760  k = k + 1
761  neigh(k, n) = n - nk - 1
762  END IF
763  !
764  ! ... Point at the bottom, left with wrap.
765  !
766  IF ( (i.NE.1) .AND. (j.EQ.1) ) THEN
767  k = k + 1
768  neigh(k,n) = n - 1 + nk * (nth-1)
769  END IF
770  !
771  ! ... Point at the bottom, right(6)
772  !
773  IF ( (i.NE.nk) .AND. (j.NE.1) ) THEN
774  k = k + 1
775  neigh(k, n) = n - nk + 1
776  END IF
777  !
778  ! ... Point at the bottom, right with wrap
779  !
780  IF ( (i.NE.nk) .AND. (j.EQ.1) ) THEN
781  k = k + 1
782  neigh(k,n) = n + 1 + nk * (nth - 1)
783  END IF
784  !
785  ! ... Point at the top, left(7)
786  !
787  IF ( (i.NE.1) .AND. (j.NE.nth) ) THEN
788  k = k + 1
789  neigh(k, n) = n + nk - 1
790  END IF
791  !
792  ! ... Point at the top, left with wrap
793  !
794  IF ( (i.NE.1) .AND. (j.EQ.nth) ) THEN
795  k = k + 1
796  neigh(k,n) = n - 1 - (nk) * (nth-1)
797  END IF
798  !
799  ! ... Point at the top, right(8)
800  !
801  IF ( (i.NE.nk) .AND. (j.NE.nth) ) THEN
802  k = k + 1
803  neigh(k, n) = n + nk + 1
804  END IF
805  !
806  ! ... Point at top, right with wrap
807  !
808  !
809  IF ( (i.NE.nk) .AND. (j.EQ.nth) ) THEN
810  k = k + 1
811  neigh(k,n) = n + 1 - (nk) * (nth-1)
812  END IF
813  !
814  neigh(9,n) = k
815  !
816  END DO
817  !
818  RETURN
819  !/
820  !/ End of PTNGHB ----------------------------------------------------- /
821  !/
822  END SUBROUTINE ptnghb
823  !/ ------------------------------------------------------------------- /
840  SUBROUTINE pt_fld ( IMI, IND, IMO, ZP, NPART )
841  !/
842  !/ +-----------------------------------+
843  !/ | WAVEWATCH III NOAA/NCEP |
844  !/ | H. L. Tolman |
845  !/ | FORTRAN 90 |
846  !/ | Last update : 01-Nov-2006 !
847  !/ +-----------------------------------+
848  !/
849  !/ 01-Nov-2006 : Origination. ( version 3.10 )
850  !/
851  ! 1. Purpose :
852  !
853  ! This subroutine does incremental flooding of the image to
854  ! determine the watershed image.
855  !
856  ! 3. Parameters :
857  !
858  ! Parameter list
859  ! ----------------------------------------------------------------
860  ! IMI I.A. I Input discretized spectrum.
861  ! IND I.A. I Sorted addresses.
862  ! IMO I.A. O Output partitioned spectrum.
863  ! ZP R.A. I Spectral array.
864  ! NPART Int. O Number of partitions found.
865  ! ----------------------------------------------------------------
866  !
867  ! 4. Subroutines used :
868  !
869  ! Name Type Module Description
870  ! ----------------------------------------------------------------
871  ! STRACE Sur. W3SERVMD Subroutine tracing.
872  ! ----------------------------------------------------------------
873  !
874  ! 10. Source code :
875  !
876  !/ ------------------------------------------------------------------- /
877  !
878 #ifdef W3_S
879  USE w3servmd, ONLY: strace
880 #endif
881  !
882  USE w3gdatmd, ONLY: nspec
883  !
884  IMPLICIT NONE
885  !/
886  !/ ------------------------------------------------------------------- /
887  !/ Parameter list
888  !/
889  INTEGER, INTENT(IN) :: IMI(NSPEC), IND(NSPEC)
890  INTEGER, INTENT(OUT) :: IMO(NSPEC), NPART
891  REAL, INTENT(IN) :: ZP(NSPEC)
892  !/
893  !/ ------------------------------------------------------------------- /
894  !/ Local parameters
895  !/
896  INTEGER :: MASK, INIT, IWSHED, IMD(NSPEC), &
897  IC_LABEL, IFICT_PIXEL, M, IH, MSAVE, &
898  IP, I, IPP, IC_DIST, IEMPTY, IPPP, &
899  JL, JN, IPT, J
900  INTEGER :: IQ(NSPEC), IQ_START, IQ_END
901 #ifdef W3_S
902  INTEGER, SAVE :: IENT = 0
903 #endif
904  REAL :: ZPMAX, EP1, DIFF
905  !/
906 #ifdef W3_S
907  CALL strace (ient, 'PT_FLD')
908 #endif
909  !
910  ! -------------------------------------------------------------------- /
911  ! 0. Initializations
912  !
913  mask = -2
914  init = -1
915  iwshed = 0
916  imo = init
917  ic_label = 0
918  imd = 0
919  ifict_pixel = -100
920  !
921  iq_start = 1
922  iq_end = 1
923  !
924  zpmax = maxval( zp )
925  !
926  ! -------------------------------------------------------------------- /
927  ! 1. Loop over levels
928  !
929  m = 1
930  !
931  DO ih=1, ihmax
932  msave = m
933  !
934  ! 1.a Pixels at level IH
935  !
936  DO
937  ip = ind(m)
938  IF ( imi(ip) .NE. ih ) EXIT
939  !
940  ! Flag the point, if it stays flagge, it is a separate minimum.
941  !
942  imo(ip) = mask
943  !
944  ! Consider neighbors. If there is neighbor, set distance and add
945  ! to queue.
946  !
947  DO i=1, neigh(9,ip)
948  ipp = neigh(i,ip)
949  IF ( (imo(ipp).GT.0) .OR. (imo(ipp).EQ.iwshed) ) THEN
950  imd(ip) = 1
951  CALL fifo_add (ip)
952  EXIT
953  END IF
954  END DO
955  !
956  IF ( m+1 .GT. nspec ) THEN
957  EXIT
958  ELSE
959  m = m + 1
960  END IF
961  !
962  END DO
963  !
964  ! 1.b Process the queue
965  !
966  ic_dist = 1
967  CALL fifo_add (ifict_pixel)
968  !
969  DO
970  CALL fifo_first (ip)
971  !
972  ! Check for end of processing
973  !
974  IF ( ip .EQ. ifict_pixel ) THEN
975  CALL fifo_empty (iempty)
976  IF ( iempty .EQ. 1 ) THEN
977  EXIT
978  ELSE
979  CALL fifo_add (ifict_pixel)
980  ic_dist = ic_dist + 1
981  CALL fifo_first (ip)
982  END IF
983  END IF
984  !
985  ! Process queue
986  !
987  DO i=1, neigh(9,ip)
988  ipp = neigh(i,ip)
989  !
990  ! Check for labeled watersheds or basins
991  !
992  IF ( (imd(ipp).LT.ic_dist) .AND. ( (imo(ipp).GT.0) .OR. &
993  (imo(ipp).EQ.iwshed))) THEN
994  !
995  IF ( imo(ipp) .GT. 0 ) THEN
996  !
997  IF ((imo(ip) .EQ. mask) .OR. (imo(ip) .EQ. &
998  iwshed)) THEN
999  imo(ip) = imo(ipp)
1000  ELSE IF (imo(ip) .NE. imo(ipp)) THEN
1001  imo(ip) = iwshed
1002  END IF
1003  !
1004  ELSE IF (imo(ip) .EQ. mask) THEN
1005  !
1006  imo(ip) = iwshed
1007  !
1008  END IF
1009  !
1010  ELSE IF ( (imo(ipp).EQ.mask) .AND. (imd(ipp).EQ.0) ) THEN
1011  !
1012  imd(ipp) = ic_dist + 1
1013  CALL fifo_add (ipp)
1014  !
1015  END IF
1016  !
1017  END DO
1018  !
1019  END DO
1020  !
1021  ! 1.c Check for mask values in IMO to identify new basins
1022  !
1023  m = msave
1024  !
1025  DO
1026  ip = ind(m)
1027  IF ( imi(ip) .NE. ih ) EXIT
1028  imd(ip) = 0
1029  !
1030  IF (imo(ip) .EQ. mask) THEN
1031  !
1032  ! ... New label for pixel
1033  !
1034  ic_label = ic_label + 1
1035  CALL fifo_add (ip)
1036  imo(ip) = ic_label
1037  !
1038  ! ... and all connected to it ...
1039  !
1040  DO
1041  CALL fifo_empty (iempty)
1042  IF ( iempty .EQ. 1 ) EXIT
1043  CALL fifo_first (ipp)
1044  !
1045  DO i=1, neigh(9,ipp)
1046  ippp = neigh(i,ipp)
1047  IF ( imo(ippp) .EQ. mask ) THEN
1048  CALL fifo_add (ippp)
1049  imo(ippp) = ic_label
1050  END IF
1051  END DO
1052  !
1053  END DO
1054  !
1055  END IF
1056  !
1057  IF ( m + 1 .GT. nspec ) THEN
1058  EXIT
1059  ELSE
1060  m = m + 1
1061  END IF
1062  !
1063  END DO
1064  !
1065  END DO
1066  !
1067  ! -------------------------------------------------------------------- /
1068  ! 2. Find nearest neighbor of 0 watershed points and replace
1069  ! use original input to check which group to affiliate with 0
1070  ! Soring changes first in IMD to assure symetry in adjustment.
1071  !
1072  DO j=1, 5
1073  imd = imo
1074  DO jl=1 , nspec
1075  ipt = -1
1076  IF ( imo(jl) .EQ. 0 ) THEN
1077  ep1 = zpmax
1078  DO jn=1, neigh(9,jl)
1079  diff = abs( zp(jl) - zp(neigh(jn,jl)))
1080  IF ( (diff.LE.ep1) .AND. (imo(neigh(jn,jl)).NE.0) ) THEN
1081  ep1 = diff
1082  ipt = jn
1083  END IF
1084  END DO
1085  IF ( ipt .GT. 0 ) imd(jl) = imo(neigh(ipt,jl))
1086  END IF
1087  END DO
1088  imo = imd
1089  IF ( minval(imo) .GT. 0 ) EXIT
1090  END DO
1091  !
1092  npart = ic_label
1093  !
1094  RETURN
1095  !
1096  CONTAINS
1097  !/ ------------------------------------------------------------------- /
1104  SUBROUTINE fifo_add ( IV )
1106  INTEGER, INTENT(IN) :: IV
1107  !
1108  iq(iq_end) = iv
1109  !
1110  iq_end = iq_end + 1
1111  IF ( iq_end .GT. nspec ) iq_end = 1
1112  !
1113  RETURN
1114  END SUBROUTINE fifo_add
1115  !/ ------------------------------------------------------------------- /
1123  SUBROUTINE fifo_empty ( IEMPTY )
1125  INTEGER, INTENT(OUT) :: IEMPTY
1126  !
1127  IF ( iq_start .NE. iq_end ) THEN
1128  iempty = 0
1129  ELSE
1130  iempty = 1
1131  END IF
1132  !
1133  RETURN
1134  END SUBROUTINE fifo_empty
1135  !/ ------------------------------------------------------------------- /
1143  SUBROUTINE fifo_first ( IV )
1145  INTEGER, INTENT(OUT) :: IV
1146  !
1147  iv = iq(iq_start)
1148  !
1149  iq_start = iq_start + 1
1150  IF ( iq_start .GT. nspec ) iq_start = 1
1151  !
1152  RETURN
1153  END SUBROUTINE fifo_first
1154  !/
1155  !/ End of PT_FLD ----------------------------------------------------- /
1156  !/
1157  END SUBROUTINE pt_fld
1158  !/ ------------------------------------------------------------------- /
1176  SUBROUTINE ptmean ( NPI, IMO, ZP, DEPTH, UABS, UDIR, WN, &
1177  NPO, XP, DIMXP, PMAP )
1178  !/
1179  !/ +-----------------------------------+
1180  !/ | WAVEWATCH III USACE/NOAA |
1181  !/ | Barbara Tracy |
1182  !/ | H. L. Tolman |
1183  !/ | FORTRAN 90 |
1184  !/ | Last update : 02-Dec-2010 !
1185  !/ +-----------------------------------+
1186  !/
1187  !/ 28-Oct-2006 : Origination. ( version 3.10 )
1188  !/ 02-Nov-2006 : Adding tail to integration. ( version 3.10 )
1189  !/ 24-Mar-2007 : Adding overall field. ( version 3.11 )
1190  !/ 02-Dec-2010 : Adding a mapping PMAP between ( version 3.14 )
1191  !/ original and combined partitions
1192  !/ ( M. Szyszka )
1193  !/
1194  ! 1. Purpose :
1195  !
1196  ! Compute mean parameters per partition.
1197  !
1198  ! 3. Parameters :
1199  !
1200  ! Parameter list
1201  ! ----------------------------------------------------------------
1202  ! NPI Int. I Number of partitions found.
1203  ! IMO I.A. I Partition map.
1204  ! ZP R.A. I Input spectrum.
1205  ! DEPTH Real I Water depth.
1206  ! UABS Real I Wind speed.
1207  ! UDIR Real I Wind direction.
1208  ! WN R.A. I Wavenumebers for each frequency.
1209  ! NPO Int. O Number of partitions with mean parameters.
1210  ! XP R.A. O Array with output parameters.
1211  ! DIMXP int. I Second dimension of XP.
1212  ! PMAP I.A. O Mapping between orig. and combined partitions
1213  ! ----------------------------------------------------------------
1214  !
1215  ! 4. Subroutines used :
1216  !
1217  ! Name Type Module Description
1218  ! ----------------------------------------------------------------
1219  ! STRACE Sur. W3SERVMD Subroutine tracing.
1220  ! WAVNU1 Subr. W3DISPMD Wavenumber computation.
1221  ! ----------------------------------------------------------------
1222  !
1223  ! 10. Source code :
1224  !
1225  !/ ------------------------------------------------------------------- /
1226  !
1227  USE constants
1228 #ifdef W3_S
1229  USE w3servmd, ONLY: strace
1230 #endif
1231  USE w3dispmd, ONLY: wavnu1
1232  !
1233  USE w3gdatmd, ONLY: nk, nth, nspec, dth, sig, dsii, dsip, &
1234  ecos, esin, xfr, fachfe, th, fte
1235  USE w3odatmd, ONLY: iaproc, naperr, ndse, ndst
1236  !
1237  IMPLICIT NONE
1238  !/
1239  !/ ------------------------------------------------------------------- /
1240  !/ Parameter list
1241  !/
1242  INTEGER, INTENT(IN) :: NPI, IMO(NSPEC), DIMXP
1243  INTEGER, INTENT(OUT) :: NPO, PMAP(DIMXP)
1244  REAL, INTENT(IN) :: ZP(NSPEC), DEPTH, UABS, UDIR, WN(NK)
1245  REAL, INTENT(OUT) :: XP(DIMP,0:DIMXP)
1246  !/
1247  !/ ------------------------------------------------------------------- /
1248  !/ Local parameters
1249  !/
1250  INTEGER :: IK, ITH, ISP, IP, IFPMAX(0:NPI)
1251 #ifdef W3_S
1252  INTEGER, SAVE :: IENT = 0
1253 #endif
1254  REAL :: SUMF(0:NK+1,0:NPI), SUMFW(NK,0:NPI), &
1255  SUMFX(NK,0:NPI), SUMFY(NK,0:NPI), &
1256  SUME(0:NPI), SUMEW(0:NPI), &
1257  SUMEX(0:NPI), SUMEY(0:NPI), &
1258  EFPMAX(0:NPI), FCDIR(NTH)
1259  REAL,DIMENSION(0:NPI) :: SUME1, SUME2, SUMEM1, SUMQP
1260  REAL :: HS, XL, XH, XL2, XH2, EL, EH, DENOM, &
1261  SIGP, WNP, CGP, UPAR, C(NK), RD, FACT
1262  REAL :: QP, M0, M1, M2, MM1, FSPRD, EPM_FP, ALP_PM
1263  REAL :: Y, YHAT, XHAT, SUMXY, SUMYLOGY, NUMER,&
1264  SUMY, SUMXXY, SUMXYLOGY, SUMEXP, SUMEYP
1265  REAL :: FTEII
1266  !/
1267 #ifdef W3_S
1268  CALL strace (ient, 'PTMEAN')
1269 #endif
1270  !
1271  ! -------------------------------------------------------------------- /
1272  ! 1. Check on need of processing
1273  !
1274  npo = 0
1275  xp = 0.
1276  !
1277  IF ( npi .EQ. 0 ) RETURN
1278  !
1279  ! -------------------------------------------------------------------- /
1280  ! 2. Initialize arrays
1281  !
1282  sumf = 0.
1283  sumfw = 0.
1284  sumfx = 0.
1285  sumfy = 0.
1286  sume = 0.
1287  !
1288  sume1 = 0. !/ first spectral moment
1289  sume2 = 0. !/ second spectral moment
1290  sumem1 = 0. !/ inverse spectral moment
1291  sumqp = 0. !/ peakedness parameter
1292  !
1293  sumew = 0.
1294  sumex = 0.
1295  sumey = 0.
1296  ifpmax = 0
1297  efpmax = 0.
1298  !
1299  DO ik=1, nk
1300  c(ik) = sig(ik) / wn(ik)
1301  END DO
1302  !
1303  DO ith=1, nth
1304  upar = wsmult * uabs * max(0.,cos(th(ith)-dera*udir))
1305  IF ( upar .LT. c(nk) ) THEN
1306  fcdir(ith) = sig(nk+1)
1307  ELSE
1308  DO ik=nk-1, 2, -1
1309  IF ( upar .LT. c(ik) ) EXIT
1310  END DO
1311  rd = (c(ik)-upar) / (c(ik)-c(ik+1))
1312  IF ( rd .LT. 0 ) THEN
1313  ik = 0
1314  rd = max( 0., rd+1. )
1315  END IF
1316  fcdir(ith) = rd*sig(ik+1) + (1.-rd)*sig(ik)
1317  END IF
1318  END DO
1319  !
1320  ! -------------------------------------------------------------------- /
1321  ! 3. Spectral integrals and preps
1322  ! 3.a Integrals
1323  ! NOTE: Factor DTH only used in Hs computation.
1324  !
1325  DO ik=1, nk
1326  DO ith=1, nth
1327  isp = ik + (ith-1)*nk
1328  ip = imo(isp)
1329  fact = max( 0. , min( 1. , &
1330  1. - ( fcdir(ith) - 0.5*(sig(ik-1)+sig(ik)) ) / dsip(ik) ) )
1331  sumf(ik, 0) = sumf(ik, 0) + zp(isp)
1332  sumfw(ik, 0) = sumfw(ik, 0) + zp(isp) * fact
1333  sumfx(ik, 0) = sumfx(ik, 0) + zp(isp) * ecos(ith)
1334  sumfy(ik, 0) = sumfy(ik, 0) + zp(isp) * esin(ith)
1335  IF ( ip .EQ. 0 ) cycle
1336  sumf(ik,ip) = sumf(ik,ip) + zp(isp)
1337  sumfw(ik,ip) = sumfw(ik,ip) + zp(isp) * fact
1338  sumfx(ik,ip) = sumfx(ik,ip) + zp(isp) * ecos(ith)
1339  sumfy(ik,ip) = sumfy(ik,ip) + zp(isp) * esin(ith)
1340  END DO
1341  END DO
1342  sumf(nk+1,:) = sumf(nk,:) * fachfe
1343  !
1344  DO ip=0, npi
1345  DO ik=1, nk
1346  sume(ip) = sume(ip) + sumf(ik,ip) * dsii(ik)
1347  sumqp(ip) = sumqp(ip) + sumf(ik,ip)**2 * dsii(ik) * sig(ik)
1348  sume1(ip) = sume1(ip) + sumf(ik,ip) * dsii(ik) * sig(ik)
1349  sume2(ip) = sume2(ip) + sumf(ik,ip) * dsii(ik) * sig(ik)**2
1350  sumem1(ip) = sumem1(ip) + sumf(ik,ip) * dsii(ik) / sig(ik)
1351 
1352  sumew(ip) = sumew(ip) + sumfw(ik,ip) * dsii(ik)
1353  sumex(ip) = sumex(ip) + sumfx(ik,ip) * dsii(ik)
1354  sumey(ip) = sumey(ip) + sumfy(ik,ip) * dsii(ik)
1355  IF ( sumf(ik,ip) .GT. efpmax(ip) ) THEN
1356  ifpmax(ip) = ik
1357  efpmax(ip) = sumf(ik,ip)
1358  END IF
1359  END DO
1360 
1361  !SUME (IP) = SUME (IP) + SUMF (NK,IP) * FTE
1362  !SUME1(IP) = SUME1(IP) + SUMF (NK,IP) * FTE
1363  !SUME2(IP) = SUME2(IP) + SUMF (NK,IP) * FTE
1364  !SUMEM1(IP) = SUMEM1(IP) + SUMF (NK,IP) * FTE
1365  !SUMQP(IP) = SUMQP(IP) + SUMF (NK,IP) * FTE
1366  !SUMEW(IP) = SUMEW(IP) + SUMFW(NK,IP) * FTE
1367  !SUMEX(IP) = SUMEX(IP) + SUMFX(NK,IP) * FTE
1368  !SUMEY(IP) = SUMEY(IP) + SUMFY(NK,IP) * FTE
1369  ! Met Office: Proposed bugfix for tail calculations, previously
1370  ! PT1 and PT2 values were found to be too low when using the
1371  ! FTE scaling factor for the tail. I think there are two issues:
1372  ! 1. energy spectrum is scaled in radian frequency space above by DSII.
1373  ! This needs to be consistent and FTE contains a DTH*SIG(NK)
1374  ! factor that is not used in the DSII scaled calcs above
1375  ! 2. the tail fit calcs for period parameters needs to follow
1376  ! the form used in w3iogomd and scaling should be
1377  ! based on the relationship between FTE and FT1, FTTR etc.
1378  ! as per w3iogomd and ww3_grid
1379  fteii = fte / (dth * sig(nk))
1380  sume(ip) = sume(ip) + sumf(nk,ip) * fteii
1381  sume1(ip) = sume1(ip) + sumf(nk,ip) * sig(nk) * fteii * (0.3333 / 0.25)
1382  sume2(ip) = sume2(ip) + sumf(nk,ip) * sig(nk)**2 * fteii * (0.5 / 0.25)
1383  sumem1(ip) = sumem1(ip) + sumf(nk,ip) / sig(nk) * fteii * (0.2 / 0.25)
1384  sumqp(ip) = sumqp(ip) + sumf(nk,ip) * fteii
1385  sumew(ip) = sumew(ip) + sumfw(nk,ip) * fteii
1386  sumex(ip) = sumex(ip) + sumfx(nk,ip) * fteii
1387  sumey(ip) = sumey(ip) + sumfy(nk,ip) * fteii
1388 
1389  END DO
1390  !
1391  ! -------------------------------------------------------------------- /
1392  ! 4. Compute pars
1393  !
1394  npo = -1
1395  !
1396  DO ip=0, npi
1397  !
1398  sumexp = 0.
1399  sumeyp = 0.
1400  !
1401  m0 = sume(ip) * dth * tpiinv
1402  hs = 4. * sqrt( max( m0 , 0. ) )
1403  IF ( hs .LT. hspmin ) THEN
1404  ! For wind cutoff and 2-band partitioning methods, keep the
1405  ! partition, but set the integrated parameters to UNDEF
1406  ! for Hs values less that HSPMIN:
1407  IF( ptmeth .EQ. 4 .OR. ptmeth .EQ. 5 ) THEN
1408  npo = npo + 1
1409  xp(:,npo) = undef
1410  xp(6,npo) = 0.0 ! Set wind sea frac to zero
1411  ENDIF
1412  cycle
1413  ENDIF
1414  !
1415  IF ( npo .GE. dimxp ) GOTO 2000
1416  npo = npo + 1
1417  IF (ip.GT.0)THEN
1418  IF(npo.LT.1)cycle
1419  pmap(npo) = ip
1420  ENDIF
1421  !
1422  m1 = sume1(ip) * dth * tpiinv**2
1423  m2 = sume2(ip) * dth * tpiinv**3
1424  mm1 = sumem1(ip) * dth
1425  qp = sumqp(ip) *(dth * tpiinv)**2
1426  ! M1 = MAX( M1, 1.E-7 )
1427  ! M2 = MAX( M2, 1.E-7 )
1428  !
1429  xl = 1. / xfr - 1.
1430  xh = xfr - 1.
1431  xl2 = xl**2
1432  xh2 = xh**2
1433  el = sumf(ifpmax(ip)-1,ip) - sumf(ifpmax(ip),ip)
1434  eh = sumf(ifpmax(ip)+1,ip) - sumf(ifpmax(ip),ip)
1435  denom = xl*eh - xh*el
1436  sigp = sig(ifpmax(ip))
1437  IF (denom.NE.0.) THEN
1438  sigp = sigp *( 1. + 0.5 * ( xl2*eh - xh2*el ) &
1439  / sign( abs(denom) , denom ) )
1440  END IF
1441  CALL wavnu1 ( sigp, depth, wnp, cgp )
1442  !
1443  !/ --- Parabolic fit around the spectral peak ---
1444  ik = ifpmax(ip)
1445  efpmax(ip) = sumf(ik,ip) * dth
1446  IF (ik.GT.1 .AND. ik.LT.nk) THEN
1447  el = sumf(ik-1,ip) * dth
1448  eh = sumf(ik+1,ip) * dth
1449  numer = 0.125 * ( el - eh )**2
1450  denom = el - 2. * efpmax(ip) + eh
1451  IF (denom.NE.0.) efpmax(ip) = efpmax(ip) &
1452  - numer / sign( abs(denom),denom )
1453  END IF
1454  !
1455  !/ --- Weighted least-squares regression to estimate frequency
1456  !/ spread (FSPRD) to an exponential function:
1457  !/ E(f) = A * exp(-1/2*(f-fp)/B)**2 ,
1458  !/ where B is frequency spread and E(f) is used for
1459  !/ weighting to avoid greater weights to smalll values
1460  !/ in ordinary least-square fit. ---
1461  fsprd = undef
1462  sumy = 0.
1463  sumxy = 0.
1464  sumxxy = 0.
1465  sumylogy = 0.
1466  sumxylogy = 0.
1467  !
1468  DO ik=1, nk
1469  y = sumf(ik,ip)*dth
1470  ! --- sums for weighted least-squares ---
1471  IF (y.GE.1.e-15) THEN
1472  yhat = log(y)
1473  xhat = -0.5 * ( (sig(ik)-sigp)*tpiinv )**2
1474  sumy = sumy + y
1475  sumxy = sumxy + xhat * yhat
1476  sumxxy = sumxxy + xhat * xhat * y
1477  sumylogy = sumylogy + y * yhat
1478  sumxylogy = sumxylogy + sumxy * yhat
1479  END IF
1480  END DO
1481  !
1482  numer = sumy * sumxxy - sumxy**2
1483  denom = sumy * sumxylogy - sumxy * sumylogy
1484  IF (denom.NE.0.) fsprd = sqrt( numer / sign(abs(denom),numer) )
1485  !
1486  sumexp = sumfx(ifpmax(ip),ip) * dsii(ifpmax(ip))
1487  sumeyp = sumfy(ifpmax(ip),ip) * dsii(ifpmax(ip))
1488  !
1489  !/ --- Significant wave height ---
1490  xp(1,npo) = hs
1491  !/ --- Peak wave period ---
1492  xp(2,npo) = tpi / sigp
1493  !/ --- Peak wave length ---
1494  xp(3,npo) = tpi / wnp
1495  !/ --- Mean wave direction ---
1496  xp(4,npo) = mod( 630.-atan2(sumey(ip),sumex(ip))*rade , 360. )
1497  !/ --- Mean directional spread ---
1498  xp(5,npo) = rade * sqrt( max( 0. , 2. * ( 1. - sqrt( &
1499  max(0.,(sumex(ip)**2+sumey(ip)**2)/sume(ip)**2) ) ) ) )
1500  !/ --- Wind sea fraction ---
1501  xp(6,npo) = sumew(ip) / sume(ip)
1502  !/ --- Peak wave direction ---
1503  xp(7,npo) = mod(630.-atan2(sumeyp,sumexp)*rade , 360.)
1504  !/ --- Spectral width (Longuet-Higgins 1975) ---
1505  xp(8,npo) = sqrt( max( 1. , m2*m0 / m1**2 ) - 1. )
1506  !/ --- JONSWAP peak enhancement parameter (E(fp)/EPM(fp))---
1507  ! EPM_FMX = ALPHA_PM_FMX * GRAV**2 * TPI * SIGP**-5 * EXP(-5/4)
1508  alp_pm = 0.3125 * hs**2 * (sigp)**4
1509  epm_fp = alp_pm * tpi * (sigp**(-5)) * 2.865048e-1
1510  xp(9,npo) = max( efpmax(ip) / epm_fp , 1.0 )
1511  !/ --- peakedness parameter (Goda 1970) ---
1512  xp(10,npo) = 2. * qp / m0**2
1513  !/ --- gaussian frequency width ---
1514  xp(11,npo) = fsprd
1515  !/ --- wave energy period (inverse moment) ---
1516  xp(12,npo) = mm1 / m0
1517  !/ --- mean wave period (first moment) ---
1518  xp(13,npo) = m0 / m1
1519  !/ --- zero-upcrossing period (second moment) ---
1520  xp(14,npo) = sqrt( m0 / m2 )
1521  !/ --- peak spectral density (one-dimensional) ---
1522  xp(15,npo) = efpmax(ip)
1523  !
1524  END DO
1525  !
1526  RETURN
1527  !
1528  ! Escape locations read errors --------------------------------------- *
1529  !
1530 2000 CONTINUE
1531  IF ( iaproc .EQ. naperr ) WRITE (ndse,1000) npo+1
1532  RETURN
1533  !
1534  ! Formats
1535  !
1536 1000 FORMAT (/' *** WAVEWATCH III ERROR IN PTMEAN :'/ &
1537  ' XP ARRAY TOO SMALL AT PARTITION',i6/)
1538  !/
1539  !/ End of PTMEAN ----------------------------------------------------- /
1540  !/
1541  END SUBROUTINE ptmean
1542  !/
1543  !/ End of module W3PARTMD -------------------------------------------- /
1544  !/
1545 END MODULE w3partmd
w3gdatmd::nk
integer, pointer nk
Definition: w3gdatmd.F90:1230
w3partmd::ptsort
subroutine ptsort(IMI, IND, IHMAX)
Sorts the image data in ascending order.
Definition: w3partmd.F90:513
w3gdatmd::dth
real, pointer dth
Definition: w3gdatmd.F90:1232
w3gdatmd::nspec
integer, pointer nspec
Definition: w3gdatmd.F90:1230
constants::dera
real, parameter dera
DERA Conversion factor from degrees to radians.
Definition: constants.F90:77
w3partmd
Spectral partitioning according to the watershed method.
Definition: w3partmd.F90:18
fifo_add
subroutine fifo_add(IV)
Add point to FIFO queue.
Definition: w3partmd.F90:1105
fifo_empty
subroutine fifo_empty(IEMPTY)
Check if queue is empty.
Definition: w3partmd.F90:1124
w3gdatmd::sig
real, dimension(:), pointer sig
Definition: w3gdatmd.F90:1234
w3odatmd::ptmeth
integer, pointer ptmeth
Definition: w3odatmd.F90:555
w3odatmd::iaproc
integer, pointer iaproc
Definition: w3odatmd.F90:457
w3gdatmd::fachfe
real, pointer fachfe
Definition: w3gdatmd.F90:1232
w3gdatmd::ecos
real, dimension(:), pointer ecos
Definition: w3gdatmd.F90:1234
constants::rade
real, parameter rade
RADE Conversion factor from radians to degrees.
Definition: constants.F90:76
w3gdatmd::dsip
real, dimension(:), pointer dsip
Definition: w3gdatmd.F90:1234
w3gdatmd::th
real, dimension(:), pointer th
Definition: w3gdatmd.F90:1234
w3odatmd::ndse
integer, pointer ndse
Definition: w3odatmd.F90:456
fifo_first
subroutine fifo_first(IV)
Get point out of queue.
Definition: w3partmd.F90:1144
w3gdatmd::esin
real, dimension(:), pointer esin
Definition: w3gdatmd.F90:1234
w3odatmd::naperr
integer, pointer naperr
Definition: w3odatmd.F90:457
w3servmd
Definition: w3servmd.F90:3
w3gdatmd::dsii
real, dimension(:), pointer dsii
Definition: w3gdatmd.F90:1234
w3odatmd::flcomb
logical, pointer flcomb
Definition: w3odatmd.F90:554
constants::tpiinv
real, parameter tpiinv
TPIINV Inverse of 2*Pi.
Definition: constants.F90:74
w3odatmd::hspmin
real, pointer hspmin
Definition: w3odatmd.F90:553
w3gdatmd::nth
integer, pointer nth
Definition: w3gdatmd.F90:1230
w3odatmd
Definition: w3odatmd.F90:3
w3partmd::pt_fld
subroutine pt_fld(IMI, IND, IMO, ZP, NPART)
Image watersheding.
Definition: w3partmd.F90:841
w3odatmd::wsmult
real, pointer wsmult
Definition: w3odatmd.F90:553
constants::tpi
real, parameter tpi
TPI 2*Pi.
Definition: constants.F90:72
w3servmd::strace
subroutine strace(IENT, SNAME)
Definition: w3servmd.F90:148
w3gdatmd::xfr
real, pointer xfr
Definition: w3gdatmd.F90:1232
w3odatmd::dimp
integer, parameter dimp
Definition: w3odatmd.F90:325
w3gdatmd::fte
real, pointer fte
Definition: w3gdatmd.F90:1232
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
w3odatmd::ptfcut
real, pointer ptfcut
Definition: w3odatmd.F90:556
w3partmd::ptnghb
subroutine ptnghb
Nearest neighbour calculation.
Definition: w3partmd.F90:632
w3dispmd::wavnu1
subroutine wavnu1(SI, H, K, CG)
Definition: w3dispmd.F90:85
w3partmd::ptmean
subroutine ptmean(NPI, IMO, ZP, DEPTH, UABS, UDIR, WN, NPO, XP, DIMXP, PMAP)
Compute mean parameters per partition.
Definition: w3partmd.F90:1178
w3odatmd::ihmax
integer, pointer ihmax
Definition: w3odatmd.F90:551
w3partmd::w3part
subroutine w3part(SPEC, UABS, UDIR, DEPTH, WN, NP, XP, DIMXP)
Interface to watershed partitioning routines.
Definition: w3partmd.F90:139
constants::undef
real undef
UNDEF Value for undefined variable in output.
Definition: constants.F90:84
w3dispmd
Definition: w3dispmd.F90:3
w3odatmd::wscut
real, pointer wscut
Definition: w3odatmd.F90:553