72 REAL(
sp) :: weights(4,2)
73 INTEGER :: quad_num(4,2)
79 INTEGER,
ALLOCATABLE :: index(:)
80 TYPE(
r2pts),
ALLOCATABLE:: ptw(:)
85 INTEGER,
POINTER :: n_index(:,:)
86 INTEGER,
POINTER :: n_cnt(:)
87 INTEGER,
POINTER :: n_order(:)
118 IF(.not.
ASSOCIATED(myw))
RETURN 120 IF(
ALLOCATED(myw%INDEX))
DEALLOCATE(myw%INDEX)
122 IF(
ALLOCATED(myw%PTW))
DEALLOCATE(myw%PTW)
124 IF(
ASSOCIATED(myw%N_INDEX))
DEALLOCATE(myw%N_INDEX)
125 IF(
ASSOCIATED(myw%N_CNT))
DEALLOCATE(myw%N_CNT)
126 IF(
ASSOCIATED(myw%N_ORDER))
DEALLOCATE(myw%N_ORDER)
127 IF(
ASSOCIATED(myw%N_FOUND))
DEALLOCATE(myw%N_FOUND)
137 CHARACTER(LEN=*) :: STR
140 WRITE(ipt,*)
"===== PRINTING WEIGHTS:"//trim(str)//
"========" 142 WRITE(ipt,*)
"Nin=",myw%Nin
143 WRITE(ipt,*)
"Nout=",myw%Nout
144 IF(
ALLOCATED(myw%index))
THEN 145 WRITE(ipt,*)
"Size(index)=",
size(myw%index)
147 WRITE(ipt,*)
"Index not allocated!" 150 IF(
ALLOCATED(myw%PTW))
THEN 155 WRITE(ipt,*)
"PTW not ALLOCATED!" 158 WRITE(ipt,*)
"NType=",myw%N_TYPE
160 IF(
Associated(myw%N_INDEX))
THEN 161 WRITE(ipt,*)
"Size(N_INDEX)=",
size(myw%N_INDEX)
163 WRITE(ipt,*)
"N_INDEX not allocated!" 166 IF(
Associated(myw%N_CNT))
THEN 167 WRITE(ipt,*)
"Size(N_CNT)=",
size(myw%N_CNT)
169 WRITE(ipt,*)
"N_CNT not allocated!" 172 IF(
Associated(myw%N_ORDER))
THEN 173 WRITE(ipt,*)
"Size(N_ORDER)=",
size(myw%N_ORDER)
175 WRITE(ipt,*)
"N_ORDER not allocated!" 178 IF(
Associated(myw%N_FOUND))
THEN 179 WRITE(ipt,*)
"Size(N_FOUND)=",
size(myw%N_FOUND)
181 WRITE(ipt,*)
"N_FOUND not allocated!" 184 WRITE(ipt,*)
"========== END WEIGHTS ========" 193 WRITE(ipt,*)
"===== PRINTING PTW#",cnt
194 WRITE(ipt,*)
"WEIGHTS=" 195 WRITE(ipt,
'(4F12.6)')ptw%WEIGHTS(:,1)
196 WRITE(ipt,
'(4F12.6)')ptw%WEIGHTS(:,2)
197 WRITE(ipt,*)
"QUADNUM=" 198 WRITE(ipt,
'(4I8)')ptw%QUAD_NUM(:,1)
199 WRITE(ipt,
'(4I8)')ptw%QUAD_NUM(:,2)
213 SUBROUTINE get_loc(X_bnd,Y_bnd,msze,nsze,RSQ,MASK,X,Y,BOX,CONDITION)
215 REAL(SP),
POINTER,
INTENT(IN) :: X_bnd(:,:)
216 REAL(SP),
POINTER,
INTENT(IN) :: Y_bnd(:,:)
217 REAL(SP),
INTENT(IN) :: X,Y
218 INTEGER,
INTENT(IN) :: MSZE,NSZE
219 REAL(SP),
POINTER :: Rsq(:,:)
220 INTEGER,
POINTER,
INTENT(IN) :: MASK(:,:)
223 INTEGER,
INTENT(OUT) :: BOX(4,2)
224 INTEGER,
INTENT(OUT) :: CONDITION
226 INTEGER :: MISSING(4)
228 INTEGER,
DIMENSION(2) :: NN, NNT
229 INTEGER :: err,I,j,CNT
234 REAL(SP),
POINTER::XIN(:,:),YIN(:,:)
236 xin => x_bnd(1:msze,1:nsze)
237 yin => y_bnd(1:msze,1:nsze)
289 IF(
ASSOCIATED(mask))then;
292 rsq = (xin -x)**2 + (yin -y)**2
295 nn = minloc(rsq,rsq>-1.0_sp)
299 rsq = (xin -x)**2 + (yin -y)**2
301 nn = minloc(rsq,rsq>-1.0_sp)
315 box =
get_box(x,y,nn,x_bnd,y_bnd,err)
322 ptest = rsq(nnt(1),nnt(2))
323 nnt = minloc(rsq,rsq>ptest)
330 box =
get_box(x,y,nnt,x_bnd,y_bnd,err)
342 IF(
ASSOCIATED(mask))
THEN 354 xn = x_bnd(nn(1),nn(2))
355 yn = y_bnd(nn(1),nn(2))
358 write(ipt,*)
"Error searching for Bilinear Interpolation to Point:" 359 write(ipt,*)
"X=",x,
"; Y=",y
360 write(ipt,*)
"Found Nearest Grid index:",nn
361 write(ipt,*)
"Bounds(",msze,nsze,
")" 362 write(ipt,*)
"Grid location:",xn,yn
367 CALL fatal_error(
"Could not find the triangle of the four nearest nodes",&
368 &
"containing the point x,y ?")
383 box(:,1) = mod(box(:,1),msze+1)
385 box(:,2) = mod(box(:,2),nsze+1)
388 IF(
ASSOCIATED(mask))
THEN 392 IF(box(i,1)*box(i,2)==0)
THEN 401 IF(mask(box(i,1),box(i,2))==1)
THEN 409 select case(sum(missing))
411 IF(all(missing ==(/0,0,0,1/)) )
THEN 413 ELSEIF(all(missing ==(/0,0,1,0/)) )
THEN 415 ELSEIF(all(missing ==(/0,1,0,0/)) )
THEN 417 ELSEIF(all(missing ==(/1,0,0,0/)) )
THEN 423 IF(all(missing == (/1,0,1,0/)) )
THEN 425 ELSEIF(all(missing == (/0,1,0,1/)) )
THEN 427 ELSEIF(all(missing ==(/1,1,0,0/)) )
THEN 429 ELSEIF(all(missing ==(/0,1,1,0/)) )
THEN 431 ELSEIF(all(missing ==(/0,0,1,1/)) )
THEN 433 ELSEIF(all(missing ==(/1,0,0,1/)) )
THEN 439 IF(all(missing ==(/1,1,1,0/)) )
THEN 441 ELSEIF(all(missing ==(/1,1,0,1/)) )
THEN 443 ELSEIF(all(missing ==(/1,0,1,1/)) )
THEN 445 ELSEIF(all(missing ==(/0,1,1,1/)) )
THEN 451 (
"THE LAND MASK HAS LEFT NO VALID POINTS - THIS SHOULD BE IMPOSSIBLE!")
464 IF(count(box==0)==2)
THEN 467 IF(box(1,1) == 0) condition = 8
468 IF(box(1,2) == 0) condition = 6
469 IF(box(3,1) == 0) condition = 4
470 IF(box(3,2) == 0) condition = 2
476 IF(product(box(i,:))==0) box(i,:)=0
480 IF(count(box==0)==6)
THEN 482 IF(box(1,1) /= 0) condition = 3
483 IF(box(2,1) /= 0) condition = 1
484 IF(box(3,1) /= 0) condition = 7
485 IF(box(4,1) /= 0) condition = 5
498 FUNCTION get_box(X,Y,NN,X_bnd,Y_bnd,err)
RESULT(BOX)
500 REAL(
sp),
POINTER,
INTENT(IN) :: x_bnd(:,:)
501 REAL(
sp),
POINTER,
INTENT(IN) :: y_bnd(:,:)
502 REAL(
sp),
INTENT(IN) :: x,y
503 INTEGER,
INTENT(IN):: nn(2)
504 INTEGER,
INTENT(OUT) :: err
508 REAL(
sp) :: xn,yn,xt(3),yt(3)
519 tn(1,:) = (/ 1 , 0 /)
520 tn(2,:) = (/ 0 , 1 /)
521 tn(3,:) = (/-1 , 0 /)
522 tn(4,:) = (/ 0 ,-1 /)
525 tno(1,:) = (/ 1 , 1 /)
526 tno(2,:) = (/-1 , 1 /)
527 tno(3,:) = (/-1 ,-1 /)
528 tno(4,:) = (/ 1 ,-1 /)
531 bn(1,:) = (/ 0 , 1 /)
532 bn(2,:) = (/ 1 , 1 /)
533 bn(3,:) = (/ 1 , 0 /)
534 bn(4,:) = (/ 0 , 0 /)
537 dn(1,:) = (/ 0 , 0 /)
538 dn(2,:) = (/-1 , 0 /)
539 dn(3,:) = (/-1 ,-1 /)
540 dn(4,:) = (/ 0 ,-1 /)
543 xt(1) = x_bnd(nn(1),nn(2))
545 yt(1) = y_bnd(nn(1),nn(2))
556 xt(2) = x_bnd(nn(1)+tn(i,1),nn(2)+tn(i,2))
557 yt(2) = y_bnd(nn(1)+tn(i,1),nn(2)+tn(i,2))
559 xt(3) = x_bnd(nn(1)+tn(j,1),nn(2)+tn(j,2))
560 yt(3) = y_bnd(nn(1)+tn(j,1),nn(2)+tn(j,2))
573 bn(:,1) = bn(:,1) + dn(i,1)
574 bn(:,2) = bn(:,2) + dn(i,2)
576 box(:,1) = bn(:,1) + nn(1)
577 box(:,2) = bn(:,2) + nn(2)
592 xt(1) = x_bnd(nn(1)+tno(i,1),nn(2)+tno(i,2))
593 yt(1) = y_bnd(nn(1)+tno(i,1),nn(2)+tno(i,2))
597 xt(2) = x_bnd(nn(1)+tn(i,1),nn(2)+tn(i,2))
598 yt(2) = y_bnd(nn(1)+tn(i,1),nn(2)+tn(i,2))
600 xt(3) = x_bnd(nn(1)+tn(j,1),nn(2)+tn(j,2))
601 yt(3) = y_bnd(nn(1)+tn(j,1),nn(2)+tn(j,2))
614 bn(:,1) = bn(:,1) + dn(i,1)
615 bn(:,2) = bn(:,2) + dn(i,2)
617 box(:,1) = bn(:,1) + nn(1)
618 box(:,2) = bn(:,2) + nn(2)
633 REAL(SP),
ALLOCATABLE,
TARGET,
INTENT(IN) :: Xin(:,:)
634 REAL(SP),
ALLOCATABLE,
TARGET,
INTENT(IN) :: Yin(:,:)
635 REAL(SP),
ALLOCATABLE,
TARGET,
INTENT(IN) :: Xout(:)
636 REAL(SP),
ALLOCATABLE,
TARGET,
INTENT(IN) :: Yout(:)
640 INTEGER,
OPTIONAL,
ALLOCATABLE,
TARGET,
INTENT(IN) :: LAND_MASK(:,:)
642 REAL(SP),
POINTER :: XinP(:,:)
643 REAL(SP),
POINTER :: YinP(:,:)
644 REAL(SP),
POINTER :: XoutP(:)
645 REAL(SP),
POINTER :: YoutP(:)
647 INTEGER,
POINTER :: LAND_MASKP(:,:)
649 NULLIFY(xinp,yinp,xoutp,youtp,land_maskp)
652 IF(
ALLOCATED(xin)) xinp => xin
654 IF(
ALLOCATED(yin)) yinp => yin
656 IF(
ALLOCATED(xout)) xoutp => xout
658 IF(
ALLOCATED(yout)) youtp => yout
660 IF(
PRESENT(land_mask))
THEN 662 IF(
ALLOCATED(land_mask))
THEN 663 land_maskp => land_mask
665 CALL fatal_error(
"PASSED LAND_MASK BUT IT IS NOT ALLOCATED")
679 REAL(SP),
POINTER,
INTENT(IN) :: Xin(:,:)
680 REAL(SP),
POINTER,
INTENT(IN) :: Yin(:,:)
681 REAL(SP),
POINTER,
INTENT(IN) :: Xout(:)
682 REAL(SP),
POINTER,
INTENT(IN) :: Yout(:)
685 INTEGER,
OPTIONAL,
POINTER,
INTENT(IN) :: LAND_MASK(:,:)
687 INTEGER,
POINTER :: MASK(:,:)
689 INTEGER,
POINTER :: N_INDEX(:,:)
690 INTEGER,
POINTER :: N_FOUND(:)
691 INTEGER,
POINTER :: N_CNT(:)
692 INTEGER,
POINTER :: N_ORDER(:)
698 INTEGER :: I, J, status, lb, ub, msze,nsze
705 REAL(SP) :: DRA,DRB,DRT
711 REAL(SP) :: ARCX1, ARCX2,ARCX3
713 REAL(SP),
POINTER::X_bnd(:,:),Y_bnd(:,:),RSQ(:,:)
715 LOGICAL :: BOUNDS_FLAG = .false.
722 if(.not.
associated(xin))
CALL fatal_error(
"SETUP_INTERP: INPUT ARGU& 723 &MENTS MUST BE ALLOCATED!")
724 if(.not.
associated(yin))
CALL fatal_error(
"SETUP_INTERP: INPUT ARGU& 725 &MENTS MUST BE ALLOCATED!")
726 if(.not.
associated(xout))
CALL fatal_error(
"SETUP_INTERP: INPUT ARGU& 727 &MENTS MUST BE ALLOCATED!")
728 if(.not.
associated(yout))
CALL fatal_error(
"SETUP_INTERP: INPUT ARGU& 729 &MENTS MUST BE ALLOCATED!")
731 bounds_flag = .false.
740 weights%Nout= ubound(xout,1)
744 weights%Nin = msze*nsze
748 ALLOCATE(weights%PTW(weights%Nout), stat=status)
749 IF(status /= 0)
CALL fatal_error(
"SETUP_INTERP: COULD NOT ALLOCATE SPACE")
752 ALLOCATE(rsq(msze,nsze)); rsq = 0.0_sp
753 ALLOCATE(x_bnd(0:msze+1,0:nsze+1)); x_bnd=0.0_sp
754 ALLOCATE(y_bnd(0:msze+1,0:nsze+1)); y_bnd=0.0_sp
762 x_bnd(1:msze,1:nsze)=xin
765 x_bnd(0,:) = 2*x_bnd(1,:) - x_bnd(msze,:)
766 x_bnd(msze+1,:) = 2*x_bnd(msze,:) - x_bnd(1,:)
768 x_bnd(:,0) = x_bnd(:,1)
769 x_bnd(:,nsze+1) = x_bnd(:,nsze)
772 y_bnd(1:msze,1:nsze)=yin
775 y_bnd(0,:) = y_bnd(1,:)
776 y_bnd(msze+1,:) = y_bnd(msze,:)
778 y_bnd(:,0) = 2*y_bnd(:,1) - y_bnd(:,nsze)
779 y_bnd(:,nsze+1) = 2*y_bnd(:,nsze) - y_bnd(:,1)
784 y_bnd(0,0) = y_bnd(1,0)
785 y_bnd(msze+1,0) = y_bnd(msze,0)
787 y_bnd(0,nsze+1) = y_bnd(1,nsze+1)
788 y_bnd(msze+1,nsze+1) = y_bnd(msze,nsze+1)
790 x_bnd(0,0) = x_bnd(0,1)
791 x_bnd(msze+1,0) = x_bnd(msze+1,1)
793 x_bnd(0,nsze+1) = x_bnd(0,nsze)
794 x_bnd(msze+1,nsze+1) = x_bnd(msze+1,nsze)
825 IF(
PRESENT(land_mask))
THEN 829 &(
"BILINEAR INTERP CAN NOT WORK WITH EVERY POINT MASKED")
832 &(
"BILINEAR INTERP MASK VALUES ARE INCORRECT:",&
833 &
"SET 1 FOR MASKED (LAND)",&
834 &
"SET 0 FOR UNMASKED (VALID/OCEAN)")
836 IF(all(mask==0))
NULLIFY(mask)
839 IF(weights%Nout == mt)
THEN 842 &(
"CAN NOD USE MASK FOR A GRID VARIABLE WITHOUT RUNNING TGE FIRST")
846 ALLOCATE(n_index(ubound(
nbsn,1),ubound(
nbsn,2))); n_index=0
847 ALLOCATE(n_found(0:mt)); n_found=0
848 ALLOCATE(n_cnt(m)); n_cnt=0
850 IF(par)
call warning(
"Possible interpolation using land mask",&
851 &
"This procedure works in parallel but may not report"&
852 &,
"Domain boundary errors which stop the code",&
853 &
"If your code stops with no message try running single processor mode")
856 ELSEIF(weights%Nout == nt)
THEN 859 &(
"CAN NOD USE MASK FOR A GRID VARIABLE WITHOUT RUNNING TGE FIRST")
862 ALLOCATE(n_index(n,3)); n_index=0
863 ALLOCATE(n_found(0:nt)); n_found=0
864 ALLOCATE(n_cnt(n)); n_cnt=0
866 IF(par)
call warning(
"Possible interpolation using land mask",&
867 &
"This procedure works in parallel but may not report"&
868 &,
"Domain boundary errors which stop the code",&
869 &
"If your code stops with no message try running single processor mode")
887 CALL get_loc(x_bnd,y_bnd,msze,nsze,rsq,mask,x,y,box,condition)
942 weights%PTW(i)%QUAD_NUM= box
943 weights%PTW(i)%WEIGHTS = 0.0_sp
947 IF(condition/=0) bounds_flag = .true.
950 SELECT CASE(condition)
956 dxt = (xin(box(2,1),box(2,2)) - xin(box(1,1),box(1,2)))
958 dxb = (xin(box(4,1),box(4,2)) - xin(box(3,1),box(3,2)))
961 dyt = (yin(box(2,1),box(2,2)) - yin(box(1,1),box(1,2)))
963 dyb = (yin(box(4,1),box(4,2)) - yin(box(3,1),box(3,2)))
970 IF(abs(dyt) <
tb_tol/2._sp *abs(dxt) .and. abs(dyb) <
tb_tol/2._sp *abs(dxb))
THEN 973 xbox(1) = xin(box(1,1),box(1,2))
974 xbox(2) = xin(box(2,1),box(2,2))
975 xbox(3) = xin(box(3,1),box(3,2))
976 xbox(4) = xin(box(4,1),box(4,2))
978 ybox(1) = yin(box(1,1),box(1,2))
979 ybox(2) = yin(box(2,1),box(2,2))
980 ybox(3) = yin(box(3,1),box(3,2))
981 ybox(4) = yin(box(4,1),box(4,2))
987 weights%PTW(i)%WEIGHTS(1,1) = wghts(1)
988 weights%PTW(i)%WEIGHTS(2,1) = wghts(2)
989 weights%PTW(i)%WEIGHTS(3,1) = wghts(3)
990 weights%PTW(i)%WEIGHTS(4,1) = wghts(4)
995 IF(abs(dyt) >
tb_tol *abs(dxt))
THEN 997 &(
"THIS CURVALINEAR MESH HAS CELLS WHICH ARE TOO EXTREME FOR THIS METHOD",&
998 &
"PLEASE EXAMINE TOP_DIR/testing/interp",&
999 &
"IF YOU WOULD LIKE TO ADD SUPPORT FOR EXTREME CURVALINEAR INTERPOLATION")
1065 weights%PTW(i)%WEIGHTS(2,1) = 1.0_sp
1070 weights%PTW(i)%WEIGHTS(1,1)= (xin(box(2,1),box(2,2)) - x)/(xin(box(2,1),box(2,2)) - xin(box(1,1),box(1,2)))
1072 weights%PTW(i)%WEIGHTS(2,1)= (x - xin(box(1,1),box(1,2)))/(xin(box(2,1),box(2,2)) - xin(box(1,1),box(1,2)))
1078 weights%PTW(i)%WEIGHTS(1,1) = 1.0_sp
1083 weights%PTW(i)%WEIGHTS(1,1)= (yin(box(4,1),box(4,2)) - y)/(yin(box(4,1),box(4,2)) - yin(box(1,1),box(1,2)))
1085 weights%PTW(i)%WEIGHTS(4,1)= (y - yin(box(1,1),box(1,2)))/(yin(box(4,1),box(4,2)) - yin(box(1,1),box(1,2)))
1090 weights%PTW(i)%WEIGHTS(4,1) = 1.0_sp
1094 weights%PTW(i)%WEIGHTS(3,1)= (xin(box(4,1),box(4,2)) - x)/(xin(box(4,1),box(4,2)) - xin(box(3,1),box(3,2)))
1096 weights%PTW(i)%WEIGHTS(4,1)= (x - xin(box(3,1),box(3,2)))/(xin(box(4,1),box(4,2)) - xin(box(3,1),box(3,2)))
1101 weights%PTW(i)%WEIGHTS(3,1) = 1.0_sp
1106 weights%PTW(i)%WEIGHTS(2,1)= (y - yin(box(3,1),box(3,2)))/(yin(box(2,1),box(2,2)) - yin(box(3,1),box(3,2)))
1108 weights%PTW(i)%WEIGHTS(3,1)= (yin(box(2,1),box(2,2)) - y)/(yin(box(2,1),box(2,2)) - yin(box(3,1),box(3,2)))
1115 xbox(1) = x_bnd(box(1,1),box(1,2))
1116 xbox(2) = x_bnd(box(2,1),box(2,2))
1117 xbox(3) = x_bnd(box(3,1),box(3,2))
1118 xbox(4) = x_bnd(box(4,1),box(4,2))
1120 ybox(1) = y_bnd(box(1,1),box(1,2))
1121 ybox(2) = y_bnd(box(2,1),box(2,2))
1122 ybox(3) = y_bnd(box(3,1),box(3,2))
1123 ybox(4) = y_bnd(box(4,1),box(4,2))
1127 weights%PTW(i)%WEIGHTS(1,1) = wghts(1)
1128 weights%PTW(i)%WEIGHTS(2,1) = wghts(2)
1129 weights%PTW(i)%WEIGHTS(3,1) = wghts(3)
1130 weights%PTW(i)%WEIGHTS(4,1) = wghts(4)
1135 box = cshift(box,-1)
1137 xbox(1) = x_bnd(box(1,1),box(1,2))
1138 xbox(2) = x_bnd(box(2,1),box(2,2))
1139 xbox(3) = x_bnd(box(3,1),box(3,2))
1140 xbox(4) = x_bnd(box(4,1),box(4,2))
1142 ybox(1) = y_bnd(box(1,1),box(1,2))
1143 ybox(2) = y_bnd(box(2,1),box(2,2))
1144 ybox(3) = y_bnd(box(3,1),box(3,2))
1145 ybox(4) = y_bnd(box(4,1),box(4,2))
1149 wghts = cshift(wghts,1)
1151 weights%PTW(i)%WEIGHTS(1,1) = wghts(1)
1152 weights%PTW(i)%WEIGHTS(2,1) = wghts(2)
1153 weights%PTW(i)%WEIGHTS(3,1) = wghts(3)
1154 weights%PTW(i)%WEIGHTS(4,1) = wghts(4)
1161 box = cshift(box,-2)
1163 xbox(1) = x_bnd(box(1,1),box(1,2))
1164 xbox(2) = x_bnd(box(2,1),box(2,2))
1165 xbox(3) = x_bnd(box(3,1),box(3,2))
1166 xbox(4) = x_bnd(box(4,1),box(4,2))
1168 ybox(1) = y_bnd(box(1,1),box(1,2))
1169 ybox(2) = y_bnd(box(2,1),box(2,2))
1170 ybox(3) = y_bnd(box(3,1),box(3,2))
1171 ybox(4) = y_bnd(box(4,1),box(4,2))
1175 wghts = cshift(wghts,2)
1177 weights%PTW(i)%WEIGHTS(1,1) = wghts(1)
1178 weights%PTW(i)%WEIGHTS(2,1) = wghts(2)
1179 weights%PTW(i)%WEIGHTS(3,1) = wghts(3)
1180 weights%PTW(i)%WEIGHTS(4,1) = wghts(4)
1187 box = cshift(box,-3)
1190 xbox(1) = x_bnd(box(1,1),box(1,2))
1191 xbox(2) = x_bnd(box(2,1),box(2,2))
1192 xbox(3) = x_bnd(box(3,1),box(3,2))
1193 xbox(4) = x_bnd(box(4,1),box(4,2))
1195 ybox(1) = y_bnd(box(1,1),box(1,2))
1196 ybox(2) = y_bnd(box(2,1),box(2,2))
1197 ybox(3) = y_bnd(box(3,1),box(3,2))
1198 ybox(4) = y_bnd(box(4,1),box(4,2))
1202 wghts = cshift(wghts,3)
1204 weights%PTW(i)%WEIGHTS(1,1) = wghts(1)
1205 weights%PTW(i)%WEIGHTS(2,1) = wghts(2)
1206 weights%PTW(i)%WEIGHTS(3,1) = wghts(3)
1207 weights%PTW(i)%WEIGHTS(4,1) = wghts(4)
1213 dra = sqrt( (x_bnd(box(2,1),box(2,2)) - x)**2 + (y_bnd(box(2,1),box(2,2)) - y)**2)
1214 drb = sqrt( (x_bnd(box(4,1),box(4,2)) - x)**2 + (y_bnd(box(4,1),box(4,2)) - y)**2)
1220 weights%PTW(i)%WEIGHTS(2,1) = drb/drt
1222 weights%PTW(i)%WEIGHTS(4,1) = dra/drt
1227 dra = sqrt( (x_bnd(box(1,1),box(1,2)) - x)**2 + (y_bnd(box(1,1),box(1,2)) - y)**2)
1228 drb = sqrt( (x_bnd(box(3,1),box(3,2)) - x)**2 + (y_bnd(box(3,1),box(3,2)) - y)**2)
1235 weights%PTW(i)%WEIGHTS(1,1) = drb/drt
1237 weights%PTW(i)%WEIGHTS(3,1) = dra/drt
1251 weights%PTW(i)%QUAD_NUM = 0
1253 &(
"INTERPOLATION WITH MASK: ERORR!",&
1254 &
"NEARST MESH NEIGHBOR SEARCH CAN NOT WORK WHEN THE MASK COVERS A DOMAIN BOUNDARY!")
1258 weights%PTW(i)%QUAD_NUM = 0
1260 &(
"INTERPOLATION WITH MASK: ERORR!",&
1261 &
"NEARST MESH NEIGHBOR SEARCH CAN NOT WORK WHEN THE MASK COVERS A DOMAIN BOUNDARY!")
1265 weights%PTW(i)%WEIGHTS(1,1) = 1.0_sp
1266 weights%PTW(i)%QUAD_NUM(2:4,:) = 0
1274 CALL fatal_error(
"SETUP_INTERP_BILINEAR: INVALID CONDITION" )
1284 IF(any(n_found < 0))
THEN 1287 &(
"FVCOM ATTEMPTING TO GUESS VALUES FOR A REGION WHERE ALL DATA ARE MASKED",&
1288 &
"PLEASE CHECK RESULTS CAREFULLY AND GET BETTER DATA IF POSSIBLE")
1290 mk_cnt = abs(sum(n_found))
1293 ALLOCATE(n_order(mk_cnt))
1301 weights%N_INDEX => n_index
1302 weights%N_CNT => n_cnt
1303 weights%N_ORDER => n_order
1304 weights%N_FOUND => n_found
1320 IF(any(n_found < 0))
THEN 1322 &(
"FVCOM ATTEMPTING TO GUESS VALUES FOR A REGION WHERE ALL DATA ARE MASKED",&
1323 &
"PLEASE CHECK RESULTS CAREFULLY AND GET BETTER DATA IF POSSIBLE")
1325 mk_cnt = abs(sum(n_found))
1328 ALLOCATE(n_order(mk_cnt))
1336 weights%N_INDEX => n_index
1337 weights%N_CNT => n_cnt
1338 weights%N_ORDER => n_order
1339 weights%N_FOUND => n_found
1359 WRITE(ipt,*)
"///////////////////////////////////////////////////" 1360 WRITE(ipt,*)
"//// TIMING REPORT FROM BILINEAR INTERP ///////////" 1361 WRITE(ipt,*)
"///////////////////////////////////////////////////" 1371 WRITE(ipt,*)
"///////////////////////////////////////////////////" 1380 &(
"FVCOM GRID IS OUT OF BOUNDS FOR FORCING",&
1381 &
"USING CONSTANT VALUE OUTSIDE OF FORCING REGION")
1386 SUBROUTINE interp_0(Xbox,Ybox,X,Y,wghts)
1389 REAL(SP),
INTENT(IN) :: Xbox(4)
1390 REAL(SP),
INTENT(IN) :: Ybox(4)
1391 REAL(SP),
INTENT(IN) :: X
1392 REAL(SP),
INTENT(IN) :: Y
1393 REAL(SP),
INTENT(OUT) :: wghts(4)
1397 REAL(SP) :: AB,BB,AT,BT
1398 REAL(SP) :: AL,BL,AR,BR
1401 REAL(SP) :: DXL, DXR, DXT, DXB
1402 REAL(SP) :: DYL, DYR, DYT, DYB
1405 REAL(sp) :: XT,YT,XB,YB
1410 REAL(SP) :: DYM, DXM
1412 REAL(SP) :: RADL,RADR,RADM
1415 REAL(SP) :: DR1, DR2,DR3,DR4,DR5,DR6
1416 REAL(SP) :: DRM,DRT,DRB
1421 dxt = xbox(2) - xbox(1)
1423 dxb = xbox(4) - xbox(3)
1425 dxl = xbox(1) - xbox(4)
1427 dxr = xbox(2) - xbox(3)
1430 dyt = ybox(2) - ybox(1)
1432 dyb = ybox(4) - ybox(3)
1434 dyl = ybox(1) - ybox(4)
1436 dyr = ybox(2) - ybox(3)
1441 bt = ybox(2) - at*xbox(2)
1447 bb = ybox(4) - ab*xbox(4)
1459 IF(abs(dyl) <
lr_tol * abs(dxl) .OR. abs(dyr) <
lr_tol*abs(dxr) )
THEN 1463 IF(abs(dyl) >
lr_tol * abs(dxl))
THEN 1464 xla = max(xbox(1),xbox(4))
1468 bl = ybox(4) - al*xbox(4)
1474 IF(abs(dyr) >
lr_tol * abs(dxr))
THEN 1475 xra = min(xbox(2),xbox(3))
1479 br = ybox(2) - ar*xbox(2)
1491 radl = atan2(dyl,dxl)
1492 radr = atan2(dyr,dxr)
1499 radm = (xla -xt)*(radr)/(xla-xra) + (xt - xra)*radl/(xla-xra)
1509 xt = (bt-bm)/(am - at)
1511 xb = (bb-bm)/(am - ab)
1535 drt = sqrt(dxt**2+ dyt**2)
1536 drb = sqrt(dxb**2+ dyb**2)
1539 dr1 = sqrt( (xbox(1) - xt)**2 + (ybox(1) - yt)**2)
1543 dr3 = sqrt( (xbox(3) - xb)**2 + (ybox(3) - yb)**2)
1547 drm = sqrt((yb-yt)**2 + (xb-xt)**2)
1550 dr5 = sqrt((y-yt)**2 + (x-xt)**2)
1569 wghts(1) =(dr6*dr2) / (drt*drm)
1570 wghts(2) =(dr6*dr1) / (drt*drm)
1571 wghts(3) =(dr5*dr4) / (drb*drm)
1572 wghts(4) =(dr5*dr3) / (drb*drm)
1579 REAL(SP),
INTENT(IN) :: Xbox(4)
1580 REAL(SP),
INTENT(IN) :: Ybox(4)
1581 REAL(SP),
INTENT(IN) :: X
1582 REAL(SP),
INTENT(IN) :: Y
1583 REAL(SP),
INTENT(OUT) :: wghts(4)
1587 REAL(SP) :: A1,B1,A2,B2,A3,B3
1590 REAL(SP) :: DX1, DX2, DX3
1591 REAL(SP) :: DY1, DY2, DY3
1594 REAL(sp) :: X1,Y1,X2,Y2
1600 REAL(SP) :: DRA, DRB,DRC,DRD,DRE,DRF
1601 REAL(SP) :: DR1,DR2,DR3
1604 REAL(SP) :: Xt(3),Yt(3)
1614 dx1 = xbox(2) - xbox(1)
1615 dx2 = xbox(2) - xbox(3)
1618 dy1 = ybox(2) - ybox(1)
1619 dy2 = ybox(2) - ybox(3)
1623 dx3 = xbox(3) - xbox(1)
1624 dy3 = ybox(3) - ybox(1)
1631 IF(abs(dy3) >
tb_tol *abs(dx3))
THEN 1637 b1 = ybox(2) - a1*xbox(2)
1644 b2 = ybox(2) - a2*xbox(2)
1657 IF(abs(dy1) >
tb_tol *abs(dx1))
THEN 1663 b1 = ybox(2) - a1*xbox(2)
1665 x1 = (b1-b3)/(a3 - a1)
1671 IF(abs(dy2) >
tb_tol *abs(dx2))
THEN 1678 b2 = ybox(2) - a2*xbox(2)
1679 x2 = (b2-b3)/(a3 - a2)
1688 dr1 = sqrt(dx1**2+ dy1**2)
1689 dr2 = sqrt(dx2**2+ dy2**2)
1692 dra = sqrt( (xbox(1) - x1)**2 + (ybox(1) - y1)**2)
1696 drc = sqrt( (xbox(2) - x2)**2 + (ybox(2) - y2)**2)
1700 dr3 = sqrt((y2-y1)**2 + (x2-x1)**2)
1701 dre = sqrt((y-y1)**2 + (x-x1)**2)
1717 wghts(1) = (drf*drb) / (dr1*dr3)
1718 wghts(2) = (drf*dra) / (dr1*dr3) + (dre*drd) / (dr2*dr3)
1719 wghts(3) = (dre*drc) / (dr2*dr3)
1725 dr3 = sqrt( (xbox(1) - x)**2 + (ybox(1) - y)**2)
1727 dr1 = sqrt( (xbox(3) - x)**2 + (ybox(3) - y)**2)
1747 real(SP),
ALLOCATABLE ,
TARGET,
INTENT(IN):: zin(:,:)
1748 real(SP),
ALLOCATABLE,
TARGET,
INTENT(INOUT) :: Zout(:)
1751 REAL(SP),
POINTER :: ZinP(:,:),ZoutP(:)
1753 IF (
allocated(zin))
THEN 1757 &(
"INTERP: ZIN IS NOT ALLOCATED")
1760 IF (
allocated(zout))
THEN 1764 &(
"INTERP: ZOUT IS NOT ALLOCATED")
1775 real(SP),
POINTER ,
INTENT(IN):: zin(:,:)
1776 real(SP),
POINTER,
INTENT(INOUT) :: Zout(:)
1778 integer :: i,j,x,y, kk
1783 DO j = 1,ubound(zout,1)
1792 tt=zin(x,y)*ptw%weights(i,1)+tt
1800 IF(
ASSOCIATED(weights%N_INDEX))
THEN 1802 DO i = 1,ubound(weights%N_ORDER,1)
1804 j = weights%N_ORDER(i)
1807 DO kk = 1, weights%N_CNT(j)
1808 tt = tt + zout(weights%N_INDEX(j,kk))
1811 zout(j) = tt / real(weights%N_CNT(j),sp)
1829 REAL(SP),
ALLOCATABLE,
TARGET,
INTENT(IN) :: Xin(:)
1830 REAL(SP),
ALLOCATABLE,
TARGET,
INTENT(IN) :: Yin(:)
1831 REAL(SP),
ALLOCATABLE,
TARGET,
INTENT(IN) :: Xout(:)
1832 REAL(SP),
ALLOCATABLE,
TARGET,
INTENT(IN) :: Yout(:)
1833 REAL(SP),
OPTIONAL :: rzero
1837 REAL(SP),
POINTER :: XinP(:)
1838 REAL(SP),
POINTER :: YinP(:)
1839 REAL(SP),
POINTER :: XoutP(:)
1840 REAL(SP),
POINTER :: YoutP(:)
1842 NULLIFY(xinp,yinp,xoutp,youtp)
1845 IF(
ALLOCATED(xin)) xinp => xin
1847 IF(
ALLOCATED(yin)) yinp => yin
1849 IF(
ALLOCATED(xout)) xoutp => xout
1851 IF(
ALLOCATED(yout)) youtp => yout
1853 IF(
PRESENT(rzero))
THEN 1864 REAL(SP),
POINTER,
INTENT(IN) :: Xin(:)
1865 REAL(SP),
POINTER,
INTENT(IN) :: Yin(:)
1866 REAL(SP),
POINTER,
INTENT(IN) :: Xout(:)
1867 REAL(SP),
POINTER,
INTENT(IN) :: Yout(:)
1868 REAL(SP),
OPTIONAL :: rzero
1870 REAL(SP),
ALLOCATABLE :: Xvec(:),Yvec(:)
1874 INTEGER :: I, status, lb, ub
1880 &(
"SETUP_INTERP: INPUT ARGUMENTS MUST BE ALLOCATED!")
1882 &(
"SETUP_INTERP: INPUT ARGUMENTS MUST BE ALLOCATED!")
1884 &(
"SETUP_INTERP: INPUT ARGUMENTS MUST BE ALLOCATED!")
1886 &(
"SETUP_INTERP: INPUT ARGUMENTS MUST BE ALLOCATED!")
1891 weights%Nout = ubound(xout,1)
1892 weights%Nin = ubound(xin,1)
1894 ALLOCATE(weights%PTW(weights%Nout), stat=status)
1895 IF(status /= 0)
CALL fatal_error(
"SETUP_INTERP: COULD NOT ALLOCATE SPACE")
1897 ALLOCATE(weights%INDEX(weights%Nin), stat=status)
1898 IF(status /= 0)
CALL fatal_error(
"SETUP_INTERP: COULD NOT ALLOCATE SPACE")
1901 CALL sortrx(weights%Nin,xin,weights%INDEX)
1904 ALLOCATE(xvec(weights%Nin), stat=status)
1906 & (
"SETUP_INTERP: COULD NOT ALLOCATE SPACE")
1909 ALLOCATE(yvec(weights%Nin), stat=status)
1911 & (
"SETUP_INTERP: COULD NOT ALLOCATE SPACE")
1914 DO i = 1,weights%Nin
1915 xvec(i) = xin(weights%INDEX(i))
1916 yvec(i) = yin(weights%INDEX(i))
1920 IF(
PRESENT(rzero))
THEN 1921 DO i = 1, weights%Nout
1922 CALL gen_wts(xvec,yvec,xout(i),yout(i),weights%INDEX,weights&
1926 DO i = 1, weights%Nout
1927 CALL gen_wts(xvec,yvec,xout(i),yout(i),weights%INDEX,weights&
1939 SUBROUTINE gen_wts(Xvec,Yvec,Xout,Yout,INDX,PTW,rzero)
1941 real(SP),
INTENT(in) :: Xout,Yout
1942 real(SP),
ALLOCATABLE,
INTENT(IN) :: Xvec(:),Yvec(:)
1943 INTEGER,
ALLOCATABLE,
INTENT(IN) :: INDX(:)
1944 TYPE(
r2pts),
INTENT(OUT) :: PTW
1945 REAL(SP),
OPTIONAL :: rzero
1947 INTEGER :: I,Q,K,NB,J
1949 Real(SP) :: DELX, DELY, D, SUMWGHT
1951 REAL(SP) :: D_MAX(4)
1952 REAL(SP) :: DIST(4,2)
1968 delx = xvec(i) - xout
1974 If (abs(delx).LE.
search)
Then 1975 dely = yvec(i) - yout
1976 d = sqrt(delx**2+dely**2)
1986 IF(d .LT. d_max(q))
THEN 1988 ndm= maxloc(dist(q,:),1)
1990 d_max(q) = maxval(dist(q,:))
1993 ptw%QUAD_NUM(q,ndm) = i
1999 if (k == 0)
call warning(
"FOUND NO Values in interpolation serach radius!")
2001 IF (
PRESENT(rzero))
THEN 2009 IF (dist(i,k) < huge(d))
THEN 2010 ptw%WEIGHTS(i,k) = 1/(.5_sp+dist(i,k)**2)
2016 sumwght = sum(ptw%WEIGHTS)
2017 ptw%WEIGHTS = ptw%WEIGHTS / sumwght
2024 REAL(
sp),
INTENT(IN):: dx,dy
2025 INTEGER :: ibit1, ibit2
2027 ibit1 = (int(sign(1.,dx))+1) / 2
2028 ibit2 = (int(sign(1.,dy))+1) / 2
2039 SUBROUTINE sortrx(N,DATA,INDX)
2078 INTEGER,
INTENT(IN):: N
2082 INTEGER :: LSTK(31),RSTK(31),ISTK
2083 INTEGER :: L,R,I,J,P,INDXP,INDXT
2092 INTEGER,
PARAMETER :: M = 9
2105 IF (n.LE.m)
GOTO 900
2145 IF (
DATA(indx(l)) .GT. datap)
THEN 2152 IF (datap .GT.
DATA(indx(r)))
THEN 2153 IF (
DATA(indx(l)) .GT.
DATA(indx(r)))
THEN 2180 IF (
DATA(indx(i)).LT.datap)
GOTO 300
2192 IF (
DATA(indx(j)).GT.datap)
GOTO 400
2215 IF (r-j .GE. i-l .AND. i-l .GT. m)
THEN 2220 ELSE IF (i-l .GT. r-j .AND. r-j .GT. m)
THEN 2225 ELSE IF (r-j .GT. m)
THEN 2227 ELSE IF (i-l .GT. m)
THEN 2231 IF (istk.LT.1)
GOTO 900
2247 IF (
DATA(indx(i-1)) .GT.
DATA(indx(i)))
THEN 2255 IF (
DATA(indx(p)).GT.datap)
GOTO 920
2273 REAL(SP),
ALLOCATABLE,
TARGET,
INTENT(IN) :: Zin(:)
2275 REAL(SP),
ALLOCATABLE,
TARGET :: Zout(:)
2277 REAL(SP),
POINTER :: ZinP(:),ZoutP(:)
2279 IF (
allocated(zin))
THEN 2283 &(
"INTERP: ZIN IS NOT ALLOCATED")
2286 IF (
allocated(zout))
THEN 2290 &(
"INTERP: ZOUT IS NOT ALLOCATED")
2298 REAL(SP),
POINTER :: Zin(:)
2300 REAL(SP),
POINTER :: Zout(:)
2302 REAL(SP),
ALLOCATABLE :: Zvec(:)
2304 integer :: I,status, msze,nsze, lb, ub
2307 &(
"INTERP: ZIN IS NOT ALLOCATED")
2312 IF (weights%Nin /= ubound(zin,1))
CALL fatal_error &
2313 &(
"INTERP: THE DATA INPUT SIZE DOES NOT MATCH THE WEIGHT!")
2316 ALLOCATE(zvec(0:weights%Nin),stat=status)
2317 if(status /= 0)
CALL fatal_error(
"INPTERP: COULD NOT ALLOCATE SPACE")
2320 DO i = 1,weights%Nin
2321 zvec(i) = zin(weights%INDEX(i))
2324 DO i = 1,weights%Nout
2337 real(SP),
INTENT(OUT) :: ZVAL
2338 TYPE(
r2pts),
INTENT(IN) :: PTW
2339 real(SP),
ALLOCATABLE ,
INTENT(IN):: zvec(:)
2348 zval=zvec(n)*ptw%weights(i,j)+zval
real(sp), parameter small
subroutine setup_interp_bilinear_a(Xin, Yin, Xout, Yout, WEIGHTS, land_mask)
real(sp), parameter tb_tol
subroutine print_ptw(PTW, CNT)
logical function dbg_set(vrb)
subroutine watch_init(MYWATCH)
subroutine grid_neighbor_index(FOUND, IDEX, CNT, ORDER)
subroutine interp_bilinear_a(Zin, WEIGHTS, zout)
subroutine get_loc(X_bnd, Y_bnd, msze, nsze, RSQ, MASK, X, Y, BOX, CONDITION)
subroutine interp_bilinear_p(Zin, WEIGHTS, zout)
integer, dimension(:), pointer n_found
subroutine setup_interp_quad_a(Xin, Yin, Xout, Yout, WEIGHTS, rzero)
subroutine sortrx(N, DATA, INDX)
integer function quadrant(DX, DY)
subroutine setup_interp_quad_p(Xin, Yin, Xout, Yout, WEIGHTS, rzero)
subroutine interp_weigh(Zvec, PTW, zval)
integer, parameter type_node
subroutine watch_report(MYWATCH, UNIT, MSG)
subroutine interp_quad_a(zin, Weights, zout)
subroutine warning(ER1, ER2, ER3, ER4)
subroutine print_weights(MYW, STR)
integer, parameter type_element
subroutine interp_neg(Xbox, Ybox, X, Y, wghts)
subroutine setup_interp_bilinear_p(Xin, Yin, Xout, Yout, WEIGHTS, land_mask)
subroutine kill_weights(MYW)
subroutine interp_0(Xbox, Ybox, X, Y, wghts)
subroutine fatal_error(ER1, ER2, ER3, ER4)
subroutine interp_quad_p(zin, Weights, zout)
subroutine watch_start_lap(MYWATCH)
integer, dimension(:,:), allocatable, target nbsn
integer function, dimension(4, 2) get_box(X, Y, NN, X_bnd, Y_bnd, err)
integer, parameter dbg_sbr
subroutine watch_stop_lap(MYWATCH)
logical function isintri(X0, Y0, Xt, Yt)
real(sp), parameter lr_tol
subroutine gen_wts(Xvec, Yvec, Xout, Yout, INDX, PTW, rzero)