WAVEWATCH III  beta 0.0.1
w3snl5md.F90
Go to the documentation of this file.
1 
9 
10 #include "w3macros.h"
11 !/ ------------------------------------------------------------------- /
25 MODULE w3snl5md
26  !/
27  !/ +-----------------------------------+
28  !/ | WAVEWATCH III NOAA/NCEP |
29  !/ | O. Gramstad |
30  !/ | Q. Liu |
31  !/ | FORTRAN 90 |
32  !/ | Last update : 07-Jun-2021 |
33  !/ +-----------------------------------+
34  !/
35  !/ 24-Sep-2013 : Origination. ( version 3.14 )
36  !/ 24-Sep-2013 : GKE for the regular wavenumbergrid ( O. Gramstad )
37  !/ (interpolation required)
38  !/ 02-Dec-2013 : GKE for WW3 logarithmic freq. grid ( O. Gramstad )
39  !/ (single grid point)
40  !/ 27-Feb-2019 : GKE for 2D applications. ( version 7.13 )
41  !/ ( Q. Liu )
42  !/ 07-06-2021 : Merge into WW3 Github ( version 7.13 )
43  !/ ( Q. Liu )
44  !/
45  ! 1. Purpose :
46  ! Interface module for GKE (resonant & quasi-resonant four-wave
47  ! interactions)
48  !
49  ! 2. Variables and types :
50  !
51  ! 3. Subroutines and functions :
52  !
53  ! Name Type Scope Description
54  ! -------------------------------------------------------------------
55  ! W3SNL5 Subr. Public Interface to gkeModule
56  ! INSNL5 Subr. Public Initialization routine
57  ! CALC_WBTv2 Subr. Private Calc. dominant wave breaking prob.
58  ! INPOUT Subr. Private Point output
59  ! -------------------------------------------------------------------
60  !
61  ! 4. Future work: Dnl
62  !/
63  !/ ------------------------------------------------------------------- /
64  IMPLICIT NONE
65  !/
66  ! Subrs.
67  PUBLIC :: w3snl5, insnl5
68  PRIVATE :: calc_wbtv2, inpout
69  ! Vars.
70  PRIVATE :: nsel, psea, pnms
71  !/ ------------------------------------------------------------------- /
72  ! Parameter list
73  INTEGER :: NSEL
74  INTEGER, ALLOCATABLE, SAVE :: PSEA(:)
75  CHARACTER(LEN=10), ALLOCATABLE, SAVE :: PNMS(:)
76  !
77 CONTAINS
78  !/ ------------------------------------------------------------------- /
98  SUBROUTINE w3snl5(A, CG, WN, FMEAN, T1ABS, U10, UDIR, JSEA, &
99  S, D, KURT)
100  !/
101  !/ +-----------------------------------+
102  !/ | WAVEWATCH III NOAA/NCEP |
103  !/ | O. Gramstad |
104  !/ | Q. Liu |
105  !/ | FORTRAN 90 |
106  !/ | Last update : 24-Apr-2019 |
107  !/ +-----------------------------------+
108  !/
109  !/ 24-Sep-2013 : Origination. ( version 3.14 )
110  !/ 24-Sep-2013 : GKE for resonant & quasi-resonant four-wave
111  !/ interactions ( O. Gramstad )
112  !/ 27-Feb-2019 : Full implementation of GKE ( version 7.13 )
113  !/ ( Q. Liu )
114  !/ 21-Apr-2019 : Phase mixing option ( version 7.13 )
115  !/ ( Q. Liu )
116  !/ 24-Apr-2019 : Phase mixing option (b_T) ( version 7.13 )
117  !/ ( Q. Liu )
118  !/ 02-May-2019 : Organize screen output & disable binary output
119  !/ ( version 7.13 )
120  !/ ( Q. Liu )
121  !/
122  !/
123  ! 1. Purpose :
124  !
125  ! Interface to CalcQRSNL subr. of the GKE module. Please refer to
126  ! -------------
127  ! gkeModule.f90 for further details.
128  ! -------------
129  !
130  ! ◆ Different times used in this module
131  !
132  ! |----o---------o----o--|-|--o-----o------o-----o------o----> (t)
133  ! ^ ^ ^ ^ ^ T1ABS (absol. current time step)¹
134  ! | | | |
135  ! | | | v t0 (relat. time, previous time step)
136  ! | |<------->|
137  ! | | PM_IVAL (phase mixing interval, relat. time)
138  ! | |
139  ! | v PM_PREV (phase mixing, appear quasi-periodically)
140  ! | (relat. time)
141  ! |
142  ! v TBEG (absol. begining time, defined by ww3_shel.inp)
143  !
144  ! ¹ Because of using the dynamic integration scheme, T1ABS
145  ! is related to, but not the same as, TIME in w3wdatmd.ftn
146  ! 2. Method :
147  !
148  ! 3. Parameters :
149  !
150  ! 4. Subroutines used :
151  !
152  ! Name Type Module Description
153  ! ----------------------------------------------------------------
154  ! STRACE Subr. W3SERVMD Subroutine tracing.
155  ! ----------------------------------------------------------------
156  !
157  ! 5. Called by :
158  !
159  ! Name Type Module Description
160  ! ----------------------------------------------------------------
161  ! W3SRCE Subr. W3SRCEMD Source term integration.
162  ! W3EXPO Subr. N/A Point output post-processor.
163  ! GXEXPO Subr. N/A GrADS point output post-processor.
164  ! ----------------------------------------------------------------
165  !
166  ! 6. Error messages :
167  !
168  ! None.
169  !
170  ! 7. Remarks :
171  !
172  ! 8. Structure :
173  !
174  ! See source code.
175  !
176  ! 9. Switches :
177  !
178  ! !/S Enable subroutine tracing.
179  !
180  ! 10. Source code :
181  !
182  !/ ------------------------------------------------------------------- /
183  USE constants, ONLY: grav, tpi
184  USE w3gkemd, ONLY: calcqrsnl, qr_depth
185  USE w3gdatmd, ONLY: nk, nth, nspec, sig, th, &
186  gtype, rlgtype, clgtype, &
188  USE w3wdatmd, ONLY: qi5tbeg, qr5tim0, qr5cvk0, qc5int0, &
189  qr5tmix
190  USE w3odatmd, ONLY: flout, nopts, tosnl5, tolast, &
192  USE w3parall, ONLY: init_get_isea
193  USE w3timemd, ONLY: dsec21
194  USE w3servmd, ONLY: extcde
195 #ifdef W3_S
196  USE w3servmd, ONLY: strace
197 #endif
198  !/
199  IMPLICIT NONE
200  !/
201  !/ ------------------------------------------------------------------- /
202  !/ Parameter list
203  !/
204  REAL, INTENT(IN) :: a(nth, nk) ! N(θ, k)
205  REAL, INTENT(IN) :: cg(nk) ! Cg(k)
206  REAL, INTENT(IN) :: wn(nk) ! WN(k)
207  REAL, INTENT(IN) :: fmean ! 1/T_{0, -1}
208  INTEGER, INTENT(IN) :: t1abs(2) ! Absol. t1
209  REAL, INTENT(IN) :: u10 ! Wind velocity
210  REAL, INTENT(IN) :: udir ! φ (in rad)
211  INTEGER, INTENT(IN) :: jsea ! Local sea point count
212  REAL, INTENT(OUT) :: s(nth,nk), & ! Snl
213  d(nth,nk), & ! Dnl
214  kurt ! Kurtosis
215 
216  !/ ------------------------------------------------------------------- /
217  !/ Local parameters
218  REAL, PARAMETER :: btlow = 10., bthgh = 500.
219  REAL :: t0rel, t1rel, tdel1, tdel2
220  REAL :: cvk1(nspec), snl(nspec), dnl(nspec)
221  REAL :: cvk0(nspec)
222  COMPLEX :: inpqr0(qi5nnz)
223  INTEGER :: ik, ith, ispec, isea, jloc
224  INTEGER, ALLOCATABLE :: pdiff(:)
225  LOGICAL, SAVE :: fstout = .true.
226  REAL :: factor(nk), a2(nk, nth), s2(nk, nth)
227  REAL :: pm_prev, pm_ival, pm_delt
228  REAL :: wbt, btinv
229  INTEGER :: iunt
230 #ifdef W3_S
231  INTEGER, SAVE :: ient = 0
232 #endif
233 
234  !/
235  !/ ------------------------------------------------------------------- /
236  !/
237 #ifdef W3_S
238  CALL strace (ient, 'W3SNL5')
239 #endif
240  !
241  !/ ------------------------------------------------------------------- /
242  ! Read in wave info. @ the previous time step t0
243  ! Array initialization is done in w3wdat/w3setw (called by w3initmd)
244  t0rel = qr5tim0(jsea) ! t0 (nsea)
245  cvk0 = qr5cvk0(:, jsea) ! Cvk (ns, nsea) @ t0
246  inpqr0 = qc5int0(:, jsea) ! Inpqr (nnz, nsea) @ t0
247  !
248  ! Calc. Relative time for T1ABS (QI5TBEG as the reference)
249  t1rel = dsec21(qi5tbeg, t1abs) ! in second
250  !
251  ! W3WAVEMD: IF ( IT.EQ.0 ) DTG = 1 → T1REL = -1 (the first step of
252  ! integration; TIME = TCALC/TOFRST, DTG = 0 → 1, QI5TBEG = TIME - 1)
253  IF(t1rel < 0.) t1rel = 0.
254  !
255  ! Three options for phase mixing
256  IF (qi5pmx .EQ. 0) THEN
257  ! 1) 0: no phase mixing
258 #ifdef W3_TS
259  IF (iaproc .EQ. napout) &
260  WRITE(screen, '(A, 2(I10.8, I7.6), E12.3)') &
261  " ⊚ → [WW3 SNL₅] QI5TBEG, T1ABS, T1REL:", &
262  qi5tbeg, t1abs, t1rel
263 #endif
264  ELSE
265 #ifdef W3_TS
266  IF (iaproc .EQ. napout) &
267  WRITE(screen, '(A, 2(I10.8, I7.6), E12.3)', advance='no') &
268  " ⊚ → [WW3 SNL₅] QI5TBEG, T1ABS, T1REL, T1REL[P]:", &
269  qi5tbeg, t1abs, t1rel
270 #endif
271  !
272  ! Calc. Phase mixing interval
273  IF (qi5pmx .GT. 0) THEN
274  ! 2) N: mix phase by every N characteristic wave periods
275  IF (abs(fmean) < 1e-7) THEN ! FMEAN may be 0.
276  pm_ival = real(qi5pmx) * 1. ! then, assume FMEAN = 1.
277  ELSE
278  pm_ival = real(qi5pmx) * (1. / fmean)
279  END IF
280  !
281  ELSE IF (qi5pmx .LT. 0) THEN
282  ! 3) < 0: mix phase based on dominant wave breaking probability bT
283  ! Calc bT
284  wbt = calc_wbtv2(a, cg, wn, qr5dpt, u10, udir) ! [0, 1.]
285  ! Mix phase by every 1/bT periods
286  ! Odin used bT < 1/15. (0.066) → BTLOW = 15 and PM_IVAL > 150 s
287  btinv = max(btlow, min(1./max(1e-6, wbt), bthgh))
288  IF (abs(fmean) < 1e-7) THEN ! FMEAN may be 0.
289  pm_ival = btinv * 1. ! then, assume FMEAN = 1.
290  ELSE
291  pm_ival = btinv * (1. / fmean)
292  END IF
293  END IF
294  !
295  ! Previous phase mixing time (relat. to TBEG)
296  ! QR5TMIX has already been initialized in w3wdatmd as zero.
297  pm_prev = qr5tmix(jsea)
298  ! Update t1 if necessary
299  pm_delt = t1rel - pm_prev
300  IF (pm_delt .GE. pm_ival) THEN
301  qr5tmix(jsea) = t1rel ! relat. to TBEG → PM_PREV
302  t1rel = 0.
303  ELSE
304  t1rel = pm_delt
305  END IF
306 #ifdef W3_TS
307  IF (iaproc .EQ. napout) THEN
308  WRITE(screen, '(F9.1)') t1rel
309  IF (qi5pmx .LT. 0 ) WRITE(screen, '(A, F6.3)') '↔ bT: ', wbt
310  ENDIF
311 #endif
312  END IF
313  !
314  ! Calc. Cvk1 from A (C(\bm{k}) = g N(k, θ) / k)
315  DO ik = 1, nk
316  DO ith = 1, nth
317  ispec = ith + (ik-1) * nth
318  cvk1(ispec) = a(ith, ik) / wn(ik) * grav
319  END DO
320  END DO
321  !
322  ! CalcQRSNL(nk, nth, sig, th, t0, t1, Cvk0, Cvk1, Inpqr0, Snl, Dnl, Kurt)
323  ! Depth is needed for reading in kernels at the first run
324  qr_depth = qr5dpt
325  CALL calcqrsnl(nk, nth, sig(1:nk), th, &
326  t0rel, t1rel, cvk0, cvk1, &
327  inpqr0, snl, dnl, kurt)
328  !
329  ! Tranform back from C(k) to N(k)
330  ! TODO D(ITH, IK) (See NL2 for reference)
331  d = 0.0
332  DO ik = 1, nk
333  DO ith = 1, nth
334  ispec = ith + (ik-1) * nth
335  s(ith, ik) = snl(ispec) * wn(ik) / grav
336  END DO
337  END DO
338  !
339  ! Store wave info. @ t1 → t0
340  qr5tim0(jsea) = t0rel
341  qr5cvk0(:, jsea) = cvk0
342  qc5int0(:, jsea) = inpqr0
343  !
344  ! Point output (Snl term)
345  ! First ouput action (Find nearest grid points & generate binary files)
346  IF (fstout) THEN
347  CALL inpout
348  fstout = .false.
349  IF (iaproc .EQ. napout) THEN
350  WRITE(screen, *)
351  WRITE(screen, '(A)') &
352  ' ⊚ → [WW3 SNL₅] Point ouptut initialization'
353  WRITE(screen, '(A, I4)') &
354  ' ⊚ → [WW3 SNL₅] # of valid points: ', nsel
355  WRITE(screen, *)
356  END IF
357  END IF
358  !
359  ! Calc FACTOR used for Jacobian tranformation from N(k, θ) to E(f, θ)
360  factor = tpi / cg * sig(1:nk)
361  !
362  ! Regular grid & curvilinear grid
363  IF ( ((gtype .EQ. rlgtype) .OR. (gtype .EQ. clgtype)) &
364  .AND. flout(2) .AND. nsel .GT. 0) THEN
365  tdel1 = dsec21(t1abs, tosnl5)
366  tdel2 = dsec21(t1abs, tolast(:, 2)) ! not really useful since
367  ! TOSNL5 can never catch
368  ! TOLAST
369  ! Output time
370  IF (abs(tdel1) < 1e-6 .OR. abs(tdel2) < 1e-6) THEN
371  ! JSEA→ ISEA
372  CALL init_get_isea(isea, jsea)
373  ! Find the loc of ISEA at PSEA (nearest sea grid point)
374  IF (ALLOCATED(pdiff)) DEALLOCATE(pdiff); ALLOCATE(pdiff(nsel))
375  pdiff = abs(psea(1:nsel) - isea)
376  IF (any(pdiff .EQ. 0)) THEN
377  jloc = minloc(pdiff, 1)
378 #ifdef W3_TS
379  IF (iaproc .EQ. napout) &
380  WRITE(screen, '(3A, I10.8, I7.6)') &
381  '✓ Point output for |', pnms(jloc), '| @', t1abs
382 #endif
383 
384  ! N(θ, k) → F(f, θ) & S(θ, k) → S(f, θ)
385  DO ith = 1, nth
386  a2(:, ith) = a(ith, :) * factor
387  s2(:, ith) = s(ith, :) * factor
388  END DO
389  ! NaN Check
390  IF (hasnan(nk, nth, a2) .OR. hasnan(nk, nth, s2)) THEN
391  IF (iaproc .EQ. napout) &
392  WRITE(screen, *) '★★★ Warning: find NaN in E(f, θ) &
393  & or Snl(f, θ) !'
394  END IF
395  ! unit no.
396  iunt = 500 + jloc
397  ! Store data (binary)
398  ! OPEN(IUNT, FILE='NL5_'//trim(PNMS(JLOC))//'_src.bin', &
399  ! form='unformatted', convert=file_endian, ACCESS='stream', &
400  ! STATUS='old', POSITION='append', ACTION='write')
401  ! WRITE(IUNT) T1ABS
402  ! WRITE(IUNT) KURT
403  ! WRITE(IUNT) A2
404  ! WRITE(IUNT) S2
405  ! CLOSE(IUNT)
406  ! Store data (ascii)
407  OPEN(iunt, file='NL5_'//trim(pnms(jloc))//'_src.dat', &
408  form='formatted', status='old', &
409  position='append', action='write')
410  WRITE(iunt, '(I10.8, I7.6)') t1abs
411  WRITE(iunt, '(ES11.3)') kurt
412  WRITE(iunt, 113) a2
413  WRITE(iunt, 113) s2
414  CLOSE(iunt)
415  !
416  END IF
417  END IF
418  END IF
419  ! Format
420 113 FORMAT ((10es11.3))
421  !/
422  !/ End of W3SNL5 ----------------------------------------------------- /
423  !/
424  END SUBROUTINE w3snl5
425  !/ ------------------------------------------------------------------- /
426 
434  SUBROUTINE insnl5
435  !/
436  !/ +-----------------------------------+
437  !/ | WAVEWATCH III NOAA/NCEP |
438  !/ | Q. Liu |
439  !/ | FORTRAN 90 |
440  !/ | Last update : 27-Feb-2019 |
441  !/ +-----------------------------------+
442  !/
443  !/ 27-Feb-2019 : Origination. ( version 7.13 )
444  !/ ( Q. Liu )
445  !/
446  ! 1. Purpose :
447  !
448  ! Initialization for the GKE module (Prepare wavenumber grid & kernel
449  ! coefficients)
450  !
451  ! 2. Method :
452  ! See subrs. PrepKGrid & PrepKernelIO of gkeModule.f90
453  !
454  ! 3. Parameters :
455  !
456  ! 4. Subroutines used :
457  ! ----------------------------------------------------------------
458  ! Name Type Module Description
459  ! ----------------------------------------------------------------
460  ! STRACE Subr. W3SERVMD Subroutine tracing.
461  ! PrepKernelIO Subr. gkeModule KGrid & Kernel Coeff.
462  !
463  ! 5. Called by :
464  ! ----------------------------------------------------------------
465  ! Name Type Module Description
466  ! ----------------------------------------------------------------
467  ! W3IOGR Subr. W3IOGRMD Model definition file management.
468  ! ----------------------------------------------------------------
469  !
470  ! 6. Error messages :
471  !
472  ! 7. Remarks :
473  !
474  ! 8. Structure :
475  !
476  ! See source code.
477  !
478  ! 9. Switches :
479  !
480  ! !/S Enable subroutine tracing.
481  !
482  ! 10. Source code :
483  !
484  !/ ------------------------------------------------------------------- /
485  USE w3gkemd, ONLY: qr_depth, qr_oml, qi_disc, qi_kev, qi_nnz, &
487  USE w3gdatmd, ONLY: nk, nth, sig, th, &
489  qi5ipl, qi5pmx
490  USE w3odatmd, ONLY: iaproc, napout, screen
491  USE w3servmd, ONLY: extcde
492 #ifdef W3_S
493  USE w3servmd, ONLY: strace
494 #endif
495  !/
496  IMPLICIT NONE
497  !/
498  !/ ------------------------------------------------------------------- /
499  !/ Parameter list
500  !/
501  !/
502  !/ ------------------------------------------------------------------- /
503  !/ Local parameters
504  !/
505 #ifdef W3_S
506  INTEGER, SAVE :: ient = 0
507 #endif
508  !/
509  !/ ------------------------------------------------------------------- /
510  !/
511 #ifdef W3_S
512  CALL strace (ient, 'INSNL5')
513 #endif
514  !
515  ! Set important parameters for GKE module (QR[I]5DPT/OML/DIS/KEV are
516  ! defined in ww3_grid.inp, and QI5NNZ is not known yet)
517  qr_depth = qr5dpt
518  qr_oml = qr5oml
519  qi_disc = qi5dis
520  qi_kev = qi5kev
522  !
523  ! Prepare (kx, ky) grid & kernel coefficients
524  CALL prepkernelio(nk, nth, sig(1:nk), th, 'WRITE')
525  !
526  ! Store qi_NNZ to QI5NNZ (which will be used to initialize the
527  ! QC5INT0 array)
528  qi5nnz = qi_nnz
529  !
530  ! Q. Liu (TODO)
531  IF (iaproc .EQ. napout) THEN
532  WRITE(screen, '(A, F6.1)') " ⊚ → [WW3 SNL₅]: water depth : ", qr_depth
533  WRITE(screen, '(A, F7.2)') " ⊚ → [WW3 SNL₅]: ω λc cut off : ", qr_oml
534  WRITE(screen, '(A, I4)' ) " ⊚ → [WW3 SNL₅]: Discretiza. : ", qi_disc
535  WRITE(screen, '(A, I4)' ) " ⊚ → [WW3 SNL₅]: GKE version : ", qi_kev
536  WRITE(screen, '(A, I12)' ) " ⊚ → [WW3 SNL₅]: # of quartets : ", qi_nnz
537  WRITE(screen, '(A, I4)' ) " ⊚ → [WW3 SNL₅]: interpol. : ", qi_interp
538  WRITE(screen, '(A, I4)' ) " ⊚ → [WW3 SNL₅]: phase mixing : ", qi5pmx
539  END IF
540  !/
541  !/ End of INSNL5 ----------------------------------------------------- /
542  !/
543  END SUBROUTINE insnl5
544  !/ ------------------------------------------------------------------- /
562  FUNCTION calc_wbtv2 (A, CG, WN, DPT, U10, UDIR)
563  !/
564  !/ +-----------------------------------+
565  !/ | WAVEWATCH III NOAA/NCEP |
566  !/ | Q. Liu |
567  !/ | FORTRAN 90 |
568  !/ | Last update : 24-Apr-2019 |
569  !/ +-----------------------------------+
570  !/
571  !/ 24-Aug-2018 : Origination. (w3iogomd.ftn) ( version 6.06 )
572  !/ Used for output parameter b_T ( Q. Liu )
573  !/
574  !/ 24-Apr-2019 : Simplified for NL5 ( version 7.13 )
575  !/ ( Q. Liu )
576  !/
577  ! 1. Purpose :
578  !
579  ! Estimate the dominant wave breaking probability b_T based on
580  ! the empirical parameterization proposed by Babanin et al. (2001).
581  ! From their Fig. 12, we have
582  !
583  ! b_T = 85.1 * [(εp - 0.055) * (1 + H_s/d)]^2.33,
584  !
585  ! where ε is the significant steepness of the spectral peak, H_s is
586  ! the significant wave height, d is the water depth.
587  !
588  ! For more details, please see
589  ! Banner et al. 2000: JPO, 30, 3145 - 3160.
590  ! Babanin et al. 2001: JGR, 106(C6), 11569 - 11676.
591  !
592  ! See subr. CALC_WBT in w3iogomd.ftn for more details.
593  !
594  !/ ------------------------------------------------------------------- /
595  USE w3dispmd, ONLY: wavnu1
596  USE w3gdatmd, ONLY: nk, nth, sig, esin, ecos, dth, dsii
597 #ifdef W3_S
598  USE w3servmd, ONLY: strace
599 #endif
600  !
601  IMPLICIT NONE
602  !
603  !/ ------------------------------------------------------------------- /
604  !/ Parameter list
605  !/
606  REAL, INTENT(IN) :: a(nth, nk) ! N(θ, k)
607  REAL, INTENT(IN) :: cg(nk) ! Cg(k)
608  REAL, INTENT(IN) :: wn(nk) ! WN(k)
609  REAL, INTENT(IN) :: dpt ! water depth
610  REAL, INTENT(IN) :: u10 ! wind velocity
611  REAL, INTENT(IN) :: udir ! wind dirc. (φ in rad)
612  REAL :: calc_wbtv2
613  !/
614  !/ ------------------------------------------------------------------- /
615  !/ Local parameters
616  !/
617 #ifdef W3_S
618  INTEGER, SAVE :: ient = 0
619 #endif
620  !
621  REAL, PARAMETER :: beta = 1.2
622  !
623  INTEGER :: ik, ith
624  REAL :: sinu, cosu, tc, tforce
625  REAL :: esig(nk) ! E(σ)
626  REAL :: factor, et, hs, etp, hsp, sigp, kp, &
627  cgp, wstp, twbt
628  !/
629  !/ ------------------------------------------------------------------- /
630  !/
631 #ifdef W3_S
632  CALL strace (ient, 'CALC_WBTv2')
633 #endif
634  !
635  ! Wind info. is required to select wind sea partition from the wave
636  ! spectrum.
637  !
638  ! Following Janssen et al. (1989) and Bidlot (2001), spectral components
639  ! are considered to be subject to local wind forcing when
640  !
641  ! c / [U cos(θ - φ)] < β,
642  !
643  ! where c is the phase velocity c = σ/k, φ is the wind direction, U is
644  ! the wind speed U10, (sometimes approximated by U10≅ 28 * ust), β is
645  ! the constant forcing parameter with β∈ [1.0, 2.0]. By default, we use
646  ! β = 1.2 (Bidlot 2001).
647  !
648  sinu = sin(udir) ! sinφ
649  cosu = cos(udir) ! cosφ
650  !
651  esig = 0. ! E(σ)
652  et = 0. ! ΣE(σ)δσ
653  etp = 0. ! ΣE(σ)δσ at peak only
654  !
655  DO ik = 1, nk
656  tc = sig(ik) / wn(ik) ! phase velocity c=σ/k
657  factor = sig(ik) / cg(ik) ! σ / cg
658  factor = factor * dth ! σ / cg * δθ
659  !
660  DO ith = 1, nth
661  tforce = tc - u10 * (cosu*ecos(ith)+sinu*esin(ith)) &
662  * beta
663 
664  IF (tforce .LT. 0.) THEN ! wind sea component
665  esig(ik) = esig(ik) + a(ith, ik) * factor
666  ENDIF
667  ENDDO ! ITH
668  !
669  ENDDO ! IK
670  !
671  ! ESIG is E(σ) of the wind sea after filtration of any background swell.
672  ! Now we need to get Hs & σp for the wind sea spectrum.
673  ! Unlike w3iogomd.ftn, the tail energy is not added here.
674  et = sum(esig * dsii)
675  hs = 4. * sqrt(max(0., et))
676  !
677  ! Get σp from E(σ)
678  ! FPOPT = 0 in w3iogomd.ftn: fp defined by Young (1999, p. 239)
679  sigp = sum(esig**4. * sig(1:nk) * dsii) / &
680  max(1e-10, sum(esig**4. * dsii))
681  IF (abs(sigp) < 1e-7) sigp = sig(nk) ! σp = 0
682  !
683  ! kp from σp (linear dispersion)
684  CALL wavnu1 (sigp, dpt, kp, cgp)
685  !
686  ! { /1.3σp }1/2
687  ! peak wave height Hp = 4 { | E(σ) dσ }
688  ! { /0.7σp }
689  !
690  DO ik = 1, nk
691  IF ( (sig(ik) >= 0.7 * sigp) .AND. &
692  (sig(ik) <= 1.3 * sigp) ) THEN
693  etp = etp + esig(ik) * dsii(ik)
694  ENDIF
695  ENDDO ! IK
696  hsp = 4. * sqrt(max(0., etp))
697  !
698  ! significant steepness of the peak region εp
699  !
700  wstp = 0.5 * kp * hsp
701  !
702  ! Dominant wave breaking b_T
703  !
704  twbt = 85.1 * (max(0.0, wstp - 0.055) * (1 + hs/dpt))**2.33
705  twbt = min(1.0, twbt)
706  !
707  calc_wbtv2 = twbt
708 
709  RETURN
710  !/
711  !/ End of CALC_WBTv2 ------------------------------------------------ /
712  !/
713  END FUNCTION calc_wbtv2
714 
715  !/ ------------------------------------------------------------------- /
722  SUBROUTINE inpout
723  !/
724  !/ +-----------------------------------+
725  !/ | WAVEWATCH III NOAA/NCEP |
726  !/ | Q. Liu |
727  !/ | FORTRAN 90 |
728  !/ | Last update : 25-Mar-2019 |
729  !/ +-----------------------------------+
730  !/
731  !/ 24-Mar-2019 : Origination. ( version 7.13 )
732  !/ ( Q. Liu )
733  !/ 27-Apr-2019 : Add the ascii option ( Q. Liu )
734  !/
735  ! 1. Purpose :
736  !
737  ! Initialization for point output (Snl) [see also W3IOPP of w3iopomd]
738  !
739  ! 2. Method :
740  !
741  ! 3. Parameters :
742  !
743  ! 4. Subroutines used :
744  !
745  ! 5. Called by :
746  ! ----------------------------------------------------------------
747  ! Name Type Module Description
748  ! ----------------------------------------------------------------
749  ! W3SNL5 Subr. W3SNL5MD S_{nl} GKE
750  ! ----------------------------------------------------------------
751  !
752  ! 6. Error messages :
753  !
754  ! 7. Remarks :
755  !
756  ! 8. Structure :
757  !
758  ! See source code.
759  !
760  ! 9. Switches :
761  !
762  ! !/S Enable subroutine tracing.
763  !
764  ! 10. Source code :
765  !
766  !/
767  !/ ------------------------------------------------------------------- /
768  USE constants, ONLY: tpi
769  USE w3gdatmd, ONLY: nk, nth, sig, th, qr5dpt, &
771  USE w3odatmd, ONLY: nopts, ptnme, ptloc, iptint, &
773  USE w3servmd, ONLY: dist_sphere
774 #ifdef W3_S
775  USE w3servmd, ONLY: strace
776 #endif
777  !/
778  IMPLICIT NONE
779  !/ ------------------------------------------------------------------- /
780  !/
781  INTEGER :: ixs(4), iys(4), ix, iy, ipt, is, &
782  jloc, jx, jy, isea, smap(4), iunt
783  REAL :: plon, plat, xlon, ylat, dist(4)
784  !/ ------------------------------------------------------------------- /
785  !/
786  ! Initialize arrays
787  IF (ALLOCATED(psea)) DEALLOCATE(psea); ALLOCATE(psea(nopts))
788  IF (ALLOCATED(pnms)) DEALLOCATE(pnms); ALLOCATE(pnms(nopts))
789  !
790  nsel = 0
791  psea(:) = 0
792  pnms(:) = 'null'
793  dist(:) = -999.
794  !
795  DO ipt = 1, nopts
796  ! Get lon & lat of this output point
797  plon = ptloc(1, ipt)
798  plat = ptloc(2, ipt)
799  ! Get four indices surrounding the output point
800  ixs(:) = iptint(1, :, ipt)
801  iys(:) = iptint(2, :, ipt)
802  DO is = 1, 4
803  ! Get lon & lat of four corner points
804  ix = ixs(is)
805  iy = iys(is)
806  xlon = xgrd(iy, ix)
807  ylat = ygrd(iy, ix)
808  ! Grid point status
809  IF (mapsta(iy, ix) .EQ. 0) cycle
810  ! Calc dist.
811  IF (flagll) THEN
812  dist(is) = dist_sphere(plon, plat, xlon, ylat)
813  ELSE
814  dist(is) = sqrt((plon - xlon)**2. + (plat - ylat)**2.)
815  END IF
816  END DO
817  ! A sea point filter: there must be at least one sea grid point around
818  ! the selected output location. [maybe not necessary since IOPP already
819  ! checked this criterion]
820  !
821  IF (all(dist < 0.)) cycle
822  ! Find the nearest sea grid point
823  jloc = minloc(dist, 1, dist >= 0.)
824  jx = ixs(jloc)
825  jy = iys(jloc)
826  isea = mapfs(jy, jx)
827  ! Basic check
828 #ifdef W3_TS
829  IF (flagll) THEN
830  IF (iaproc .EQ. napout) &
831  WRITE(screen, "(A, 2F10.3, A, 2F10.3, A)") &
832  '✗ (PLON, PLAT): (', plon, plat, ') | (XGRD, YGRD): (',&
833  xgrd(jy, jx), ygrd(jy, jx), ')'
834  ELSE
835  IF (iaproc .EQ. napout) &
836  WRITE(screen, "(A, 2E10.3, A, 2E10.3, A)") &
837  '✗ (PLON, PLAT): (', plon, plat, ') | (XGRD, YGRD): (',&
838  xgrd(jy, jx), ygrd(jy, jx), ')'
839  END IF
840 #endif
841  ! Store ISEA
842  nsel = nsel + 1
843  psea(nsel) = isea
844  pnms(nsel) = ptnme(ipt)
845  ! Store Unit (Open & Write Binary files)
846  iunt = 500 + nsel
847  ! Binary
848  ! OPEN(IUNT, FILE='NL5_'//trim(PNMS(NSEL))//'_src.bin', &
849  ! form='unformatted', convert=file_endian, ACCESS='stream', STATUS='replace', &
850  ! ACTION='write')
851  ! WRITE(IUNT) PLON, PLAT
852  ! WRITE(IUNT) XGRD(JY, JX), YGRD(JY, JX)
853  ! WRITE(IUNT) QR5DPT
854  ! WRITE(IUNT) NK, NTH
855  ! WRITE(IUNT) SIG(1:NK)/TPI ! f, θ
856  ! WRITE(IUNT) TH
857  ! CLOSE(IUNT)
858  ! Ascii
859  OPEN(iunt, file='NL5_'//trim(pnms(nsel))//'_src.dat', &
860  form='formatted', status='replace', action='write')
861  WRITE(iunt, '(2ES11.3)') plon, plat
862  WRITE(iunt, '(ES11.3)' ) qr5dpt
863  WRITE(iunt, '(2I5)') nk, nth
864  WRITE(iunt, 113) sig(1:nk)/tpi ! f, θ
865  WRITE(iunt, 113) th
866  CLOSE(iunt)
867  !
868  END DO
869  ! Format
870 113 FORMAT ((10es11.3))
871  !
872  END SUBROUTINE inpout
873  !/ ------------------------------------------------------------------- /
874 
886  FUNCTION hasnan(NK, NTH, ARR2D)
887  !/
888  !/ +-----------------------------------+
889  !/ | WAVEWATCH III NOAA/NCEP |
890  !/ | Q. Liu |
891  !/ | FORTRAN 90 |
892  !/ | Last update : 25-Apr-2019 |
893  !/ +-----------------------------------+
894  !/
895  !/ 24-Apr-2019 : Origination. ( version 7.13 )
896  !/ ( Q. Liu )
897  !/
898  ! 1. Purpose :
899  ! Check if the 2D array `ARR2D` contains NaN (see also w3gsrumd.ftn)
900  !/
901  IMPLICIT NONE
902  !
903  INTEGER, INTENT(IN) :: nk, nth ! # OF FREQ. & DIRC.
904  REAL, INTENT(IN) :: arr2d(nk, nth)
905  LOGICAL :: hasnan
906  !/
907  hasnan = .true.
908  !
909  IF ( all(arr2d .GE. -huge(arr2d(1, 1))) .AND. &
910  all(arr2d .LE. huge(arr2d(1, 1))) ) THEN
911  hasnan = .false.
912  END IF
913  !
914  RETURN
915  !/
916  END FUNCTION hasnan
917  !/ ------------------------------------------------------------------- /
918  !/
919  !/ End of module W3SNL5MD -------------------------------------------- /
920  !/
921 END MODULE w3snl5md
922 !/ ------------------------------------------------------------------- /
w3gdatmd::qr5oml
real, pointer qr5oml
Definition: w3gdatmd.F90:1371
w3gdatmd::nk
integer, pointer nk
Definition: w3gdatmd.F90:1230
w3wdatmd::qr5tim0
real, dimension(:), pointer qr5tim0
Definition: w3wdatmd.F90:180
w3timemd::dsec21
real function dsec21(TIME1, TIME2)
Definition: w3timemd.F90:333
w3odatmd::iptint
integer, dimension(:,:,:), pointer iptint
Definition: w3odatmd.F90:488
w3gdatmd::dth
real, pointer dth
Definition: w3gdatmd.F90:1232
w3odatmd::tosnl5
integer, dimension(:), pointer tosnl5
Definition: w3odatmd.F90:462
w3gdatmd::ygrd
double precision, dimension(:,:), pointer ygrd
Definition: w3gdatmd.F90:1205
w3gdatmd::qi5ipl
integer, pointer qi5ipl
Definition: w3gdatmd.F90:1372
w3gdatmd::nspec
integer, pointer nspec
Definition: w3gdatmd.F90:1230
w3wdatmd
Define data structures to set up wave model dynamic data for several models simultaneously.
Definition: w3wdatmd.F90:18
w3odatmd::nopts
integer, pointer nopts
Definition: w3odatmd.F90:484
w3gdatmd::rlgtype
integer, parameter rlgtype
Definition: w3gdatmd.F90:624
w3gdatmd::sig
real, dimension(:), pointer sig
Definition: w3gdatmd.F90:1234
w3gdatmd::xgrd
double precision, dimension(:,:), pointer xgrd
Definition: w3gdatmd.F90:1205
w3wdatmd::qc5int0
complex, dimension(:, :), pointer qc5int0
Definition: w3wdatmd.F90:181
w3gkemd::qr_depth
real, public qr_depth
Definition: w3gkemd.F90:165
w3odatmd::iaproc
integer, pointer iaproc
Definition: w3odatmd.F90:457
w3gdatmd::ecos
real, dimension(:), pointer ecos
Definition: w3gdatmd.F90:1234
w3gdatmd::th
real, dimension(:), pointer th
Definition: w3gdatmd.F90:1234
w3odatmd::ptloc
real, dimension(:,:), pointer ptloc
Definition: w3odatmd.F90:492
w3gdatmd::mapfs
integer, dimension(:,:), pointer mapfs
Definition: w3gdatmd.F90:1163
w3gdatmd::esin
real, dimension(:), pointer esin
Definition: w3gdatmd.F90:1234
w3wdatmd::qr5tmix
real, dimension(:), pointer qr5tmix
Definition: w3wdatmd.F90:180
w3gdatmd::clgtype
integer, parameter clgtype
Definition: w3gdatmd.F90:625
w3servmd
Definition: w3servmd.F90:3
w3gdatmd::dsii
real, dimension(:), pointer dsii
Definition: w3gdatmd.F90:1234
w3snl5md::w3snl5
subroutine, public w3snl5(A, CG, WN, FMEAN, T1ABS, U10, UDIR, JSEA, S, D, KURT)
Interface to CalcQRSNL subroutine of the GKE module.
Definition: w3snl5md.F90:100
w3wdatmd::qr5cvk0
real, dimension(:, :), pointer qr5cvk0
Definition: w3wdatmd.F90:180
w3gdatmd::nth
integer, pointer nth
Definition: w3gdatmd.F90:1230
w3gdatmd::qi5nnz
integer(kind=8), pointer qi5nnz
Definition: w3gdatmd.F90:1373
w3odatmd
Definition: w3odatmd.F90:3
w3gkemd::qi_kev
integer, public qi_kev
Definition: w3gkemd.F90:176
w3gkemd::qr_oml
real, public qr_oml
Definition: w3gkemd.F90:167
w3gkemd::prepkernelio
subroutine, public prepkernelio(nk, nth, sig, th, act)
Definition: w3gkemd.F90:1202
w3odatmd::screen
integer, pointer screen
Definition: w3odatmd.F90:456
w3odatmd::tolast
integer, dimension(:,:), pointer tolast
Definition: w3odatmd.F90:464
w3gkemd::qi_interp
integer, public qi_interp
Definition: w3gkemd.F90:180
w3snl5md::hasnan
logical function hasnan(NK, NTH, ARR2D)
Check if the 2D array ARR2D contains NaN.
Definition: w3snl5md.F90:887
file
file(STRINGS ${CMAKE_BINARY_DIR}/switch switch_strings) separate_arguments(switches UNIX_COMMAND $
Definition: CMakeLists.txt:3
w3odatmd::ptnme
character(len=40), dimension(:), pointer ptnme
Definition: w3odatmd.F90:501
w3wdatmd::qi5tbeg
integer, dimension(:), pointer qi5tbeg
Definition: w3wdatmd.F90:179
w3odatmd::flout
logical, dimension(:), pointer flout
Definition: w3odatmd.F90:468
constants::tpi
real, parameter tpi
TPI 2*Pi.
Definition: constants.F90:72
w3gkemd::qi_disc
integer, public qi_disc
Definition: w3gkemd.F90:172
w3servmd::strace
subroutine strace(IENT, SNAME)
Definition: w3servmd.F90:148
w3gdatmd::gtype
integer, pointer gtype
Definition: w3gdatmd.F90:1094
w3gdatmd::qi5kev
integer, pointer qi5kev
Definition: w3gdatmd.F90:1372
w3odatmd::napout
integer, pointer napout
Definition: w3odatmd.F90:457
w3snl5md::insnl5
subroutine, public insnl5
Initialization for the GKE module (Prepare wavenumber grid & kernel coefficients).
Definition: w3snl5md.F90:435
constants
Define some much-used constants for global use (all defined as PARAMETER).
Definition: constants.F90:20
w3gdatmd::qi5dis
integer, pointer qi5dis
Definition: w3gdatmd.F90:1372
w3gdatmd
Definition: w3gdatmd.F90:16
w3dispmd::wavnu1
subroutine wavnu1(SI, H, K, CG)
Definition: w3dispmd.F90:85
w3servmd::extcde
subroutine extcde(IEXIT, UNIT, MSG, FILE, LINE, COMM)
Definition: w3servmd.F90:736
w3snl5md
Interface module for GKE (resonant & quasi-resonant four-wave interactions).
Definition: w3snl5md.F90:25
w3gdatmd::qi5pmx
integer, pointer qi5pmx
Definition: w3gdatmd.F90:1372
w3gkemd
Definition: w3gkemd.F90:3
w3gdatmd::qr5dpt
real, pointer qr5dpt
Definition: w3gdatmd.F90:1371
w3gkemd::calcqrsnl
subroutine, public calcqrsnl(nk, nth, sig, th, t0, t1, Cvk0, Cvk1, Inpqr0, Snl, Dnl, Kurt)
Definition: w3gkemd.F90:1625
w3timemd
Definition: w3timemd.F90:3
w3parall
Parallel routines for implicit solver.
Definition: w3parall.F90:22
w3gkemd::qi_nnz
integer(kind=8), public qi_nnz
Definition: w3gkemd.F90:209
w3dispmd
Definition: w3dispmd.F90:3
w3gdatmd::mapsta
integer, dimension(:,:), pointer mapsta
Definition: w3gdatmd.F90:1163
w3servmd::dist_sphere
real function dist_sphere(lo1, la1, lo2, la2)
Definition: w3servmd.F90:516
constants::grav
real, parameter grav
GRAV Acc.
Definition: constants.F90:61
w3parall::init_get_isea
subroutine init_get_isea(ISEA, JSEA)
Set ISEA for all schemes.
Definition: w3parall.F90:1398
w3gdatmd::flagll
logical, pointer flagll
Definition: w3gdatmd.F90:1219