59 '$Id: CRTM_Utility.f90 60152 2015-08-13 19:19:13Z paul.vandelst@noaa.gov $' 71 INTEGER,
INTENT(IN) :: num
72 REAL( fp),
DIMENSION(:) :: abscissas, weights
74 REAL(fp) :: x, xp, pl, pl1, pl2, dpl
77 parameter(tiny1=3.0d-14)
89 pl = ( (2*l-1)*x*pl1 - (l-1)*pl2 )/l
91 dpl = n*(x*pl-pl1)/(x*x-1)
95 IF (abs(x-xp).GT.tiny1 .AND. i.LT.10)
GO TO 100
97 abscissas(num+1-j) = (
one+x)/
two 98 weights(num+1-j) =
one/((
one-x*x)*dpl*dpl)
99 weights(j) =
one/((
one-x*x)*dpl*dpl)
105 FUNCTION matinv(A, Error_Status)
111 REAL(fp),
intent(in),
dimension(:,:) :: a
112 INTEGER,
INTENT( OUT ) :: error_status
115 REAL(fp),
dimension(size(a,1),size(a,2)) :: b
116 REAL(fp ),
dimension(size(a,1),size(a,2)) ::
matinv 117 REAL(fp),
dimension(size(a,1)) :: temp
119 CHARACTER(*),
PARAMETER :: routine_name =
'matinv' 122 INTEGER :: i, j, k, m, imax(1), ipvt(
size(a,1))
128 ipvt = (/ (i, i = 1, n) /)
132 imax = maxloc(abs(b(k:n,k)))
135 IF ( abs(b(m,k)).LE.(1.e-40_fp) )
THEN 143 ipvt( (/m,k/) ) = ipvt( (/k,m/) )
144 b((/m,k/),:) = b((/k,m/),:)
152 b(:,j) = b(:,j)-temp*c
165 INTEGER,
INTENT(in) :: MOA
166 REAL(fp),
intent(in) :: ANG
167 REAL(fp),
intent(out),
dimension(0:MOA):: PL
173 pl(j+1)=
REAL(2*J+1,fp)/
REAL(J+1,fp)*ANG*PL(J) &
174 -
REAL(J,fp)/
REAL(J+1,fp)*PL(J-1)
184 INTEGER,
intent(in):: MOA,NU
185 REAL(fp),
INTENT(in),
dimension(NU):: ANG
186 REAL(fp),
INTENT(out),
dimension(0:MOA,NU):: PL
195 pl(j+1,i)=
REAL(2*J+1, fp)/
REAL(J+1, fp)*TE*PL(J,i) &
196 -
REAL(J, fp)/
REAL(J+1, fp)*PL(J-1,i)
206 REAL(fp),
INTENT(IN) :: u
207 INTEGER,
INTENT(IN) :: n,mf
208 REAL(fp),
DIMENSION(0:N) :: pl
214 IF ( mf .EQ. 0 )
THEN 219 pl(mf)=f*sqrt((1.0_fp-u*u)**mf)
221 IF ( n.GT.mf ) pl(mf+1)=u*sqrt(2*mf+1.0_fp)*pl(mf)
222 IF( n.gt.(mf+1) )
THEN 224 pl(j+1)=(float(2*j+1)*u*pl(j) &
225 -sqrt(float(j*j-mf*mf))*pl(j-1))/sqrt(float((j+1)**2-mf*mf))
235 INTEGER,
INTENT(IN) :: n
253 SUBROUTINE asymtx( AAD, M, IA, IEVEC, &
303 CHARACTER(len=200) :: message
317 INTEGER :: m, ia, ievec, ier
318 INTEGER,
PARAMETER :: maxstrmstks = 30
319 REAL( fp),
PARAMETER :: c1=0.4375_fp,c2=0.5_fp,c3=0.75_fp,c4=0.95_fp,c5=16.0_fp,c6=256.0_fp
320 REAL( fp),
DIMENSION(:,:) :: aad, evecd
321 REAL( fp),
DIMENSION(:) :: evald
322 REAL( fp) :: wkd(4*maxstrmstks), nor_factor
327 LOGICAL noconv, notlas
328 INTEGER :: i, j, l, k, kkk, lll,n, n1, n2, in, lb, ka, ii
330 REAL(fp) :: tol, discri, sgn, rnorm, w, f, g, h, p, q, r
331 REAL(fp) :: repl, col, row, scale, t, x, z, s, y, uu, vv
340 IF ( m.LT.1 .OR. ia.LT.m .OR. ievec.LT.m )
THEN 341 message =
'ASYMTX--bad input variable(s)' 350 ELSE IF ( m.EQ.2 )
THEN 351 discri = ( aad(1,1) - aad(2,2) )**2 + 4.0d0*aad(1,2)*aad(2,1)
352 IF ( discri.LT.
zero )
THEN 353 message =
'ASYMTX--COMPLEX EVALS IN 2X2 CASE' 358 IF ( aad(1,1).LT.aad(2,2) ) sgn = -
one 359 evald(1) = 0.5d0*( aad(1,1) + aad(2,2) + sgn*sqrt(discri) )
360 evald(2) = 0.5d0*( aad(1,1) + aad(2,2) - sgn*sqrt(discri) )
363 IF ( aad(1,1).EQ.aad(2,2) .AND. &
364 (aad(2,1).EQ.
zero.OR.aad(1,2).EQ.
zero) )
THEN 365 rnorm = abs(aad(1,1))+abs(aad(1,2))+ &
366 abs(aad(2,1))+abs(aad(2,2))
368 evecd(2,1) = aad(2,1) / w
369 evecd(1,2) = - aad(1,2) / w
371 evecd(2,1) = aad(2,1) / ( evald(1) - aad(2,2) )
372 evecd(1,2) = aad(1,2) / ( evald(2) - aad(1,1) )
396 IF ( i.NE.j ) row = row + abs( aad(j,i) )
398 IF ( row.EQ.
zero )
THEN 422 IF ( i.NE.j ) col = col + abs( aad(i,j) )
424 IF ( col.EQ.
zero )
THEN 453 col = col + abs( aad(j,i) )
454 row = row + abs( aad(i,j) )
460 160
IF ( col.LT.g )
THEN 466 170
IF ( col.GE.g )
THEN 472 IF ( (col+row)/f .LT. c4*h )
THEN 476 aad(i,j) = aad(i,j) / f
479 aad(j,i) = aad(j,i) * f
484 IF ( noconv )
GO TO 140
486 IF ( k-1 .LT. l+1 )
GO TO 350
494 scale = scale + abs(aad(i,n-1))
496 IF ( scale.NE.
zero )
THEN 498 wkd(i+m) = aad(i,n-1) / scale
501 g = - sign( sqrt(h), wkd(n+m) )
503 wkd(n+m) = wkd(n+m) - g
508 f = f + wkd(i+m) * aad(i,j)
511 aad(i,j) = aad(i,j) - wkd(i+m) * f / h
518 f = f + wkd(j+m) * aad(i,j)
521 aad(i,j) = aad(i,j) - wkd(j+m) * f / h
524 wkd(n+m) = scale * wkd(n+m)
525 aad(n,n-1) = scale * g
529 DO 340 n = k-2, l, -1
533 IF ( f.NE.
zero )
THEN 542 g = g + wkd(i+m) * evecd(i,j)
546 evecd(i,j) = evecd(i,j) + g * wkd(i+m)
557 rnorm = rnorm + abs(aad(i,j))
560 IF ( i.LT.l .OR. i.GT.k ) evald(i) = aad(i,i)
565 380
IF ( n.LT.l )
GO TO 530
573 IF ( lb.EQ.l )
GO TO 410
574 s = abs( aad(lb-1,lb-1) ) + abs( aad(lb,lb) )
575 IF ( s.EQ.
zero ) s = rnorm
576 IF ( abs(aad(lb,lb-1)) .LE. tol*s )
GO TO 410
589 w = aad(n,n1) * aad(n1,n)
602 IF ( z.NE.
zero ) evald(n) = x - w / z
606 r = sqrt( x*x + z*z )
612 aad(n1,j) = q * z + p * aad(n,j)
613 aad(n,j) = q * aad(n,j) - p * z
618 aad(i,n1) = q * z + p * aad(i,n)
619 aad(i,n) = q * aad(i,n) - p * z
624 evecd(i,n1) = q * z + p * evecd(i,n)
625 evecd(i,n) = q * evecd(i,n) - p * z
639 IF ( in.EQ.10 .OR. in.EQ.20 )
THEN 642 aad(i,i) = aad(i,i) - x
644 s = abs(aad(n,n1)) + abs(aad(n1,n2))
658 p = ( r * s - w ) / aad(i+1,i) + aad(i,i+1)
659 q = aad(i+1,i+1) - z - r - s
661 s = abs(p) + abs(q) + abs(r)
665 IF ( i.EQ.lb )
GO TO 470
666 uu = abs( aad(i,i-1) ) * ( abs(q) + abs(r) )
667 vv = abs(p)*(abs(aad(i-1,i-1))+abs(z)+abs(aad(i+1,i+1)))
668 IF ( uu .LE. tol*vv )
GO TO 470
683 s = sign( sqrt( p*p + q*q + r*r ), p )
684 IF ( lb.NE.i ) aad(ka,ka-1) = - aad(ka,ka-1)
689 IF ( notlas ) r = aad(ka+2,ka-1)
690 x = abs(p) + abs(q) + abs(r)
691 IF ( x.EQ.
zero )
GO TO 520
695 s = sign( sqrt( p*p + q*q + r*r ), p )
696 aad(ka,ka-1) = - s * x
706 p = aad(ka,j) + q * aad(ka+1,j)
708 p = p + r * aad(ka+2,j)
709 aad(ka+2,j) = aad(ka+2,j) - p * z
711 aad(ka+1,j) = aad(ka+1,j) - p * y
712 aad(ka,j) = aad(ka,j) - p * x
715 DO 500 ii = 1, min0(n,ka+3)
716 p = x * aad(ii,ka) + y * aad(ii,ka+1)
718 p = p + z * aad(ii,ka+2)
719 aad(ii,ka+2) = aad(ii,ka+2) - p * r
721 aad(ii,ka+1) = aad(ii,ka+1) - p * q
722 aad(ii,ka) = aad(ii,ka) - p
726 p = x * evecd(ii,ka) + y * evecd(ii,ka+1)
728 p = p + z * evecd(ii,ka+2)
729 evecd(ii,ka+2) = evecd(ii,ka+2) - p * r
731 evecd(ii,ka+1) = evecd(ii,ka+1) - p * q
732 evecd(ii,ka) = evecd(ii,ka) - p
739 IF ( rnorm.NE.
zero )
THEN 743 DO 550 i = n-1, 1, -1
744 w = aad(i,i) - evald(n)
745 IF ( w.EQ.
zero ) w = tol * rnorm
748 r = r + aad(i,j) * aad(j,n)
757 IF ( i.LT.l .OR. i.GT.k )
THEN 759 evecd(i,j) = aad(i,j)
768 DO 590 n = l, min0(j,k)
769 z = z + evecd(i,n) * aad(n,j)
780 evecd(i,j) = evecd(i,j) * wkd(i)
784 DO 640 i = l-1, 1, -1
789 evecd(i,n) = evecd(j,n)
800 evecd(i,n) = evecd(j,n)
812 nor_factor = nor_factor + evecd(i,j)**2
814 nor_factor = sqrt(nor_factor)
815 evecd(:,j) = evecd(:,j)/nor_factor
821 SUBROUTINE asymtx_tl( nZ, V, VAL, A_TL, V_TL, VAL_TL, Error_Status)
823 INTEGER :: nz,error_status
824 REAL(fp),
DIMENSION(:,:) :: v, a_tl, v_tl
825 REAL(fp),
DIMENSION(:) :: val, val_tl
826 REAL(fp),
DIMENSION(nZ,nZ) :: v_int, a1_tl
829 CHARACTER(*),
PARAMETER :: routine_name =
'ASYMTX_TL' 830 CHARACTER(256) :: message
832 v_int =
matinv( v(1:nz,1:nz), error_status )
833 IF( error_status /=
success )
THEN 834 WRITE( message,
'("Error in matrix inversion matinv( V(1:nZ,1:nZ), Error_Status ) ")' )
842 a1_tl = matmul( v_int, matmul(a_tl, v) )
848 val_tl(i) = a1_tl(i,i)
852 v_tl(i,j) = a1_tl(i,j)/(val(j)-val(i))
864 a1_tl = matmul( v, v_tl)
870 b_tl = b_tl - v(j,i)*a1_tl(j,i)
874 v_tl(j,i) = a1_tl(j,i) + v(j,i)*b_tl
882 SUBROUTINE asymtx_ad( nZ, V, VAL, V_AD, VAL_AD, A_AD, Error_Status)
884 INTEGER :: nz,error_status
885 REAL(fp),
DIMENSION(:,:) :: v, v_ad, a_ad
886 REAL(fp),
DIMENSION(:) :: val, val_ad
888 REAL(fp),
DIMENSION(nZ,nZ) :: v_int, a1_ad
889 CHARACTER(*),
PARAMETER :: routine_name =
'ASYMTX_AD' 890 CHARACTER(256) :: message
898 a1_ad(k,j) = a1_ad(k,j) + v(i,k)*v_ad(i,j)/(val(j)-val(k))
902 a1_ad(i,i) = a1_ad(i,i) + val_ad(i)
904 v_int =
matinv( v(1:nz,1:nz), error_status )
905 IF( error_status /=
success )
THEN 906 WRITE( message,
'("Error in matrix inversion matinv( V(1:nZ,1:nZ), Error_Status ) ")' )
913 a_ad = matmul( transpose(v_int), matmul(a1_ad, transpose(v) ) )
918 SUBROUTINE asymtx2_ad( COS_Angle,n_streams, nZ, V, VAL, V_AD, VAL_AD, A_AD, Error_Status)
920 INTEGER :: nz,error_status
921 REAL(fp),
DIMENSION(:,:) :: v, v_ad, a_ad
922 REAL(fp),
DIMENSION(:) :: val, val_ad
923 INTEGER :: i,j,n_streams,n
924 REAL(fp) :: cos_angle,d0,d1
925 REAL(fp),
DIMENSION(nZ,nZ) :: v_int, a1_ad
929 IF( nz /= n_streams )
THEN 937 d1 = abs( d0 - val(i) )
941 IF( n /= 0 ) val_ad(n) =
zero 949 b_ad = b_ad + v(j,i)*v_ad(j,i)
950 a1_ad(j,i) = v_ad(j,i)
955 a1_ad(j,i) = a1_ad(j,i) - v(j,i)*b_ad
963 v_ad = matmul( transpose(v), a1_ad)
969 IF( i /= j .and. j /= n )
THEN 971 a1_ad(i,j) = v_ad(i,j)/(val(j)-val(i))
979 a1_ad(i,i) = a1_ad(i,i) + val_ad(i)
982 v_int =
matinv( v(1:nz,1:nz), error_status )
985 a_ad = matmul( transpose(v_int), matmul(a1_ad, transpose(v) ) )
real(fp), parameter, public point_25
integer, parameter, public failure
real(fp), parameter, public zero
integer, parameter, public warning
subroutine, public legendre_m(MF, N, U, PL)
subroutine legendre_rank1(MOA, NU, ANG, PL)
integer, parameter, public fp
real(fp), parameter eigen_threshold
subroutine, public asymtx_tl(nZ, V, VAL, A_TL, V_TL, VAL_TL, Error_Status)
character(*), parameter module_version_id
subroutine, public asymtx2_ad(COS_Angle, n_streams, nZ, V, VAL, V_AD, VAL_AD, A_AD, Error_Status)
real(fp), parameter, public one
recursive subroutine, public display_message(Routine_Name, Message, Error_State, Message_Log)
subroutine, public double_gauss_quadrature(NUM, ABSCISSAS, WEIGHTS)
real(fp) function gamma2(N)
real(fp), parameter, public two
real(fp), parameter, public point_5
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine READ_RECORD_CORE_(unit, field, nwords, data, start, axsiz) integer, intent(in) ::unit type(fieldtype), intent(in) ::field integer, intent(in) ::nwords MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in) ::start(:), axsiz(:) integer(SHORT_KIND) ::i2vals(nwords)!rab used in conjunction with transfer intrinsic to determine size of a variable integer(KIND=1) ::one_byte(8) integer ::word_sz!#ifdef __sgi integer(INT_KIND) ::ivals(nwords) real(FLOAT_KIND) ::rvals(nwords)!#else! integer ::ivals(nwords)! real ::rvals(nwords)!#endif real(DOUBLE_KIND) ::r8vals(nwords) pointer(ptr1, i2vals) pointer(ptr2, ivals) pointer(ptr3, rvals) pointer(ptr4, r8vals) if(mpp_io_stack_size< nwords) call mpp_io_set_stack_size(nwords) call mpp_error(FATAL, 'MPP_READ currently requires use_netCDF option') end subroutine READ_RECORD_CORE_ subroutine READ_RECORD_(unit, field, nwords, data, time_level, domain, position, tile_count, start_in, axsiz_in)!routine that is finally called by all mpp_read routines to perform the read!a non-netCDF record contains:! field ID! a set of 4 coordinates(is:ie, js:je) giving the data subdomain! a timelevel and a timestamp(=NULLTIME if field is static)! 3D real data(stored as 1D)!if you are using direct access I/O, the RECL argument to OPEN must be large enough for the above!in a global direct access file, record position on PE is given by %record.!Treatment of timestamp:! We assume that static fields have been passed without a timestamp.! Here that is converted into a timestamp of NULLTIME.! For non-netCDF fields, field is treated no differently, but is written! with a timestamp of NULLTIME. There is no check in the code to prevent! the user from repeatedly writing a static field. integer, intent(in) ::unit, nwords type(fieldtype), intent(in) ::field MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in), optional ::time_level type(domain2D), intent(in), optional ::domain integer, intent(in), optional ::position, tile_count integer, intent(in), optional ::start_in(:), axsiz_in(:) integer, dimension(size(field%axes(:))) ::start, axsiz integer ::tlevel !, subdomain(4) integer ::i, error, is, ie, js, je, isg, ieg, jsg, jeg type(domain2d), pointer ::io_domain=> tlevel if(PRESENT(start_in) .AND. PRESENT(axsiz_in)) then if(size(start(! the data domain and compute domain must refer to the subdomain being passed ! In this ! since that attempts to gather all data on PE size(field%axes(:)) axsiz(i)
subroutine legendre_scalar(MOA, ANG, PL)
subroutine, public asymtx(AAD, M, IA, IEVEC, EVECD, EVALD, IER)
integer, parameter, public success
real(fp) function, dimension(size(a, 1), size(a, 2)), public matinv(A, Error_Status)
real(fp), parameter, public pi
subroutine, public asymtx_ad(nZ, V, VAL, V_AD, VAL_AD, A_AD, Error_Status)