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(:)
684 TYPE(INTERP_WEIGHTS),
INTENT(OUT) :: WEIGHTS
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)
814 CALL watch_init(min_w)
815 CALL watch_init(box_w)
816 CALL watch_init(cond_w)
817 CALL watch_init(case_w)
819 CALL watch_init(tot_w)
825 IF(
PRESENT(land_mask))
THEN 828 IF(all(mask==1))
CALL fatal_error&
829 &(
"BILINEAR INTERP CAN NOT WORK WITH EVERY POINT MASKED")
831 IF(any(mask<0 .OR. mask>1))
CALL fatal_error&
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 841 IF (.not.
allocated(
nbsn))
CALL fatal_error&
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 858 IF (.not.
allocated(
nbsn))
CALL fatal_error&
859 &(
"CAN NOD USE MASK FOR A GRID VARIABLE WITHOUT RUNNING TGE FIRST")
861 n_type = type_element
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
945 CALL watch_start_lap(case_w)
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))
985 CALL interp_0(xbox,ybox,x,y,wghts)
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))
1125 CALL interp_neg(xbox,ybox,x,y,wghts)
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))
1147 CALL interp_neg(xbox,ybox,x,y,wghts)
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))
1173 CALL interp_neg(xbox,ybox,x,y,wghts)
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))
1200 CALL interp_neg(xbox,ybox,x,y,wghts)
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
1249 IF(n_type==type_node)
THEN 1251 weights%PTW(i)%QUAD_NUM = 0
1252 IF(i>
m)
CALL fatal_error&
1253 &(
"INTERPOLATION WITH MASK: ERORR!",&
1254 &
"NEARST MESH NEIGHBOR SEARCH CAN NOT WORK WHEN THE MASK COVERS A DOMAIN BOUNDARY!")
1256 ELSEIF( n_type==type_element)
THEN 1258 weights%PTW(i)%QUAD_NUM = 0
1259 IF(i>
n)
CALL fatal_error&
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" )
1277 CALL watch_stop_lap(case_w)
1283 IF(n_type==type_node)
THEN 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))
1299 CALL grid_neighbor_index(n_found,n_index,n_cnt,n_order)
1301 weights%N_INDEX => n_index
1302 weights%N_CNT => n_cnt
1303 weights%N_ORDER => n_order
1304 weights%N_FOUND => n_found
1319 ELSEIF( n_type==type_element)
THEN 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))
1334 CALL grid_neighbor_index(n_found,n_index,n_cnt,n_order)
1336 weights%N_INDEX => n_index
1337 weights%N_CNT => n_cnt
1338 weights%N_ORDER => n_order
1339 weights%N_FOUND => n_found
1358 IF(dbg_set(dbg_sbr))
THEN 1359 WRITE(
ipt,*)
"///////////////////////////////////////////////////" 1360 WRITE(
ipt,*)
"//// TIMING REPORT FROM BILINEAR INTERP ///////////" 1361 WRITE(
ipt,*)
"///////////////////////////////////////////////////" 1362 CALL watch_report(min_w,
ipt,
"MIN LOCATION")
1364 CALL watch_report(box_w,
ipt,
"GET BOX")
1366 CALL watch_report(cond_w,
ipt,
"CONDITION")
1368 CALL watch_report(case_w,
ipt,
"WEIGHTS")
1370 CALL watch_lap(tot_w,
ipt,
"TOTAL")
1371 WRITE(
ipt,*)
"///////////////////////////////////////////////////" 1379 IF(bounds_flag)
CALL warning&
1380 &(
"FVCOM GRID IS OUT OF BOUNDS FOR FORCING",&
1381 &
"USING CONSTANT VALUE OUTSIDE OF FORCING REGION")
integer, dimension(:,:), allocatable, target nbsn