129 PRIVATE :: balancing_matrix, eig_hqr, polyroots
130 PRIVATE :: nr_corr, nr_root
131 PRIVATE :: cmplx_sinh, cmplx_cosh, cmplx_tanh2
132 PRIVATE :: init_random_seed
134 PRIVATE :: ksp, kdp, kspc, kdpc, errtol
138 INTEGER,
PARAMETER :: KSP = kind(1.0)
139 INTEGER,
PARAMETER :: KDP = kind(1.0d0)
142 INTEGER,
PARAMETER :: KSPC = kind((1.0, 1.0))
143 INTEGER,
PARAMETER :: KDPC = kind((1.0d0, 1.0d0))
144 REAL,
PARAMETER :: ERRTOL = 1.e-12
168 SUBROUTINE w3sic5 (A, DEPTH, CG, WN, IX, IY, S, D)
336 REAL,
INTENT(IN) :: cg(
nk), wn(
nk), a(
nspec), depth
338 INTEGER,
INTENT(IN) :: ix, iy
343 INTEGER,
SAVE :: ient = 0
350 REAL :: icecoef1, icecoef2, icecoef3, &
352 REAL,
DIMENSION(NK) :: d1d, wn_r, wn_i
359 CALL strace (ient,
'W3SIC5')
376 icecoef1 = icep1(ix, iy)
379 WRITE (
ndse,1001)
'ICE PARAMETER 1 (HICE)'
384 icecoef2 = icep2(ix, iy)
387 WRITE (
ndse,1001)
'ICE PARAMETER 2 (VISC)'
392 icecoef3 = icep3(ix, iy)
395 WRITE (
ndse,1001)
'ICE PARAMETER 3 (DENS)'
400 icecoef4 = icep4(ix, iy)
403 WRITE (
ndse,1001)
'ICE PARAMETER 4 (ELAS)'
407 IF (
inflags2(4)) iceconc = icei(ix, iy)
416 IF (icecoef1 < 0.0001) noice = .true.
418 IF (
inflags2(4) .AND. iceconc < errtol) noice = .true.
427 CALL w3ic5wncg(wn_r, wn_i, cg, icecoef1, icecoef2, &
428 icecoef3, icecoef4, depth)
436 d1d(ik) = -2.0 * cg(ik) * wn_i(ik)
442 d(ikth) = d1d(
mapwn(ikth))
452 dout(ik,ith) = d(ith+(ik-1)*
nth)
455 CALL prt2ds (ndst,
nk,
nk,
nth, dout,
sig(1:),
' ', 1., &
456 0.0, 0.001,
'Diag Sice',
' ',
'NONAME')
465 1001
FORMAT(/
' *** WAVEWATCH III ERROR IN W3SIC5MD : '/ &
466 ' ',a,
' IS NOT DEFINED IN ww3_shel.inp.')
493 SUBROUTINE w3ic5wncg(WN_R, WN_I, CG, HICE, IVISC, RHOI, ISMODG, &
579 REAL,
INTENT(INOUT) :: wn_r(:), wn_i(:)
580 REAL,
INTENT(IN) :: cg(:)
581 REAL,
INTENT(IN) :: hice, ivisc, rhoi, ismodg, hwat
585 REAL,
ALLOCATABLE :: sigma(:)
586 INTEGER :: kl, ku, ik
590 INTEGER,
SAVE :: ient = 0
596 CALL strace (ient,
'W3IC5WNCG')
600 IF (
ALLOCATED(sigma))
DEALLOCATE(sigma);
ALLOCATE(sigma(
SIZE(cg)))
603 IF (
SIZE(wn_r, 1) .EQ.
nk)
THEN
607 ELSE IF (
SIZE(wn_r,1) .EQ.
nk+2)
THEN
619 CALL fsdisp(hice, ivisc, rhoi, ismodg, hwat,
tpi/sigma(ik), &
627 900
FORMAT(/
' *** WAVEWATCH III ERROR IN W3SIC5MD : '/ &
628 ' Subr. ', a,
': Cannot determine bounds of&
629 & wavenumber array.'/)
652 SUBROUTINE fsdisp(HICE, IVISC, RHOI, ISMODG, HWAT, WT, WNR, WNI)
745 REAL,
INTENT(IN) :: hice, ivisc, rhoi, ismodg, hwat, wt
746 REAL,
INTENT(OUT) :: wnr, wni
751 REAL :: ic5minig, ic5minwt, ic5maxkratio, &
752 ic5maxki, ic5minhw, ic5vemod
753 REAL :: tismodg, twt, tratio, thw
754 REAL,
PARAMETER :: nu = 0.3, rhow = 1025.
757 COMPLEX :: gv, c1, c2
758 REAL :: sigma, wno, cgo, thkh, &
759 rtrl(5), rtim(5), rtang(5)
763 COMPLEX(KDPC) :: guess, croot, c1d, c2d
767 INTEGER,
SAVE :: ient = 0
773 CALL strace (ient,
'FSDISP')
797 tismodg = max(ic5minig, ismodg)
798 twt = max(ic5minwt, wt)
799 thw = max(ic5minhw, hwat)
802 IF (abs(tismodg) < errtol)
THEN
810 IF (abs(ic5vemod - 1.) < errtol)
THEN
812 gv = cmplx(tismodg, -1. * sigma * rhoi * ivisc)
818 c1 = gv * hice**3. / (6. * rhow * sigma**2.)
831 c2 = cmplx(
grav / sigma**2. - rhoi * hice / rhow, 0.)
833 ELSE IF (abs(ic5vemod - 2.) < errtol)
THEN
835 c1 = cmplx(tismodg * hice**3. * (1+nu) / (6. * rhow * sigma**2.), 0.)
836 c2 = cmplx(
grav/sigma**2. - rhoi * hice / rhow, &
837 -1. * ivisc / (rhow * sigma))
839 ELSE IF (abs(ic5vemod - 3.) > errtol)
THEN
840 WRITE(
ndse, 1003)
'FSDISP', ic5vemod
848 CALL wavnu1(sigma, thw, wno, cgo)
849 thkh = tanh(wno * thw)
851 IF (abs(ic5vemod - 1.) < errtol .OR. abs(ic5vemod - 2.) < errtol)
THEN
854 (/real(real(c1))*thkh, 0., 0., 0., real(real(c2))*thkh, -1./),&
856 rtang = atan2(rtim, rtrl)
863 ireal = minloc(abs(rtang), dim=1)
864 IF (rtrl(ireal) <= 0. .OR. abs(rtim(ireal)) > errtol)
THEN
870 guess = rtrl(ireal) * exp(cmplx(0., 1e-6))
874 c1d = c1; c2d = c2; hwatd = thw
875 croot = nr_root(c1d, c2d, hwatd, guess)
876 wnr = real(real(croot))
877 wni = real(aimag(croot))
879 ELSE IF (abs(ic5vemod - 3.) < errtol)
THEN
885 wni = hice * ivisc * sigma**3. / (rhow *
grav**2.)
906 IF (w3inan(wnr) .OR. w3inan(wni) .OR. wnr <= 0 .OR. wni <= 0. &
907 .OR. tratio >= ic5maxkratio)
THEN
909 WRITE(
ndse, 1002)
'FSDISP', hice, ivisc, tismodg, hwat, twt, &
915 wni = min(ic5maxki, wni)
918 1000
FORMAT(/
' *** WAVEWATCH III ERROR IN W3SIC5MD : '/ &
919 ' Subr. ', a,
': Zero shear modulus G is not allowed&
920 & in the FS viscoelastic model'/)
922 1001
FORMAT(/
' *** WAVEWATCH III ERROR IN W3SIC5MD : '/ &
923 ' Subr. ', a,
': get a bad first guess'/)
925 1002
FORMAT(/
' *** WAVEWATCH III ERROR IN W3SIC5MD : '/ &
926 ' -----------------------------------------------------'/&
927 ' Subr. ', a,
' : get NaN/NeG/Huge kr or ki for' /&
928 ' -----------------------------------------------------'/&
929 ' Ice thickness : ', f9.1,
' m'/ &
930 ' Ice viscosity : ', e9.2,
' m2/s'/ &
931 ' Ice shear modulus : ', e9.2,
' Pa' / &
932 ' Water depth : ', f9.1,
' m'/ &
933 ' Wave period : ', f10.2,
' s'/ &
934 ' Wave number (Ko) : ', f11.3,
' rad/m'/ &
935 ' Wave number (Kr) : ', f11.3,
' rad/m'/ &
936 ' Attenu. Rate (Ki) : ', e9.2,
' /m'/)
938 1003
FORMAT(/
' *** WAVEWATCH III ERROR IN W3SIC5MD : '/ &
939 ' Subr. ', a,
': Unknown VE model (', f5.0,
')'/)
956 SUBROUTINE balancing_matrix(NMAT, MATRIX)
1052 INTEGER,
INTENT(IN) :: nmat
1053 REAL,
INTENT(INOUT) :: matrix(nmat, nmat)
1057 INTEGER,
SAVE :: ient = 0
1060 REAL,
PARAMETER :: radx = radix(matrix), &
1063 REAL :: c, f, g, r, s
1066 CALL strace (ient,
'BALANCING_MATRIX')
1073 c = sum( abs(matrix(:, i)) ) - matrix(i, i)
1074 r = sum( abs(matrix(i, :)) ) - matrix(i, i)
1076 IF (c /= 0.0 .AND. r /= 0.0)
THEN
1095 IF ( (c+r)/f < 0.95*s)
THEN
1099 matrix(i, :) = matrix(i, :) * g
1100 matrix(:, i) = matrix(:, i) * f
1109 END SUBROUTINE balancing_matrix
1123 SUBROUTINE eig_hqr (NMAT, HMAT, EIGR, EIGI)
1228 INTEGER,
INTENT(IN) :: nmat
1229 REAL,
INTENT(INOUT) :: hmat(nmat, nmat)
1230 REAL,
INTENT(OUT) :: eigr(nmat), eigi(nmat)
1236 INTEGER,
SAVE :: ient = 0
1239 INTEGER :: i, its, k, l, m, nn, mnnk, idiag
1240 REAL :: anorm, p, q, r, s, t, u, v, w, x, y, z
1245 CALL strace (ient,
'EIG_HQR')
1256 anorm = sum(abs(hmat))
1267 small:
DO l=nn, 2, -1
1268 s = abs( hmat(l-1, l-1) ) + abs( hmat(l, l) )
1270 IF (abs(s) < errtol) s = anorm
1272 IF ( abs(hmat(l, l-1)) < errtol )
THEN
1286 y = hmat(nn-1, nn-1)
1287 w = hmat(nn, nn-1) * hmat(nn-1, nn)
1298 eigr(nn-1) = eigr(nn)
1299 IF (z /= 0.0) eigr(nn) = x - w/z
1305 eigr(nn-1) = eigr(nn)
1319 IF (its == 10 .OR. its == 20)
THEN
1323 hmat(idiag, idiag) = hmat(idiag, idiag) + (-x)
1325 s = abs(hmat(nn, nn-1)) + abs(hmat(nn-1, nn-2))
1337 p = (r * s - w) / hmat(m+1, m) + hmat(m, m+1)
1338 q = hmat(m+1, m+1) - z - r - s
1341 s = abs(p) + abs(q) + abs(r)
1346 u = abs( hmat(m, m-1) ) * ( abs(q) + abs(r) )
1347 v = abs(p) * ( abs(hmat(m-1, m-1)) + abs(z) + &
1348 abs( hmat(m+1, m+1) ))
1354 IF (i /= m+2) hmat(i, i-3)=0.0
1363 IF (k /= nn-1) r = hmat(k+2, k-1)
1364 x = abs(p) + abs(q) + abs(r)
1372 s = sign(sqrt(p**2 + q**2 + r**2), p)
1375 IF (l /= m) hmat(k, k-1) = -hmat(k, k-1)
1377 hmat(k, k-1) = -s * x
1387 pp(k:nn) = hmat(k, k:nn) + q * hmat(k+1, k:nn)
1389 pp(k:nn) = pp(k:nn) + r * hmat(k+2, k:nn)
1390 hmat(k+2, k:nn) = hmat(k+2, k:nn) - &
1393 hmat(k+1, k:nn) = hmat(k+1, k:nn) - pp(k:nn) * y
1394 hmat(k, k:nn) = hmat(k, k:nn) - pp(k:nn) * x
1397 pp(l:mnnk) = x * hmat(l:mnnk, k) + y * &
1400 pp(l:mnnk) = pp(l:mnnk) + z*hmat(l:mnnk, k+2)
1401 hmat(l:mnnk, k+2) = hmat(l:mnnk, k+2) - &
1404 hmat(l:mnnk, k+1) = hmat(l:mnnk, k+1) - &
1406 hmat(l:mnnk, k) = hmat(l:mnnk, k) - pp(l:mnnk)
1414 1001
FORMAT(/
' *** WAVEWATCH III ERROR IN W3SIC5MD : '/ &
1415 ' Subr. ', a,
': TOO MANY ITERATIONS'/)
1420 END SUBROUTINE eig_hqr
1435 SUBROUTINE polyroots(NPC, PCVEC, RTRL, RTIM)
1542 INTEGER,
INTENT(IN) :: npc
1543 REAL,
INTENT(IN) :: pcvec(npc)
1544 REAL,
INTENT(OUT) :: rtrl(npc-1), rtim(npc-1)
1551 INTEGER,
SAVE :: ient = 0
1553 REAL :: hess(npc-1, npc-1)
1559 CALL strace (ient,
'POLYROOTS')
1563 IF (abs(pcvec(1)) < errtol)
THEN
1570 hess(1, :) = -1 * pcvec(2:) / pcvec(1)
1576 CALL balancing_matrix(npc-1, hess)
1578 CALL eig_hqr(npc-1, hess, rtrl, rtim)
1581 1001
FORMAT(/
' *** WAVEWATCH III ERROR IN W3SIC5MD : '/ &
1582 ' Subr. ', a,
': the coeff. of x^n must not be 0'/)
1586 END SUBROUTINE polyroots
1602 FUNCTION nr_corr(K, C1, C2, H)
1703 COMPLEX(KDPC),
INTENT(IN) :: k, c1, c2
1704 REAL(kdp),
INTENT(IN) :: h
1705 COMPLEX(KDPC) :: nr_corr
1712 INTEGER,
SAVE :: ient = 0
1715 REAL(kdp),
PARAMETER :: kh_lim = 7.5
1716 COMPLEX(KDPC) :: lam, lampr, fv, df, tkh
1721 CALL strace (ient,
'NR_CORR')
1727 lam = c1 * k**4 + c2
1729 lampr = 5 * c1 * k**4 + c2
1731 IF (real(real(tkh)) <= kh_lim)
THEN
1735 fv = lam * k * cmplx_sinh(tkh) - cmplx_cosh(tkh)
1736 df = lam * tkh * cmplx_cosh(tkh) + (lampr-h) * cmplx_sinh(tkh)
1741 fv = lam * k * cmplx_tanh2(tkh) - 1
1742 df = lampr * cmplx_tanh2(tkh) + lam * tkh * &
1743 (1 - cmplx_tanh2(tkh) ** 2.)
1750 END FUNCTION nr_corr
1765 FUNCTION nr_root(C1, C2, H, GUESS)
1854 COMPLEX(KDPC),
INTENT(IN) :: c1, guess, c2
1855 REAL(kdp),
INTENT(IN) :: h
1856 COMPLEX(KDPC) :: nr_root
1862 INTEGER,
SAVE :: ient = 0
1864 COMPLEX(KDPC) :: k0, k1, dk
1867 REAL :: ic5maxiter, ic5rkick, ic5kfilter
1872 CALL strace (ient,
'NR_ROOT')
1880 dk = nr_corr(k0, c1, c2, h)
1884 IF (ic5rkick > 0.5)
CALL init_random_seed()
1886 DO WHILE (abs(dk) > errtol)
1888 dk = nr_corr(k0, c1, c2, h)
1902 IF (ic5rkick > 0.5 .AND. abs(real(k1)) < ic5kfilter)
THEN
1904 CALL random_number(tranval)
1905 k1 = k1 + 2 * tranval
1908 IF (iter >= ic5maxiter)
THEN
1918 1001
FORMAT(/
' *** WAVEWATCH III ERROR IN W3SIC5MD : '/ &
1919 ' Subr. ', a,
': TOO MANY ITERATIONS'/)
1924 END FUNCTION nr_root
1940 FUNCTION cmplx_sinh(X)
2015 COMPLEX(KDPC),
INTENT(IN) :: x
2016 COMPLEX(KDPC) :: cmplx_sinh
2022 INTEGER,
SAVE :: ient = 0
2027 CALL strace (ient,
'CMPLX_SINH')
2030 cmplx_sinh = (exp(x) - exp(-x)) * 0.5
2034 END FUNCTION cmplx_sinh
2050 FUNCTION cmplx_cosh(X)
2125 COMPLEX(KDPC),
INTENT(IN) :: x
2126 COMPLEX(KDPC) :: cmplx_cosh
2132 INTEGER,
SAVE :: ient = 0
2137 CALL strace (ient,
'CMPLX_COSH')
2140 cmplx_cosh = (exp(x) + exp(-x)) * 0.5
2144 END FUNCTION cmplx_cosh
2160 FUNCTION cmplx_tanh2(X)
2237 COMPLEX(KDPC),
INTENT(IN) :: x
2238 COMPLEX(KDPC) :: cmplx_tanh2
2244 INTEGER,
SAVE :: ient = 0
2249 CALL strace (ient,
'CMPLX_TANH2')
2252 cmplx_tanh2 = (1 - exp(-2*x)) / (1 + exp(-2*x))
2256 END FUNCTION cmplx_tanh2
2266 SUBROUTINE init_random_seed()
2325 INTEGER,
SAVE :: ient = 0
2328 INTEGER :: i, n, clock
2329 INTEGER,
DIMENSION(:),
ALLOCATABLE :: seed
2332 CALL strace (ient,
'INIT_RANDOM_SEED')
2335 CALL random_seed(
SIZE = n)
2338 CALL system_clock(count=clock)
2340 seed = clock + 37 * (/ (i - 1, i = 1, n) /)
2341 CALL random_seed(put = seed)
2347 END SUBROUTINE init_random_seed