WAVEWATCH III  beta 0.0.1
w3fld1md.F90
Go to the documentation of this file.
1 !/ ------------------------------------------------------------------- /
2 Module w3fld1md
3  !/
4  !/ +-----------------------------------+
5  !/ | WAVEWATCH III NOAA/NCEP/NOPP |
6  !/ | B. G. Reichl |
7  !/ | FORTRAN 90 |
8  !/ | Last update : 22-Mar-2021 |
9  !/ +-----------------------------------+
10  !/
11  !/ 01-Jul-2013 : Origination. ( version 4.xx )
12  !/ 18-Mar-2015 : Clean-up/prepare for distribution ( version 5.12 )
13  !/ 15-Jan-2016 : Updates ( version 5.12 )
14  !/ ( B. G. Reichl )
15  !/ 27-Jul-2016 : Added Charnock output (J.Meixner) ( version 5.12 )
16  !/ 22-Jun-2018 : updated SIG2WN subroutine (X.Chen) ( version 6.06 )
17  !/ modified the range of wind profile computation;
18  !/ corrected direction of the shortest waves
19  !/ 22-Mar-2021 : Consider DAIR a variable ( version 7.13 )
20  !/
21  !/
22  !/ Copyright 2009 National Weather Service (NWS),
23  !/ National Oceanic and Atmospheric Administration. All rights
24  !/ reserved. WAVEWATCH III is a trademark of the NWS.
25  !/ No unauthorized use without permission.
26  !/
27  ! 1. Purpose :
28  !
29  ! This Module contains routines to compute the wind stress vector
30  ! from the wave spectrum, the wind vector, and the lower atmospheric
31  ! stability (the form included here is for neutral conditions, but
32  ! the structure needed to include stability is included in comments).
33  ! The stress calculated via this subroutine is
34  ! intended for coupling to serve as the boundary condition
35  ! between the ocean and atmosphere, and (for now)
36  ! and has no impact on the wave spectrum calculated.
37  ! The calculation in w3fld1 is based on the method
38  ! presented in Reichl, Hara, and Ginis (2014), "Sea State Dependence
39  ! of the Wind Stress under Hurricane Winds."
40  !
41  ! 2. Variables and types :
42  !
43  ! Not applicable.
44  !
45  ! 3. Subroutines and functions :
46  !
47  ! Name Type Scope Description
48  ! ----------------------------------------------------------------
49  ! W3FLD1 Subr. Public Reichl et al. 2014 stress calculation
50  ! INFLD1 Subr. Public Corresponding initialization routine.
51  ! APPENDTAIL Subr. Public Modification of tail for calculation
52  ! SIG2WN Subr. Public Depth-dependent dispersion relation
53  ! WND2Z0M Subr. Public Wind to roughness length
54  ! ----------------------------------------------------------------
55  !
56  ! 4. Subroutines and functions used :
57  !
58  ! Name Type Module Description
59  ! ----------------------------------------------------------------
60  ! STRACE Subr. W3SERVMD Subroutine tracing.
61  ! ----------------------------------------------------------------
62  !
63  ! 5. Remarks :
64  !
65  ! 6. Switches :
66  !
67  ! !/S Enable subroutine tracing.
68  ! !/
69  !
70  ! 7. Source code :
71  !/
72  !/ ------------------------------------------------------------------- /
73  !/
74  !
75  PUBLIC
76  ! Tail_Choice: Chose the method to determine the level of the tail
77  INTEGER, SAVE :: tail_choice
78 #ifdef W3_OMPG
79  !$omp threadprivate(Tail_Choice)
80 #endif
81  REAL, SAVE :: tail_level !if Tail_Choice=0, tail is constant
82  REAL, SAVE :: tail_transition_ratio1! freq/fpi where tail
83  ! adjustment begins
84  REAL, SAVE :: tail_transition_ratio2! freq/fpi where tail
85  ! adjustment ends
86 #ifdef W3_OMPG
87  !$omp threadprivate(Tail_Level)
88  !$omp threadprivate(Tail_transition_ratio1,Tail_transition_ratio2)
89 #endif
90  !/
91 CONTAINS
92  !/ ------------------------------------------------------------------- /
93  SUBROUTINE w3fld1( ASPC, FPI, WNDX,WNDY, ZWND, &
94  DEPTH, RIB, DAIR, UST, USTD, Z0, &
95  TAUNUX, TAUNUY, CHARN)
96  !/
97  !/ +-----------------------------------+
98  !/ | WAVEWATCH III NOAA/NCEP/NOPP |
99  !/ | B. G. Reichl |
100  !/ | FORTRAN 90 |
101  !/ | Last update : 22-Mar-2021 |
102  !/ +-----------------------------------+
103  !/
104  !/ 01-Jul-2013 : Origination. ( version 4.xx )
105  !/ 18-Mar-2015 : Prepare for submission ( version 5.12 )
106  !/ 22-Mar-2021 : Consider DAIR a variable ( version 7.13 )
107  !/
108  ! 1. Purpose :
109  !
110  ! Diagnostic stress vector calculation from wave spectrum, lower
111  ! atmosphere stability, and wind vector (at some given height).
112  ! The height of wind vector is assumed to be within the constant
113  ! stress layer. These parameterizations are meant to be performed
114  ! at wind speeds > 10 m/s, and may not converge for extremely young
115  ! seas (i.e. starting from flat sea conditions).
116  !
117  ! 2. Method :
118  ! See Reichl et al. (2014).
119  !
120  ! 3. Parameters :
121  !
122  ! Parameter list
123  ! ----------------------------------------------------------------
124  ! ASPC Real I 1-D Wave action spectrum.
125  ! FPI Real I Peak input frequency.
126  ! WNDX Real I X-dir wind (assumed referenced to current)
127  ! WNDY Real I Y-dir wind (assumed referenced to current)
128  ! ZWND Real I Wind height.
129  ! DEPTH Real I Water depth.
130  ! RIB REAL I Bulk Richardson in lower atmosphere
131  ! (for determining stability in ABL to get
132  ! 10 m neutral wind)
133  ! DAIR REAL I Air density
134  ! TAUNUX Real 0 X-dir viscous stress (guessed from prev.)
135  ! TAUNUY Real 0 Y-dir viscous stress (guessed from prev.)
136  ! UST Real O Friction velocity.
137  ! USTD Real O Direction of friction velocity.
138  ! Z0 Real O Surface roughness length
139  ! CHARN Real O,optional Charnock parameter
140  ! ----------------------------------------------------------------
141  !
142  ! 4. Subroutines used :
143  !
144  ! Name Type Module Description
145  ! ----------------------------------------------------------------
146  ! STRACE Subr. W3SERVMD Subroutine tracing.
147  ! ----------------------------------------------------------------
148  !
149  ! 5. Called by :
150  !
151  ! Name Type Module Description
152  ! ----------------------------------------------------------------
153  ! W3ASIM Subr. W3ASIMMD Air-sea interface module.
154  ! W3EXPO Subr. N/A Point output post-processor.
155  ! GXEXPO Subr. N/A GrADS point output post-processor.
156  ! ----------------------------------------------------------------
157  !
158  ! 6. Error messages :
159  !
160  ! None.
161  !
162  ! 7. Remarks :
163  !
164  ! 8. Structure :
165  !
166  ! See source code.
167  !
168  ! 9. Switches :
169  !
170  ! !/S Enable subroutine tracing.
171  !
172  ! 10. Source code :
173  !
174  !/ ------------------------------------------------------------------- /
175  USE constants, ONLY: grav, dwat, tpi, pi, kappa
176  USE w3gdatmd, ONLY: nk, nth, nspec, sig, dth, xfr, th
177  USE w3odatmd, ONLY: ndse
178  USE w3servmd, ONLY: extcde
179 #ifdef W3_S
180  USE w3servmd, ONLY: strace
181 #endif
182  !/
183  IMPLICIT NONE
184  !/
185  !/ ------------------------------------------------------------------- /
186  !/ Parameter list
187  !/
188  REAL, INTENT(IN) :: ASPC(NSPEC), WNDX, WNDY, &
189  ZWND, DEPTH, RIB, DAIR, FPI
190  REAL, INTENT(OUT) :: UST, USTD, Z0
191  REAL, INTENT(OUT), OPTIONAL :: CHARN
192  REAL, INTENT(INOUT) :: TAUNUX, TAUNUY
193  !/
194  !/ ------------------------------------------------------------------- /
195  !/ Local parameters
196  !/
197  REAL, PARAMETER :: NU=0.105/10000.0
198  REAL, PARAMETER :: DELTA=0.03
199  ! Commonly used parameters
200  REAL :: wnd_in_mag, wnd_in_dir
201  !For Calculating Tail
202  REAL :: KMAX, KTAILA, KTAILB, KTAILC
203  REAL :: SAT, z01, z02, u10
204  LOGICAL :: ITERFLAG
205  INTEGER :: COUNT
206  !For Iterations
207  REAL :: DTX, DTY, iter_thresh, &
208  USTSM, Z0SM, Z1
209  !For stress calculation
210  REAL :: WAGE, CBETA, BP, CD, &
211  USTRB, ANGDIF, USTAR, ZNU, &
212  TAUT, TAUX, TAUY, BETAG, TAUDIR, &
213  TAUDIRB
214  !For wind profile calculation
215  REAL :: UPROFV, VPROFV
216  !For wind profile iteration
217  REAL :: WND_1X, WND_1Y, &
218  WND_2X, WND_2Y, &
219  WND_3X, WND_3Y, &
220  DIFU10XX, DIFU10YX, DIFU10XY, DIFU10YY, &
221  FD_A, FD_B, FD_C, FD_D, &
222  DWNDX, DWNDY, &
223  APAR, CH,UITV, VITV,USTL,&
224  CK
225  !For adding stability to wind profile
226  REAL :: WND_TOP, ANG_TOP, WND_PA, WND_PE, &
227  WND_PEx, WND_PEy, WND_PAx, WND_PAy, &
228  CDM
229  INTEGER :: NKT, K, T, Z2, ITER, ZI, ZII, &
230  I, CTR, ITERATION, KA1, KA2, &
231  KA3, KB
232  ! For defining extended spectrum with appended tail.
233  REAL, ALLOCATABLE, DIMENSION(:) :: WN, DWN, CP,SIG2
234  REAL, ALLOCATABLE, DIMENSION(:,:) :: SPC2
235  REAL, ALLOCATABLE, DIMENSION(:) :: TLTN, TLTE, TAUD, &
236  TLTND, &
237  TLTED, ZOFK, UPROF, VPROF, &
238  FTILDE, UP1, VP1, UP, VP, &
239  TLTNA, TLTEA
240 #ifdef W3_S
241  INTEGER, SAVE :: IENT = 0
242 #endif
243  LOGICAL :: FSFL1,FSFL2, CRIT1, CRIT2
244  LOGICAL :: IT_FLAG1, IT_FLAG2
245  LOGICAL, SAVE :: FIRST = .true.
246 #ifdef W3_OMPG
247  !$omp threadprivate( FIRST)
248 #endif
249  !/
250  !/ ------------------------------------------------------------------- /
251  !/
252 #ifdef W3_S
253  CALL strace (ient, 'W3FLD1')
254 #endif
255  !
256  ! 0. Initializations ------------------------------------------------ *
257  !
258  ! **********************************************************
259  ! *** The initialization routine should include all ***
260  ! *** initialization, including reading data from files. ***
261  ! **********************************************************
262  !
263  IF ( first ) THEN
264  CALL infld
265  first = .false.
266  END IF
267  wnd_in_mag = sqrt( wndx**2 + wndy**2 )
268  wnd_in_dir = atan2(wndy, wndx)
269  !----------------------------------------------------------+
270  ! Assume wind input is neutral 10 m wind. If wind input +
271  ! is not 10 m, tail level will need to be calculated based +
272  ! on esimation of 10 m wind. +
273  !----------------------------------------------------------+
274  u10 = wnd_in_mag
275  ! - Get tail level
276  if (tail_choice.eq.0) then
277  sat=tail_level
278  elseif (tail_choice.eq.1) then
279  CALL wnd2sat(u10,sat)
280  endif
281  !
282  ! 1. Attach Tail ---------------------------------------------------- *
283  !
284  ! If the depth remains constant, the allocation could be limited to the
285  ! first time step. Since this code is designed for coupled
286  ! implementation where the water level can change, I keep it the
287  ! allocation on every time step. When computational efficiency is
288  ! important, this process may be rethought.
289  !
290  ! i. Find maximum wavenumber of input spectrum
291  call sig2wn(sig(nk),depth,kmax)
292  nkt = nk
293  ! ii. Find additional wavenumber bins to extended to cm scale waves
294  DO WHILE ( kmax .LT. 366.0 )
295  nkt = nkt + 1
296  kmax = ( kmax * xfr**2 )
297  enddo!K<366
298  ! iii. Allocate new "extended" spectrum
299  ALLOCATE( wn(nkt), dwn(nkt), cp(nkt), sig2(nkt),spc2(nkt,nth), &
300  tltn(nkt), tlte(nkt), taud(nkt), &
301  tltnd(nkt), tlted(nkt), zofk(nkt), uprof(nkt+1),&
302  vprof(nkt+1), ftilde(nkt), up1(nkt+1),vp1(nkt+1), &
303  up(nkt+1), vp(nkt+1), tltna(nkt),tltea(nkt))
304  !
305  ! 1a. Build Discrete Wavenumbers for defining extended spectrum on---- *
306  !
307  !i. Copy existing sig to extended sig2, calculate phase speed.
308  DO k = 1, nk !existing spectrum
309  call sig2wn(sig(k),depth,wn(k))
310  cp(k) = ( sig(k) / wn(k) )
311  sig2(k) = sig(k)
312  enddo!K
313  !ii. Calculate extended sig2 and phase speed.
314  DO k = ( nk + 1 ), ( nkt) !extension
315  sig2(k) = sig2(k-1) *xfr
316  call sig2wn(sig2(k),depth,wn(k))
317  cp(k) = sig2(k) / wn(k)
318  enddo!K
319  !iii. Calculate dk's for integrations.
320  DO k = 1, nkt-1
321  dwn(k) = wn(k+1) - wn(k)
322  ENDDO
323  dwn(nkt) = wn(nkt)*xfr**2 - wn(nkt)
324  !
325  ! 1b. Attach initial tail--------------------------------------------- *
326  !
327  !i. Convert action spectrum to variance spectrum
328  ! SPC(k,theta) = A(k,theta) * sig(k)
329  ! This could be redone for computational efficiency
330  i=0
331  DO k=1, nk
332  DO t=1, nth
333  i = i + 1
334  spc2(k,t) = aspc(i) * sig(k)
335  enddo!T
336  enddo!K
337  !ii. Extend k^-3 tail to extended spectrum
338  DO k=nk+1, nkt
339  DO t=1, nth
340  spc2(k,t)=spc2(nk,t)*wn(nk)**3.0/wn(k)**(3.0)
341  enddo!T
342  enddo!K
343  !
344  ! 1c. Calculate transitions for new (constant saturation ) tail ------ *
345  !
346  !
347  !i. Find wavenumber for beginning spc level transition to tail
348  call sig2wn (fpi*tpi*tail_transition_ratio1,depth,ktaila )
349  !ii. Find wavenumber for ending spc level transition to tail
350  call sig2wn (fpi*tpi*tail_transition_ratio2,depth,ktailb )
351  !iii. Find wavenumber for ending spc direction transition to tail
352  ktailc= ktailb * 2.0
353  !iv. Find corresponding indices of wavenumber transitions
354  ka1 = 2 ! Do not modify 1st wavenumber bin
355  DO WHILE ( ( ktaila .GE. wn(ka1) ) .AND. (ka1 .LT. nkt-6) )
356  ka1 = ka1 + 1
357  ENDDO
358  ka2 = ka1+2
359  DO WHILE ( ( ktailb .GE. wn(ka2) ) .AND. (ka2 .LT. nkt-4) )
360  ka2 = ka2 + 1
361  ENDDO
362  ka3 = ka2+2
363  DO WHILE ( ( ktailc .GE. wn(ka3)) .AND. (ka3 .LT. nkt-2) )
364  ka3 = ka3 + 1
365  ENDDO
366  !v. Call subroutine to perform actually tail truncation
367  ! only if there is some energy in spectrum
368  CALL appendtail(spc2, wn, nkt, ka1, ka2, ka3,&
369  wnd_in_dir, sat)
370  ! Spectrum is now set for stress integration
371  !
372  ! 2. Prepare for iterative calculation of wave-form stress----------- *
373  !
374  dtx = 0.00005
375  dty = 0.00005
376  iter_thresh = 0.001
377  !
378  ! 2a. Calculate initial guess for viscous stress from smooth-law------ *
379  ! (Would be preferable to use prev. step)
380  !
381  z0sm = 0.001 !Guess
382  it_flag1 = .true.
383  iteration = 0
384  DO WHILE( it_flag1 )
385  iteration = iteration + 1
386  z1 = z0sm
387  ustsm = kappa * wnd_in_mag / ( log( zwnd / z1 ) )
388  z0sm = 0.132 * nu / ustsm
389  IF ( (abs( z0sm - z1 ) .LT. 10.0**(-6)) .OR.&
390  ( iteration .GT. 5 )) THEN
391  it_flag1 = .false.
392  ENDIF
393  ENDDO
394 
395  iteration = 1
396  ! Guessed values of viscous stress
397  taunux = ustsm**2 * dair * wndx / wnd_in_mag
398  taunuy = ustsm**2 * dair * wndy / wnd_in_mag
399  !
400  ! 3. Enter iterative calculation of wave form/skin stress---------- *
401  !
402  it_flag1 = .true.
403  DO WHILE (it_flag1)
404  DO iter=1, 3 !3 loops for TAUNU iteration
405  z2 = nkt
406  ! First : TAUNUX + DX
407  IF (iter .EQ. 1) THEN
408  taunux = taunux + dtx
409  ! Second : TAUNUY + DY
410  ELSEIF (iter .EQ. 2) THEN
411  taunux = taunux - dtx
412  taunuy = taunuy + dty
413  ! Third : unmodified
414  ELSEIF (iter .EQ. 3) THEN
415  taunuy = taunuy - dty
416  ENDIF
417  ! Near surface turbulent stress = taunu
418  tltn(1) = taunuy
419  tlte(1) = taunux
420 
421  CALL appendtail(spc2, wn, nkt, ka1, ka2, ka3,&
422  atan2(taunuy,taunux), sat)
423  !|---------------------------------------------------------------------|
424  !|-----Calculate first guess at growth rate and local turbulent stress-|
425  !|-----for integration as a function of wavedirection------------------|
426  !|---------------------------------------------------------------------|
427  DO zi = 2, nkt
428  ustl=0.0
429  tltnd(zi)=0.0
430  tlted(zi)=0.0
431  z2 = z2 - 1
432  ! Use value of prev. wavenumber/height
433  taud(zi) = atan2( tltn(zi-1), tlte(zi-1))
434  ustl = sqrt( sqrt( tltn(zi-1)**2 + tlte(zi-1)**2 )/ dair )
435  DO t = 1, nth
436  angdif=taud(zi)-th(t) !stress/wave angle
437  IF ( cos( angdif ) .GE. 0.0 ) THEN !Waves aligned
438  wage = cp(z2) / (ustl)
439  ! First, waves much slower than wind.
440  IF ( wage .LT. 10. ) THEN
441  cbeta = 25.0
442  ! Transition from waves slower than wind to faster
443  ELSEIF ( ( wage .GE. 10.0 ) .AND. &
444  ( wage .LE. 25.0 ) ) THEN
445  cbeta = 10.0 + 15.0 * cos( pi * ( wage - 10.0 ) &
446  / 15.0 )
447  ! Waves faster than wind
448  ELSEIF ( wage .GT. 25.0 ) THEN
449  cbeta = -5.0
450  ENDIF
451  ! Waves opposing wind
452  ELSE
453  cbeta = -25.0
454  ENDIF
455  !Integrate turbulent stress
456  tltnd(zi) =tltnd(zi)+( sin( th(t) ) * cos( angdif )**2)&
457  * cbeta * spc2(z2,t) * &
458  sqrt( tlte(zi-1)**2 + tltn(zi-1)**2.0 ) &
459  * ( wn(z2)**2.0 )*dth
460  tlted(zi) = tlted(zi)+(cos( th(t) ) * cos( angdif )**2)&
461  * cbeta * spc2(z2,t) * &
462  sqrt( tlte(zi-1)**2 + tltn(zi-1)**2.0 ) &
463  * ( wn(z2)**2.0 )*dth
464  ENDDO
465  !|---------------------------------------------------------------------|
466  !|-----Complete the integrations---------------------------------------|
467  !|---------------------------------------------------------------------|
468  IF (zi .EQ. 2) THEN
469  !First turbulent stress bin above taunu
470  tltna(zi) = tltnd(zi) * dwn(z2) * 0.5
471  tltea(zi) = tlted(zi) * dwn(z2) * 0.5
472  ELSE
473  tltna(zi)=(tltnd(zi)+tltnd(zi-1))*0.5*dwn(z2)
474  tltea(zi)=(tlted(zi)+tlted(zi-1))*0.5*dwn(z2)
475  ENDIF
476  tltn(zi)=tltn(zi-1)+tltna(zi)
477  tlte(zi)=tlte(zi-1)+tltea(zi)
478  ENDDO
479  tauy=tltn(nkt)
480  taux=tlte(nkt)
481  ! This is the first guess at the stress.
482  !|---------------------------------------------------------------------|
483  !|----Iterate til convergence------------------------------------------|
484  !|---------------------------------------------------------------------|
485  ustrb=sqrt(sqrt(tauy**2.0+taux**2.0)/dair)
486  taudirb=atan2(tauy,taux)
487  it_flag2 = .true.
488  ctr=1
489  DO WHILE ( (it_flag2) .AND. ( ctr .LT. 10 ) )
490  z2=nkt+1
491  DO zi=1, nkt
492  z2=z2-1
493  ustl=0.0
494  tlted(zi)=0.0
495  tltnd(zi)=0.0
496  ftilde(z2)=0.0
497  taud(zi) = atan2(tltn(zi),tlte(zi))
498  ustl = sqrt(sqrt(tltn(zi)**2+tlte(zi)**2)/dair)
499  DO t=1, nth
500  betag=0.0
501  angdif = taud(zi)-th(t)
502  IF ( cos( angdif ) .GE. 0.0 ) THEN
503  wage = cp(z2) / (ustl)
504  IF ( wage .LT. 10 ) THEN
505  cbeta = 25.0
506  ELSEIF ( ( wage .GE. 10.0 ) .AND. &
507  ( wage .LE. 25.0 ) ) THEN
508  cbeta = 10.0 + 15.0 * cos( pi * ( wage - 10.0 ) &
509  / 15.0 )
510  ELSEIF ( wage .GT. 25.0 ) THEN
511  cbeta = -5.0
512  ENDIF
513  ELSE
514  cbeta = -25.0
515  ENDIF
516  bp = sqrt( (cos( th(t) ) * cos( angdif )**2.0)**2.0 &
517  + (sin( th(t) ) * cos( angdif )**2.0)**2.0 )
518  betag=bp*cbeta*sqrt(tlte(zi)**2.0+tltn(zi)**2.0) &
519  /(dwat)*sig2(z2)/cp(z2)**2
520  ftilde(z2) = ftilde(z2) + betag * dwat * grav &
521  * spc2(z2,t) * dth
522  tltnd(zi) =tltnd(zi)+ (sin( th(t) ) * cos( angdif )**2.0)&
523  * cbeta * spc2(z2,t) * sqrt( &
524  tlte(zi)**2.0 + tltn(zi)**2.0 ) * &
525  ( wn(z2)**2.0 )*dth
526  tlted(zi) = tlted(zi)+(cos( th(t) ) * cos( angdif )**2.0)&
527  * cbeta * spc2(z2,t) * sqrt( &
528  tlte(zi)**2.0 + tltn(zi)**2.0 ) * &
529  ( wn(z2)**2.0 )*dth
530  ENDDO
531  IF (zi .EQ. 1) THEN
532  tltna(zi)=tltnd(zi)*dwn(z2)*0.5
533  tltea(zi)=tlted(zi)*dwn(z2)*0.5
534  ELSE
535  tltna(zi)=(tltnd(zi)+tltnd(zi-1))*0.5*dwn(z2)
536  tltea(zi)=(tlted(zi)+tlted(zi-1))*0.5*dwn(z2)
537  ENDIF
538  IF (zi.GT.1) then
539  tltn(zi)=tltn(zi-1)+tltna(zi)
540  tlte(zi)=tlte(zi-1)+tltea(zi)
541  else
542  tltn(zi)=taunuy+tltna(zi)
543  tlte(zi)=taunux+tltea(zi)
544  endif
545  ENDDO
546  tauy=tltn(nkt) !by NKT full stress is entirely
547  taux=tlte(nkt) !from turbulent stress
548  taut=sqrt(tauy**2.0+taux**2.0)
549  ustar=sqrt(sqrt(tauy**2.0+taux**2.0)/dair)
550  taudir=atan2(tauy, taux)
551  ! Note: add another criterion (stress direction) for iteration.
552  crit1=(abs(ustar-ustrb)*100.0)/((ustar+ustrb)*0.5) .GT. 0.1
553  IF ((taudir+taudirb).NE.0.) THEN
554  crit2=(abs(taudir-taudirb)*100.0/(taudir+taudirb)*0.5) .GT. 0.1
555  ELSE
556  crit2=.true.
557  ENDIF
558  IF (crit1 .OR. crit2) THEN
559  ! IF ((ABS(USTAR-USTRB)*100.0)/((USTAR+USTRB)*0.5) .GT. 0.1) THEN
560  ustrb=ustar
561  taudirb=taudir
562  ctr=ctr+1
563  ELSE
564  it_flag2 = .false.
565  ENDIF
566  ENDDO
567  ! Note: search for the top of WBL from top to bottom (avoid problems
568  ! caused by for very long swell)
569  kb=nkt
570  DO WHILE(((tltn(kb)**2+tlte(kb)**2)/(taux**2+tauy**2)).GT. &
571  .99)
572  kb=kb-1
573  ENDDO
574  kb=kb+1
575  !|---------------------------------------------------------------------|
576  !|----Now begin work on wind profile-----------------------------------|
577  !|---------------------------------------------------------------------|
578  DO i=1,nkt
579  zofk(i)=delta/wn(i)
580  ENDDO
581  znu=0.1 * 1.45e-5 / sqrt(sqrt(taunux**2.0+taunuy**2.0)/dair)
582  uprof(1:nkt+1)=0.0
583  vprof(1:nkt+1)=0.0
584  uprofv=0.0
585  vprofv=0.0
586  zi=1
587  z2=nkt
588  up1(zi) = ( ( ( wn(z2)**2 / delta ) * ftilde(z2) ) + &
589  ( dair / ( zofk(z2) * kappa ) ) * ( sqrt( &
590  tltn(zi)**2 + tlte(zi)**2 ) / dair )**(3/2) ) &
591  * ( tlte(zi) ) / ( tlte(zi) * taux &
592  + tltn(zi) * tauy )
593  vp1(zi) = ( ( ( wn(z2)**2 / delta ) * ftilde(z2) ) + &
594  ( dair / ( zofk(z2) * kappa ) ) * ( sqrt( &
595  tltn(zi)**2 + tlte(zi)**2 ) / dair )**(3/2) ) &
596  * ( tltn(zi) ) / ( tlte(zi) * taux &
597  + tltn(zi) * tauy )
598  up(zi) = up1(zi)
599  vp(zi) = vp1(zi)
600  uprof(zi) = dair / kappa * ( sqrt( taunux**2.0 + taunuy**2.0 ) &
601  / dair )**(1.5) * ( taunux / ( taux * &
602  taunux + tauy * taunuy ) ) * log( &
603  zofk(z2) / znu )
604  vprof(zi) = dair / kappa * ( sqrt( taunux**2.0 + taunuy**2.0 ) &
605  / dair )**(1.5) * ( taunuy / ( taux * &
606  taunux + tauy * taunuy ) ) * log( &
607  zofk(z2) / znu )
608  !Noted: wind profile computed till the inner layer height of the longest
609  !wave, not just to the top of wave boundary layer (previous)
610  DO zi=2, nkt
611  z2 = z2 - 1
612  up1(zi) = ( ( ( wn(z2)**2.0 / delta ) * ftilde(z2) ) + &
613  ( dair / ( zofk(z2) * kappa ) ) * ( sqrt( &
614  tltn(zi)**2.0 + tlte(zi)**2.0 ) / dair )**(1.5) ) &
615  * ( tlte(zi) ) / ( tlte(zi) * taux + &
616  tltn(zi) * tauy )
617  vp1(zi) = ( ( ( wn(z2)**2.0 / delta ) * ftilde(z2) ) + &
618  ( dair / ( zofk(z2) * kappa ) ) * ( sqrt( &
619  tltn(zi)**2.0 + tlte(zi)**2.0 ) / dair )**(1.5) ) &
620  * ( tltn(zi) ) / ( tlte(zi) * taux + &
621  tltn(zi) * tauy )
622  up(zi) = up1(zi) * 0.5 + up1(zi-1) * 0.5
623  vp(zi) = vp1(zi) * 0.5 + vp1(zi-1) * 0.5
624  uprof(zi) = uprof(zi-1) + up(zi) * ( zofk(z2) - zofk(z2+1) )
625  vprof(zi) = vprof(zi-1) + vp(zi) * ( zofk(z2) - zofk(z2+1) )
626  ENDDO
627  !|---------------------------------------------------------------------|
628  !|----Iteration completion/checks--------------------------------------|
629  !|---------------------------------------------------------------------|
630  !ZI = ( KB + 1 )
631  ! Now solving for 'ZWND' height wind
632  uprof(nkt+1) = uprof(nkt) + ( sqrt( sqrt( tauy**2.0 + &
633  taux**2.0 ) / dair ) ) / kappa * taux &
634  / sqrt( tauy**2.0 +taux**2.0 ) * log( zwnd &
635  / zofk(z2) )
636  vprof(nkt+1) = vprof(nkt) + ( sqrt( sqrt( tauy**2.0 + &
637  taux**2.0 ) / dair ) ) / kappa * tauy &
638  / sqrt( tauy**2.0 +taux**2.0 ) * log( zwnd &
639  / zofk(z2) )
640  IF (iter .EQ. 3) THEN
641  wnd_1x = uprof(nkt+1)
642  wnd_1y = vprof(nkt+1)
643  ELSEIF (iter .EQ. 2) THEN
644  wnd_2x = uprof(nkt+1)
645  wnd_2y = vprof(nkt+1)
646  ELSEIF (iter .EQ. 1) THEN
647  wnd_3x = uprof(nkt+1)
648  wnd_3y = vprof(nkt+1)
649  ENDIF
650 
651 
652  !-------------------------------------+
653  ! Guide for adding stability effects +
654  !-------------------------------------+
655  !Get Wind at top of wave boundary layer
656  ! WND_TOP=SQRT(UPROF(KB)**2+VPROF(KB)**2)
657  ! Get Wind Angle at top of wave boundary layer
658  ! ANG_TOP=ATAN2(VPROF(KB),UPROF(KB))
659  ! Stress and direction
660  ! USTD = ATAN2(TAUY,TAUX)
661  ! UST = SQRT( SQRT( TAUX**2 + TAUY**2 ) / DAIR)
662  ! Calclate along (PA) and across (PE) wind components
663  ! WND_PA=WND_TOP*COS(ANG_TOP-USTD)
664  ! WND_PE=WND_TOP*SIN(ANG_TOP-USTD)
665  ! Calculate cartesian aligned wind
666  ! WND_PAx=WND_PA*cos(ustd)
667  ! WND_PAy=WND_PA*sin(USTd)
668  !Calculate cartesion across wind
669  ! WND_PEx=WND_PE*cos(ustd+pi/2.)
670  ! WND_PEy=WND_PE*sin(ustd+pi/2.)
671  !----------------------------------------------------+
672  ! If a non-neutral profile is used the effective z0 +
673  ! should be computed. This z0 can then be used +
674  ! with stability information to derive a Cd, which +
675  ! can be used to project the along-stress wind to +
676  ! the given height. +
677  ! i.e.: Assume neutral inside WBL calculate Z0 +
678  ! Z0=ZOFK(Z2)*EXP(-WND_PA*kappa/UST) +
679  ! WND_PA=UST/SQRT(CDM) +
680  !----------------------------------------------------+
681  ! WND_PAx=WND_PA*cos(ustd)
682  ! WND_PAy=WND_PA*sin(USTd)
683  ! IF (ITER .EQ. 3) THEN
684  ! WND_1X = WND_PAx+WND_PEx
685  ! WND_1Y = WND_PAy+WND_PEy
686  ! ELSEIF (ITER .EQ. 2) THEN
687  ! WND_2X = WND_PAx+WND_PEx
688  ! WND_2Y = WND_PAy+WND_PEy
689  ! ELSEIF (ITER .EQ. 1) THEN
690  ! WND_3X = WND_PAx+WND_PEx
691  ! WND_3Y = WND_PAy+WND_PEy
692  ! ENDIF
693  ENDDO
694  iteration = iteration + 1
695  difu10xx = wnd_3x - wnd_1x
696  difu10yx = wnd_3y - wnd_1y
697  difu10xy = wnd_2x - wnd_1x
698  difu10yy = wnd_2y - wnd_1y
699  fd_a = difu10xx / dtx
700  fd_b = difu10xy / dty
701  fd_c = difu10yx / dtx
702  fd_d = difu10yy / dty
703  dwndx = - wndx + wnd_1x
704  dwndy = - wndy + wnd_1y
705  uitv = abs( dwndx )
706  vitv = abs( dwndy )
707  ch = sqrt( uitv**2.0 + vitv**2.0 )
708  IF (ch .GT. 15.) THEN
709  apar = 0.5 / ( fd_a * fd_d - fd_b * fd_c )
710  ELSE
711  apar = 1.0 / ( fd_a * fd_d - fd_b * fd_c )
712  ENDIF
713  ck=4.
714  IF (((vitv/max(abs(wndy),ck) .GT. iter_thresh) .OR. &
715  (uitv/max(abs(wndx),ck) .GT. iter_thresh)) .AND. &
716  (iteration .LT. 2)) THEN
717  taunux = taunux - apar * ( fd_d * dwndx - fd_b * dwndy )
718  taunuy = taunuy - apar * ( -fd_c * dwndx +fd_a * dwndy )
719  ELSEIF (((vitv/max(abs(wndy),ck) .GT. iter_thresh) .OR. &
720  (uitv/max(abs(wndx),ck) .GT. iter_thresh)) .AND. &
721  (iteration .LT. 24)) THEN
722  iter_thresh = 0.001
723  taunux = taunux - apar * ( fd_d * dwndx - fd_b * dwndy )
724  taunuy = taunuy - apar * ( -fd_c * dwndx +fd_a * dwndy )
725  ELSEIF (((vitv/max(abs(wndy),ck) .GT. iter_thresh) .OR. &
726  (uitv/max(abs(wndx),ck) .GT. iter_thresh)) .AND. &
727  (iteration .LT. 26)) THEN
728  iter_thresh = 0.01
729  taunux = taunux - apar * ( fd_d * dwndx - fd_b * dwndy )
730  taunuy = taunuy - apar * ( -fd_c * dwndx +fd_a * dwndy )
731  ELSEIF (((vitv/max(abs(wndy),ck) .GT. iter_thresh) .OR. &
732  (uitv/max(abs(wndx),ck) .GT. iter_thresh)) .AND. &
733  (iteration .LT. 30)) THEN
734  iter_thresh = 0.05
735  taunux = taunux - apar * ( fd_d * dwndx - fd_b * dwndy )
736  taunuy = taunuy - apar * ( -fd_c * dwndx +fd_a * dwndy )
737  ELSEIF (iteration .GE. 30) THEN
738  write(*,*)'Attn: W3FLD1 not converged.'
739  write(*,*)' Wind (X/Y): ',wndx,wndy
740  it_flag1 = .false.
741  ust=-999
742  taunux=0.
743  taunuy=0.
744  ELSEIF (((vitv/max(abs(wndy),ck) .LT. iter_thresh) .AND.&
745  (uitv/max(abs(wndx),ck) .LT. iter_thresh)) .AND. &
746  (iteration .GE. 2)) THEN
747  it_flag1 = .false.
748  ENDIF
749  ! if taunu iteration is unstable try to reset with new guess...
750  if (.not.(cos(wnd_in_dir-atan2(taunuy,taunux)).ge.0.0)) then
751  taunux = ustsm**2 * dair * wndx / wnd_in_mag*.95
752  taunuy = ustsm**2 * dair * wndy / wnd_in_mag*.95
753  endif
754  ENDDO
755  !|---------------------------------------------------------------------|
756  !|----Finish-----------------------------------------------------------|
757  !|---------------------------------------------------------------------|
758  ustd = atan2(tauy,taux)
759  ust = sqrt( sqrt( taux**2 + tauy**2 ) / dair)
760  ! Get Z0 from aligned wind
761  wnd_pa=wnd_in_mag*cos(wnd_in_dir-ustd)
762  z0 = zwnd/exp(wnd_pa*kappa/ust)
763  cd = ust**2 / wnd_in_mag**2
764  IF (PRESENT(charn)) THEN
765  charn = 0.01/sqrt(sqrt( taunux**2 + taunuy**2 )/(ust**2))
766  ENDIF
767  fsfl1=.not.((cd .LT. 0.01).AND.(cd .GT. 0.0001))
768  fsfl2=.not.(cos(wnd_in_dir-ustd).GT.0.9)
769  IF (fsfl1 .or. fsfl2) THEN
770  !Fail safe to bulk
771  write(*,*)'Attn: W3FLD1 failed, will output bulk...'
772  CALL wnd2z0m(wnd_in_mag,z0)
773  ust = wnd_in_mag*kappa/log(zwnd/z0)
774  ustd = wnd_in_dir
775  cd = ust**2 / wnd_in_mag**2
776  ENDIF
777  DEALLOCATE(wn, dwn, cp,sig2, spc2, tltn, tlte, taud, &
778  tltnd, tlted, zofk, uprof, &
779  vprof, ftilde, up1, vp1, up, vp, tltna, tltea)
780  !/ End of W3FLD1 ----------------------------------------------------- /
781  !/
782  RETURN
783  !
784  END SUBROUTINE w3fld1
785  !/ ------------------------------------------------------------------- /
786  SUBROUTINE infld
787  !/
788  !/ +-----------------------------------+
789  !/ | WAVEWATCH III NOAA/NCEP |
790  !/ | B. G. Reichl |
791  !/ | FORTRAN 90 |
792  !/ | Last update : 15-Jan-2016 |
793  !/ +-----------------------------------+
794  !/
795  !/ 15-Jan-2016 : Origination. ( version 5.12 )
796  !/
797  ! 1. Purpose :
798  !
799  ! Initialization for w3fld1 (also used by w3fld2)
800  !
801  ! 2. Method :
802  !
803  ! 3. Parameters :
804  !
805  ! Parameter list
806  ! ----------------------------------------------------------------
807  ! ----------------------------------------------------------------
808  !
809  ! 4. Subroutines used :
810  !
811  ! Name Type Module Description
812  ! ----------------------------------------------------------------
813  ! STRACE Subr. W3SERVMD Subroutine tracing.
814  ! ----------------------------------------------------------------
815  !
816  ! 5. Called by :
817  !
818  ! Name Type Module Description
819  ! ----------------------------------------------------------------
820  ! W3FLDX Subr. W3FLDXMD Corresponding source term.
821  ! ----------------------------------------------------------------
822  !
823  ! 6. Error messages :
824  !
825  ! None.
826  !
827  ! 7. Remarks :
828  !
829  ! 8. Structure :
830  !
831  ! See source code.
832  !
833  ! 9. Switches :
834  !
835  ! !/S Enable subroutine tracing.
836  !
837  ! 10. Source code :
838  !
839  !/ ------------------------------------------------------------------- /
840  USE w3odatmd, ONLY: ndse
842  USE w3servmd, ONLY: extcde
843 #ifdef W3_S
844  USE w3servmd, ONLY: strace
845 #endif
846  !/
847  IMPLICIT NONE
848  !/
849  !/ ------------------------------------------------------------------- /
850  !/ Parameter list
851  !/
852  !/
853  !/ ------------------------------------------------------------------- /
854  !/ Local parameters
855  !/
856 #ifdef W3_S
857  INTEGER, SAVE :: IENT = 0
858 #endif
859  !/
860  !/ ------------------------------------------------------------------- /
861  !/
862 #ifdef W3_S
863  CALL strace (ient, 'INFLD')
864 #endif
865  !
866  ! 1. .... ----------------------------------------------------------- *
867  !
872 
873  !
874  RETURN
875  !
876  ! Formats
877  !
878 
879  !/
880  !/ End of INFLD1 ----------------------------------------------------- /
881  !/
882  END SUBROUTINE infld
883  !/
884  !/ ------------------------------------------------------------------- /
885  SUBROUTINE appendtail(INSPC, WN2, NKT, KA1, KA2, KA3, WNDDIR,SAT)
886  !/
887  !/ +-----------------------------------+
888  !/ | WAVEWATCH III NOAA/NCEP |
889  !/ | B. G. Reichl |
890  !/ | FORTRAN 90 |
891  !/ | Last update : 15-Jan-2016 |
892  !/ +-----------------------------------+
893  !/
894  !/ 15-Jan-2016 : Origination. ( version 5.12 )
895  !/
896  ! 1. Purpose :
897  !
898  ! Set tail for stress calculation.
899  !
900  ! 2. Method :
901  !
902  ! 3. Parameters :
903  !
904  ! Parameter list
905  ! ----------------------------------------------------------------
906  ! ----------------------------------------------------------------
907  !
908  ! 4. Subroutines used :
909  !
910  ! Name Type Module Description
911  ! ----------------------------------------------------------------
912  ! STRACE Subr. W3SERVMD Subroutine tracing.
913  ! ----------------------------------------------------------------
914  !
915  ! 5. Called by :
916  !
917  ! Name Type Module Description
918  ! ----------------------------------------------------------------
919  ! W3FLD1 Subr. W3FLD1MD Corresponding source term.
920  ! ----------------------------------------------------------------
921  !
922  ! 6. Error messages :
923  !
924  ! None.
925  !
926  ! 7. Remarks :
927  !
928  ! 8. Structure :
929  !
930  ! See source code.
931  !
932  ! 9. Switches :
933  !
934  ! !/S Enable subroutine tracing.
935  !
936  ! 10. Source code :
937  !
938  !/ ------------------------------------------------------------------- /
939  USE constants, ONLY: tpi, pi
940  USE w3gdatmd, ONLY: nth, th, dth
941  USE w3odatmd, ONLY: ndse
942  USE w3servmd, ONLY: extcde
943 #ifdef W3_S
944  USE w3servmd, ONLY: strace
945 #endif
946  !/
947  IMPLICIT NONE
948  !/
949  !/ ------------------------------------------------------------------- /
950  !/ Parameter list
951  !/
952  INTEGER, INTENT(IN) :: NKT, KA1, KA2, KA3
953  REAL, INTENT(IN) :: WN2(NKT), WNDDIR,SAT
954  REAL, INTENT(INOUT) :: INSPC(NKT,NTH)
955  !/
956  !/ ------------------------------------------------------------------- /
957  !/ Local parameters
958  !/
959 #ifdef W3_S
960  INTEGER, SAVE :: IENT = 0
961 #endif
962  REAL :: BT(NKT), IC, ANGLE2, ANG(NKT),&
963  NORMSPC(NTH), AVG, ANGDIF, M, MAXANG, &
964  MAXAN, MINAN
965  INTEGER :: MAI, I, K, T
966  REAL, ALLOCATABLE, DIMENSION(:) :: ANGLE1
967  !/
968  !/ ------------------------------------------------------------------- /
969  !/
970 #ifdef W3_S
971  CALL strace (ient, 'APPENDTAIL')
972 #endif
973  !
974  ! 1. .... ----------------------------------------------------------- *
975  !
976  !|###############################################################|
977  !|##1. Get the level of the saturation spectrum in transition
978  !|## region A
979  !|###############################################################|
980  !-------------------------------------------
981  ! 1a, get saturation level at KA1 (1.25xFPI)
982  !-------------------------------------------
983  bt(ka1) = 0
984  ang = 0.0
985  DO t=1, nth
986  bt(ka1)=bt(ka1)+inspc(ka1,t)*wn2(ka1)**3.0*dth
987  ENDDO
988  !-----------------------------------------------
989  ! 1b, Set saturation level at KA2 (3xFPI) to SAT
990  !-----------------------------------------------
991  bt(ka2) = sat
992  !-------------------------------------------------------------
993  ! 1c, Find slope of saturation spectrum in transition region A
994  !-------------------------------------------------------------
995  m = ( bt(ka2) - bt(ka1) ) / ( wn2(ka2) - wn2(ka1) )
996  !----------------------------------------------------------------
997  ! 1d, Find intercept of saturation spectrum in transition region
998  ! A
999  !----------------------------------------------------------------
1000  ic = bt(ka1) - m * wn2(ka1)
1001  !------------------------------------------------------
1002  ! 1e, Calculate saturation level for all wavenumbers in
1003  ! transition region A
1004  !------------------------------------------------------
1005  DO k=ka1,ka2
1006  bt(k)=m*wn2(k)+ic
1007  ENDDO
1008  !|###############################################################|
1009  !|##2. Determine the directionality at each wavenumber in
1010  !|## transition region B
1011  !|###############################################################|
1012  !-----------------------------------------------
1013  ! 2a, Find angle of spectral peak at KA2 (3xFPI)
1014  !-----------------------------------------------
1015  maxang = 0.0
1016  DO t=1, nth
1017  IF (inspc(ka2,t) .GT. maxang) THEN
1018  maxang=inspc(ka2,t)
1019  ENDIF
1020  ENDDO
1021  !-------------------------------
1022  ! 2b, Check if peak spans 2 bins
1023  !-------------------------------
1024  !MAI = total number of angles of peak (if it spans more than 1)
1025  mai = 0
1026  DO t=1, nth
1027  IF (maxang .EQ. inspc(ka2,t)) THEN
1028  mai = mai+1
1029  ENDIF
1030  ENDDO
1031  !ANGLE1 = angles that correspond to peak (array)
1032  mai = max(1,mai)
1033  ALLOCATE(angle1(mai))
1034  !-----------------------------------------------------
1035  ! 2c, If peak spans 2 or more bins it must be averaged
1036  !-----------------------------------------------------
1037  k=1
1038  DO t=1, nth
1039  IF (maxang .EQ. inspc(ka2,t)) THEN
1040  angle1(k) = th(t)
1041  k=k+1
1042  ENDIF
1043  ENDDO
1044  DO k=1, mai
1045  DO WHILE (angle1(k) .LT. 0.0)
1046  angle1(k) = angle1(k) + tpi
1047  ENDDO
1048  DO WHILE (angle1(k) .GE. tpi)
1049  angle1(k) = angle1(k) - tpi
1050  ENDDO
1051  ENDDO
1052  IF (mai .GT. 1) THEN
1053  maxan = angle1(1)
1054  minan = angle1(1)
1055  DO i=2, mai
1056  IF (maxan .LT. angle1(i) )THEN
1057  maxan = angle1(i)
1058  ENDIF
1059  IF (minan .GT. angle1(i) )THEN
1060  minan = angle1(i)
1061  ENDIF
1062  ENDDO
1063  !------------------------------------------------------
1064  ! Need to distinguish if mean cross the origin (0/2pi)
1065  !------------------------------------------------------
1066  IF (maxan-minan .GT. pi) THEN
1067  DO i=1, mai
1068  IF (maxan - angle1(i) .GT. pi) THEN
1069  angle1(i) = angle1(i) + tpi
1070  ENDIF
1071  ENDDO
1072  angle2=sum(angle1)/max(real(mai),1.)
1073  ELSE
1074  angle2=sum(angle1)/max(real(mai),1.)
1075  ENDIF
1076  ELSE
1077  angle2=angle1(1)
1078  ENDIF
1079  DO WHILE (angle2 .LT. 0.0)
1080  angle2 = angle2 + tpi
1081  ENDDO
1082  DO WHILE (angle2 .GE. tpi)
1083  angle2 = angle2 - tpi
1084  ENDDO
1085  !
1086  !---------------------------------------------------
1087  ! This deals with angles that are less than 90
1088  !---------------------------------------------------
1089  if (cos(angle2-wnddir) .ge. 0.) then !Less than 90
1090  m=asin(sin(wnddir-angle2))/(wn2(ka3)-wn2(ka2))
1091  ic=angle2
1092  do k=ka2, ka3
1093  ang(k)=ic +m*(wn2(k)-wn2(ka2))
1094  enddo
1095  else
1096  !----------------------------------------------------
1097  ! This deals with angels that turn clockwise
1098  !----------------------------------------------------
1099  if (sin(wnddir-angle2).GE.0) then
1100  m=acos(cos(wnddir-angle2))/(wn2(ka3)-wn2(ka2))
1101  ic=angle2
1102  do k=ka2, ka3
1103  ang(k)=ic+m*(wn2(k)-wn2(ka2))
1104  enddo
1105  else
1106  !-----------------------------------------------------
1107  ! This deals with angels that cross counter-clockwise
1108  !-----------------------------------------------------
1109  m=acos(cos(wnddir-angle2))/(wn2(ka3)-wn2(ka2))
1110  ic=angle2
1111  do k=ka2, ka3
1112  ang(k)=ic-m*(wn2(k)-wn2(ka2))
1113  enddo
1114  endif
1115  endif
1116  !----------------------------------------------
1117  ! Region A, Saturation level decreased linearly
1118  ! while direction is maintained
1119  !----------------------------------------------
1120  DO k=ka1, ka2-1
1121  avg=sum(inspc(k,:))/max(real(nth),1.)
1122  DO t=1,nth
1123  if (avg /= 0.0) then
1124  inspc(k,t)=bt(k)*inspc(k,t)/tpi/(wn2(k)**3.0)/avg
1125  else
1126  inspc(k,t) = 0.0
1127  end if
1128  ENDDO
1129  ENDDO
1130  !-----------------------------------------------------------
1131  ! Region B, Saturation level left flat while spectrum turned
1132  ! to direction of wind
1133  !-----------------------------------------------------------
1134  DO k = ka2, ka3
1135  DO t=1, nth
1136  angdif=th(t)-ang(k)
1137  IF (cos(angdif) .GT. 0.0) THEN
1138  normspc(t) = cos(angdif)**2.0
1139  ELSE
1140  normspc(t)=0.0
1141  ENDIF
1142  ENDDO
1143  avg=sum(normspc)/max(real(nth),1.)
1144  DO t=1, nth
1145  if (avg /= 0.0) then
1146  inspc(k,t) = sat * normspc(t)/tpi/(wn2(k)**3.0)/avg
1147  else
1148  inspc(k,t) = 0.0
1149  end if
1150  ENDDO
1151  ENDDO
1152  DO t=1, nth
1153  angdif=th(t)-wnddir
1154  IF (cos(angdif) .GT. 0.0) THEN
1155  normspc(t) = cos(angdif)**2.0
1156  ELSE
1157  normspc(t) = 0.0
1158  ENDIF
1159  ENDDO
1160  avg=sum(normspc)/max(real(nth),1.)!1./4.
1161  DO k=ka3+1, nkt
1162  DO t=1, nth
1163  if (avg /= 0.0) then
1164  inspc(k,t)=normspc(t)*(sat)/tpi/(wn2(k)**3.0)/avg
1165  else
1166  inspc(k,t) = 0.0
1167  end if
1168  ENDDO
1169  ENDDO
1170  DEALLOCATE(angle1)
1171  !
1172  ! Formats
1173  !
1174  !/
1175  !/ End of APPENDTAIL ----------------------------------------------------- /
1176  !/
1177  RETURN
1178  !
1179  END SUBROUTINE appendtail
1180  !/ ------------------------------------------------------------------- /
1181  !/
1182  !/ ------------------------------------------------------------------- /
1183  SUBROUTINE sig2wn(SIG,DEPTH,WN)
1184  !/ ------------------------------------------------------------------- /
1185  !Author: Brandon Reichl (GSO/URI)
1186  !Origination : 2013
1187  !Update : March - 18 - 2015
1188  ! : June -22 -2018 (XYC)
1189  !Puropse : Convert from angular frequency to wavenumber
1190  ! using full gravity wave dispersion relation
1191  ! if tanh(kh)<0.99, otherwise uses deep-water
1192  ! approximation.
1193  !NOTE: May be a better version internal to WW3 that can replace this.
1194  ! Improved by using newton's method for iteration.(2018)
1195  !/ ------------------------------------------------------------------- /
1196  !/
1197  use constants, only: grav
1198  !/
1199  implicit none
1200  !/
1201  REAL,INTENT(IN) :: SIG,DEPTH
1202  REAL,INTENT(OUT) :: WN
1203  !/
1204  real :: wn1,wn2 !,sig1,sig2,dsigdk
1205  real :: fk, fk_slp
1206  integer :: i
1207  logical :: SWITCH
1208  !/ ------------------------------------------------------------------- /
1209  wn1=sig**2/grav
1210  switch=.true.
1211  !/ Updated code with Newton's method by XYC:
1212  if (tanh(wn1*depth) .LT. 0.99) then
1213  do while (switch)
1214  fk=grav*wn1*tanh(wn1*depth) - sig**2
1215  fk_slp = grav*tanh(wn1*depth) + grav*wn1*depth/(cosh(wn1*depth))**2
1216 
1217  wn2=wn1 - fk/fk_slp
1218 
1219  if (abs(wn2-wn1)/wn1 .LT. 0.0001 ) then
1220  switch = .false.
1221  else
1222  wn1=wn2
1223  endif
1224  enddo
1225  else
1226  wn2=wn1
1227  endif
1228  wn=wn2
1229  !/ END of update
1230  !/
1231  !/ Previous code by BR:
1232  !/ ------------------------------------------------------------------- /
1233  ! wn1=sig**2/GRAV
1234  ! wn2=wn1+0.00001
1235  ! SWITCH=.true.
1236  !/ ------------------------------------------------------------------- /
1237  ! if (tanh(wn1*depth).LT.0.99) then
1238  ! do i=1,5
1239  ! if (SWITCH) then
1240  ! sig1=sqrt(GRAV*wn1*tanh(wn1*depth))
1241  ! sig2=sqrt(GRAV*wn2*tanh(wn2*depth))
1242  ! if (sig1.lt.sig*.99999.or.sig1.gt.sig*1.00001) then
1243  ! dsigdk=(sig2-sig1)/(wn2-wn1)
1244  ! WN1=WN1+(SIG2-SIG1)/dsigdk
1245  ! wn2=wn1+wn1*0.00001
1246  ! else
1247  ! SWITCH = .FALSE.
1248  ! endif
1249  ! endif
1250  ! enddo
1251  ! endif
1252  !/
1253  ! WN=WN1
1254  !/
1255  RETURN
1256  END SUBROUTINE sig2wn
1257  !/ ------------------------------------------------------------------- /
1258  !/
1259  !/ ------------------------------------------------------------------- /
1260  SUBROUTINE wnd2z0m( W10M , ZNOTM )
1261  !/ +-----------------------------------+
1262  !/ | WAVEWATCH III NOAA/NCEP |
1263  !/ | B. G. Reichl |
1264  !/ | FORTRAN 90 |
1265  !/ | Last update : 04-Aug-2016 |
1266  !/ +-----------------------------------+
1267  !/
1268  !/ 09-Apr-2014 : Last Update. ( version 5.12 )
1269  !/ 15-Aug-2016 : Updated for 2016 HWRF z0 ( J. Meixner )
1270  !/
1271  ! 1. Purpose :
1272  !
1273  ! Get bulk momentum z0 from 10-m wind.
1274  ! Bulk stress corresponds to 2015 GFDL Hurricane model
1275  ! Not published yet, but contact Brandon Reichl or
1276  ! Isaac Ginis (Univ. of Rhode Island) for further info
1277  !
1278  ! 2. Method :
1279  ! This has now been updated for 2016 HWRF z0 using routines
1280  ! from HWRF znot_m_v1, Biju Thomas, 02/07/2014
1281  ! and znot_wind10m Weiguo Wang, 02/24/2016
1282  !
1283  ! 3. Parameters :
1284  ! Name Unit Type Description
1285  ! ----------------------------------------------------------------
1286  ! W10M m/s input 10 m neutral wind [m/s]
1287  ! ZNOTM m output Roughness scale for momentum
1288  ! ----------------------------------------------------------------
1289  ! 4. Subroutines used :
1290  !
1291  ! Name Type Module Description
1292  ! ----------------------------------------------------------------
1293  ! STRACE Subr. W3SERVMD Subroutine tracing.
1294  ! ----------------------------------------------------------------
1295  !
1296  ! 5. Called by :
1297  !
1298  ! Name Type Module Description
1299  ! ----------------------------------------------------------------
1300  ! W3FLD1 Subr. W3FLD1MD Corresponding source term.
1301  ! W3FLD2 Subr. W3FLD2MD Corresponding source term.
1302  ! ----------------------------------------------------------------
1303  !
1304  ! 6. Error messages :
1305  !
1306  ! None.
1307  !
1308  ! 7. Remarks :
1309  !
1310  ! 8. Structure :
1311  !
1312  ! See source code.
1313  !
1314  ! 9. Switches :
1315  !
1316  ! !/S Enable subroutine tracing.
1317  !
1318  ! 10. Source code :
1319  !
1320  !/ ------------------------------------------------------------------- /
1321 #ifdef W3_S
1322  USE w3servmd, ONLY: strace
1323 #endif
1324  !/
1325  IMPLICIT NONE
1326  REAL, INTENT(IN) :: W10M
1327  REAL, INTENT(OUT):: ZNOTM
1328 
1329  !Parameters from znot_m_v1
1330  REAL, PARAMETER :: bs0 = -8.367276172397277e-12
1331  REAL, PARAMETER :: bs1 = 1.7398510865876079e-09
1332  REAL, PARAMETER :: bs2 = -1.331896578363359e-07
1333  REAL, PARAMETER :: bs3 = 4.507055294438727e-06
1334  REAL, PARAMETER :: bs4 = -6.508676881906914e-05
1335  REAL, PARAMETER :: bs5 = 0.00044745137674732834
1336  REAL, PARAMETER :: bs6 = -0.0010745704660847233
1337 
1338  REAL, PARAMETER :: cf0 = 2.1151080765239772e-13
1339  REAL, PARAMETER :: cf1 = -3.2260663894433345e-11
1340  REAL, PARAMETER :: cf2 = -3.329705958751961e-10
1341  REAL, PARAMETER :: cf3 = 1.7648562021709124e-07
1342  REAL, PARAMETER :: cf4 = 7.107636825694182e-06
1343  REAL, PARAMETER :: cf5 = -0.0013914681964973246
1344  REAL, PARAMETER :: cf6 = 0.0406766967657759
1345 
1346  !Variables from znot_wind10m
1347  REAL :: Z10, U10,AAA,TMP
1348 
1349 #ifdef W3_S
1350  INTEGER, SAVE :: IENT = 0
1351  CALL strace (ient, 'WND2Z0M')
1352 #endif
1353 
1354  !Values as set in znot_wind10m
1355  z10=10.0
1356  u10=w10m
1357  if (u10 > 85.0) u10=85.0
1358 
1359  !Calculation of z0 as in znot_m_v1
1360  IF ( u10 .LE. 5.0 ) THEN
1361  znotm = (0.0185 / 9.8*(7.59e-4*u10**2+2.46e-2*u10)**2)
1362  ELSEIF (u10 .GT. 5.0 .AND. u10 .LT. 10.0) THEN
1363  znotm =.00000235*(u10**2 - 25 ) + 3.805129199617346e-05
1364  ELSEIF ( u10 .GE. 10.0 .AND. u10 .LT. 60.0) THEN
1365  znotm = bs6 + bs5*u10 + bs4*u10**2 + bs3*u10**3 + bs2*u10**4 +&
1366  bs1*u10**5 + bs0*u10**6
1367  ELSE
1368  znotm = cf6 + cf5*u10 + cf4*u10**2 + cf3*u10**3 + cf2*u10**4 +&
1369  cf1*u10**5 + cf0*u10**6
1370  END IF
1371 
1372  !Modifications as in znot_wind10m for icoef_sf=4
1373 
1374  !for wind<20, cd similar to icoef=2 at 10m, then reduced
1375  tmp=0.4*0.4/(alog(10.0/znotm))**2 ! cd at zlev
1376  aaa=0.75
1377  IF (u10 < 20) THEN
1378  aaa=0.99
1379  ELSEIF(u10 < 45.0) THEN
1380  aaa=0.99+(u10-20)*(0.75-0.99)/(45.0-20.0)
1381  END IF
1382  znotm=z10/exp( sqrt(0.4*0.4/(tmp*aaa)) )
1383 
1384  END SUBROUTINE wnd2z0m
1385  !/ ------------------------------------------------------------------- /
1386  SUBROUTINE wnd2sat(WND10,SAT)
1387  !/ +-----------------------------------+
1388  !/ | WAVEWATCH III NOAA/NCEP |
1389  !/ | B. G. Reichl |
1390  !/ | FORTRAN 90 |
1391  !/ | Last update : 04-Aug-2016 |
1392  !/ +-----------------------------------+
1393  !/
1394  !/ 15-Jan-2016 : Origination. ( version 5.12 )
1395  !/ 04-Aug-2016 : Updated for 2016 HWRF CD/U10 curve ( J. Meixner )
1396  !/
1397  ! 1. Purpose :
1398  !
1399  ! Gives level of saturation spectrum to produce
1400  ! equivalent Cd as in wnd2z0m (for neutral 10m wind)
1401  ! tuned for method of Reichl et al. 2014
1402  !
1403  ! 2. Method :
1404  !
1405  ! 3. Parameters :
1406  !
1407  ! Parameter list
1408  ! ----------------------------------------------------------------
1409  !Input: WND10 - 10 m neutral wind [m/s]
1410  !Output: SAT - Level 1-d saturation spectrum in tail [non-dim]
1411  ! ----------------------------------------------------------------
1412  ! 4. Subroutines used :
1413  !
1414  ! Name Type Module Description
1415  ! ----------------------------------------------------------------
1416  ! STRACE Subr. W3SERVMD Subroutine tracing.
1417  ! ----------------------------------------------------------------
1418  !
1419  ! 5. Called by :
1420  !
1421  ! Name Type Module Description
1422  ! ----------------------------------------------------------------
1423  ! W3FLD1 Subr. W3FLD1MD Corresponding source term.
1424  ! ----------------------------------------------------------------
1425  !
1426  ! 6. Error messages :
1427  !
1428  ! None.
1429  !
1430  ! 7. Remarks :
1431  !
1432  ! 8. Structure :
1433  !
1434  ! See source code.
1435  !
1436  ! 9. Switches :
1437  !
1438  ! !/S Enable subroutine tracing.
1439  !
1440  ! 10. Source code :
1441  !
1442  !/ ------------------------------------------------------------------- /
1443 #ifdef W3_S
1444  USE w3servmd, ONLY: strace
1445 #endif
1446  !/
1447  IMPLICIT NONE
1448  !/
1449  REAL, INTENT(IN) :: WND10
1450  REAL, INTENT(OUT) :: SAT
1451 #ifdef W3_S
1452  INTEGER, SAVE :: IENT = 0
1453  CALL strace (ient, 'WND2SAT')
1454 #endif
1455  !/ Old HWRF 2015 and ST2
1456  ! SAT =0.000000000001237 * WND10**6 +&
1457  ! -0.000000000364155 * WND10**5 +&
1458  ! 0.000000037435015 * WND10**4 +&
1459  ! -0.000001424719473 * WND10**3 +&
1460  ! 0.000000471570975 * WND10**2 +&
1461  ! 0.000778467452178 * WND10**1 +&
1462  ! 0.002962335390055
1463  !
1464  ! SAT values based on
1465  ! HWRF 2016 CD curve, created with fetch limited cases ST4 physics
1466  IF (wnd10<20.0) THEN
1467  sat = -0.000018541921682*wnd10**2 &
1468  +0.000751515452434*wnd10 &
1469  +0.002466529381004
1470  ELSEIF (wnd10<45) THEN
1471  sat = -0.000000009060349*wnd10**4 &
1472  +0.000001276678367*wnd10**3 &
1473  -0.000068274393789*wnd10**2 &
1474  +0.001418180888868*wnd10 &
1475  +0.000262277682984
1476  ELSE
1477  sat = -0.000155976275073*wnd10 &
1478  +0.012027763023184
1479  ENDIF
1480 
1481  sat = min(max(sat,0.002),0.014)
1482  END SUBROUTINE wnd2sat
1483  !
1484  !/ End of module W3FLD1MD -------------------------------------------- /
1485  !/
1486 END MODULE w3fld1md
w3gdatmd::nk
integer, pointer nk
Definition: w3gdatmd.F90:1230
constants::pi
real, parameter pi
PI Value of Pi.
Definition: constants.F90:71
w3gdatmd::tail_id
integer, pointer tail_id
Definition: w3gdatmd.F90:1270
w3gdatmd::dth
real, pointer dth
Definition: w3gdatmd.F90:1232
w3gdatmd::nspec
integer, pointer nspec
Definition: w3gdatmd.F90:1230
w3fld1md::tail_choice
integer, save tail_choice
Definition: w3fld1md.F90:77
w3fld1md::w3fld1
subroutine w3fld1(ASPC, FPI, WNDX, WNDY, ZWND, DEPTH, RIB, DAIR, UST, USTD, Z0, TAUNUX, TAUNUY, CHARN)
Definition: w3fld1md.F90:96
w3gdatmd::sig
real, dimension(:), pointer sig
Definition: w3gdatmd.F90:1234
w3fld1md::tail_transition_ratio2
real, save tail_transition_ratio2
Definition: w3fld1md.F90:84
w3fld1md
Definition: w3fld1md.F90:2
w3gdatmd::tail_tran1
real, pointer tail_tran1
Definition: w3gdatmd.F90:1271
w3gdatmd::th
real, dimension(:), pointer th
Definition: w3gdatmd.F90:1234
w3fld1md::sig2wn
subroutine sig2wn(SIG, DEPTH, WN)
Definition: w3fld1md.F90:1184
w3gdatmd::tail_tran2
real, pointer tail_tran2
Definition: w3gdatmd.F90:1271
w3fld1md::wnd2sat
subroutine wnd2sat(WND10, SAT)
Definition: w3fld1md.F90:1387
w3odatmd::ndse
integer, pointer ndse
Definition: w3odatmd.F90:456
w3fld1md::tail_transition_ratio1
real, save tail_transition_ratio1
Definition: w3fld1md.F90:82
constants::kappa
real, parameter kappa
KAPPA von Karman's constant (N.D.).
Definition: constants.F90:69
w3servmd
Definition: w3servmd.F90:3
w3gdatmd::nth
integer, pointer nth
Definition: w3gdatmd.F90:1230
w3odatmd
Definition: w3odatmd.F90:3
constants::dwat
real, parameter dwat
DWAT Density of water (kg/m3).
Definition: constants.F90:62
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
constants
Define some much-used constants for global use (all defined as PARAMETER).
Definition: constants.F90:20
w3gdatmd
Definition: w3gdatmd.F90:16
w3fld1md::appendtail
subroutine appendtail(INSPC, WN2, NKT, KA1, KA2, KA3, WNDDIR, SAT)
Definition: w3fld1md.F90:886
w3servmd::extcde
subroutine extcde(IEXIT, UNIT, MSG, FILE, LINE, COMM)
Definition: w3servmd.F90:736
w3fld1md::tail_level
real, save tail_level
Definition: w3fld1md.F90:81
w3gdatmd::tail_lev
real, pointer tail_lev
Definition: w3gdatmd.F90:1271
constants::grav
real, parameter grav
GRAV Acc.
Definition: constants.F90:61
w3fld1md::wnd2z0m
subroutine wnd2z0m(W10M, ZNOTM)
Definition: w3fld1md.F90:1261
w3fld1md::infld
subroutine infld
Definition: w3fld1md.F90:787