30 public :: interp_factor2d
31 public :: interp_factor3d
43 interface interp_factor2d
44 procedure INTERP_factor2d_linear_latlon
45 procedure INTERP_factor2d_linear_xy
46 procedure INTERP_factor2d_weight
47 end interface interp_factor2d
48 interface interp_factor3d
49 procedure INTERP_factor3d_linear_latlon
50 procedure INTERP_factor3d_linear_xy
51 procedure INTERP_factor3d_weight
52 end interface interp_factor3d
62 private :: interp_search_horiz
63 private :: interp_insert
71 real(RP),
private,
parameter :: large_number = 9.999e+15_rp
73 integer,
private :: INTERP_weight_order = 2
74 real(RP),
private :: INTERP_search_limit
75 real(RP),
private :: INTERP_buffer_size_fact = 2.0_rp
76 logical,
private :: INTERP_use_spline_vert = .true.
77 real(RP),
private :: INTERP_threshold_undef = 1.0_rp
79 real(RP),
private :: EPS_bilinear
94 integer,
intent(in) :: weight_order
95 real(rp),
intent(in),
optional :: search_limit
97 namelist /param_interp/ &
98 interp_buffer_size_fact, &
99 interp_use_spline_vert, &
100 interp_threshold_undef
106 log_info(
"INTERP_setup",*)
'Setup'
108 interp_weight_order = weight_order
110 interp_search_limit = large_number
111 if (
present(search_limit) )
then
112 interp_search_limit = search_limit
113 log_info(
"INTERP_setup",*)
'search limit [m] : ', interp_search_limit
120 log_info(
"INTERP_setup",*)
'Not found namelist. Default used.'
121 elseif( ierr > 0 )
then
122 log_error(
"INTERP_setup",*)
'Not appropriate names in namelist PARAM_INTERP. Check!'
125 log_nml(param_interp)
128 eps_bilinear = 1e-6_rp
130 eps_bilinear = 0.025_rp
156 real(rp),
intent(in) :: lon_org (:,:)
157 real(rp),
intent(in) :: lat_org (:,:)
158 real(rp),
intent(in) :: topc_org(:,:)
159 real(rp),
intent(in) :: lon_loc (:,:)
160 real(rp),
intent(in) :: lat_loc (:,:)
161 real(rp),
intent(in) :: topc_loc(:,:)
162 real(rp),
intent(in) :: topf_loc(:,:)
164 logical,
intent(in),
optional :: skip_z
165 logical,
intent(in),
optional :: skip_x
166 logical,
intent(in),
optional :: skip_y
168 real(rp) :: max_ref, min_ref
169 real(rp) :: max_loc, min_loc
179 if (
present(skip_z) )
then
184 if (
present(skip_x) )
then
189 if (
present(skip_y) )
then
193 if ( .NOT. skip_z_ )
then
194 max_ref = maxval( topc_org(:,:) ) + minval( topf_loc(:,:) - topc_loc(:,:) )
195 max_loc = maxval( topc_loc(:,:) )
197 if ( max_ref < max_loc )
then
198 log_error(
"INTERP_domain_compatibility",*)
'REQUESTED DOMAIN IS TOO MUCH BROAD'
199 log_error_cont(*)
'-- VERTICAL direction over the limit'
200 log_error_cont(*)
'-- reference max: ', max_ref
201 log_error_cont(*)
'-- local max: ', max_loc
206 if ( .NOT. skip_x_ )
then
207 max_ref = maxval( lon_org(:,:) / d2r )
208 min_ref = minval( lon_org(:,:) / d2r )
209 max_loc = maxval( lon_loc(:,:) / d2r )
210 min_loc = minval( lon_loc(:,:) / d2r )
212 if ( (min_ref+360.0_rp-max_ref) < 360.0_rp /
size(lon_org,1) * 2.0_rp )
then
214 elseif( max_ref < max_loc .OR. min_ref > min_loc )
then
215 log_error(
"INTERP_domain_compatibility",*)
'REQUESTED DOMAIN IS TOO MUCH BROAD'
216 log_error_cont(*)
'-- LONGITUDINAL direction over the limit'
217 log_error_cont(*)
'-- reference max: ', max_ref
218 log_error_cont(*)
'-- reference min: ', min_ref
219 log_error_cont(*)
'-- local max: ', max_loc
220 log_error_cont(*)
'-- local min: ', min_loc
225 if ( .NOT. skip_y_ )
then
226 max_ref = maxval( lat_org(:,:) / d2r )
227 min_ref = minval( lat_org(:,:) / d2r )
228 max_loc = maxval( lat_loc(:,:) / d2r )
229 min_loc = minval( lat_loc(:,:) / d2r )
231 if ( max_ref < max_loc .OR. min_ref > min_loc )
then
232 log_error(
"INTERP_domain_compatibility",*)
'REQUESTED DOMAIN IS TOO MUCH BROAD'
233 log_error_cont(*)
'-- LATITUDINAL direction over the limit'
234 log_error_cont(*)
'-- reference max: ', max_ref
235 log_error_cont(*)
'-- reference min: ', min_ref
236 log_error_cont(*)
'-- local max: ', max_loc
237 log_error_cont(*)
'-- local min: ', min_loc
249 KA_ref, KS_ref, KE_ref, &
263 integer,
intent(in) :: ka_ref, ks_ref, ke_ref
264 integer,
intent(in) :: ka, ks, ke
266 real(rp),
intent(in) :: hgt_ref(ka_ref)
267 real(rp),
intent(in) :: hgt (ka)
269 integer,
intent(out) :: idx_k (ka,2)
270 real(rp),
intent(out) :: vfact (ka)
272 logical,
intent(in),
optional :: flag_extrap
274 integer :: idx(ka_ref), kmax
275 logical :: flag_extrap_
280 if (
present(flag_extrap) )
then
281 flag_extrap_ = flag_extrap
283 flag_extrap_ = .true.
288 do k = ks_ref, ke_ref
289 if ( hgt_ref(k) > undef )
then
299 if ( hgt(k) < hgt_ref(idx(1)) - eps )
then
300 if ( flag_extrap_ )
then
309 elseif( hgt(k) < hgt_ref(idx(1)) )
then
313 elseif( hgt(k) > hgt_ref(idx(kmax)) + eps )
then
314 if ( flag_extrap_ )
then
315 idx_k(k,1) = idx(kmax)
323 elseif( hgt(k) >= hgt_ref(idx(kmax)) )
then
324 idx_k(k,1) = idx(kmax)
330 if ( hgt(k) >= hgt_ref(idx(kk) ) &
331 .AND. hgt(k) < hgt_ref(idx(kk+1)) )
then
333 idx_k(k,2) = idx(kk+1)
334 vfact(k) = ( hgt_ref(idx(kk+1)) - hgt(k) ) &
335 / ( hgt_ref(idx(kk+1)) - hgt_ref(idx(kk)) )
356 idx_i, idx_j, hfact )
360 integer,
intent(in) :: ia_ref, ja_ref
361 integer,
intent(in) :: ia, ja
363 real(rp),
intent(in) :: lon_ref(ia_ref)
364 real(rp),
intent(in) :: lat_ref(ja_ref)
365 real(rp),
intent(in) :: lon(ia,ja)
366 real(rp),
intent(in) :: lat(ia,ja)
367 integer,
intent(out) :: idx_i(ia,ja,4)
368 integer,
intent(out) :: idx_j(ia,ja,4)
369 real(rp),
intent(out) :: hfact(ia,ja,4)
372 integer :: worki(4), workj(4)
375 integer :: i, j, ii, jj
387 if ( lon(i,j) < lon_ref(1) )
then
389 hfact(i,j,:) = 0.0_rp
390 else if ( lon(i,j) > lon_ref(ia_ref) )
then
391 idx_i(i,j,:) = ia_ref
392 hfact(i,j,:) = 0.0_rp
393 else if ( lon(i,j) == lon_ref(ia_ref) )
then
394 idx_i(i,j,:) = ia_ref
395 hfact(i,j,1) = 0.0_rp
396 hfact(i,j,2) = 1.0_rp
397 hfact(i,j,3) = 0.0_rp
398 hfact(i,j,4) = 1.0_rp
401 if ( lon(i,j) < lon_ref(ii) )
then
402 f1 = ( lon_ref(ii) - lon(i,j) ) / ( lon_ref(ii) - lon_ref(ii-1) )
403 f2 = ( lon(i,j) - lon_ref(ii-1) ) / ( lon_ref(ii) - lon_ref(ii-1) )
418 if ( lat(i,j) < lat_ref(1) )
then
420 hfact(i,j,:) = 0.0_rp
421 else if ( lat(i,j) > lat_ref(ja_ref) )
then
422 idx_j(i,j,:) = ja_ref
423 hfact(i,j,:) = 0.0_rp
424 else if ( lat(i,j) == lat_ref(ja_ref) )
then
425 idx_j(i,j,:) = ja_ref
426 hfact(i,j,1) = 0.0_rp
427 hfact(i,j,2) = 0.0_rp
432 if ( lat(i,j) < lat_ref(jj) )
then
433 f1 = ( lat_ref(jj) - lat(i,j) ) / ( lat_ref(jj) - lat_ref(jj-1) )
434 f2 = ( lat(i,j) - lat_ref(jj-1) ) / ( lat_ref(jj) - lat_ref(jj-1) )
435 hfact(i,j,1) = hfact(i,j,1) * f1
436 hfact(i,j,2) = hfact(i,j,2) * f1
437 hfact(i,j,3) = hfact(i,j,3) * f2
438 hfact(i,j,4) = hfact(i,j,4) * f2
449 workh(ii) = hfact(i,j,ii)
450 worki(ii) = idx_i(i,j,ii)
451 workj(ii) = idx_j(i,j,ii)
454 workh(:), worki(:), workj(:), &
457 hfact(i,j,ii) = workh(ii)
458 idx_i(i,j,ii) = worki(ii)
459 idx_j(i,j,ii) = workj(ii)
491 integer,
intent(in) :: ia_ref, ja_ref
492 integer,
intent(in) :: ia, ja
494 real(rp),
intent(in) :: x_ref(ia_ref,ja_ref)
495 real(rp),
intent(in) :: y_ref(ia_ref,ja_ref)
496 real(rp),
intent(in) :: x(ia)
497 real(rp),
intent(in) :: y(ja)
499 integer,
intent(out) :: idx_i(ia,ja,4)
500 integer,
intent(out) :: idx_j(ia,ja,4)
501 real(rp),
intent(out) :: hfact(ia,ja,4)
503 logical,
intent(in),
optional :: zonal
504 logical,
intent(in),
optional :: pole
505 logical,
intent(in),
optional :: missing
508 integer :: inc_i, inc_j
509 logical :: error, err
510 logical :: zonal_, pole_
514 integer :: worki(4), workj(4)
518 integer :: i1, i2, i3, i4
519 integer :: j1, j2, j3, j4
521 integer :: ite, ite_max
525 if (
present(zonal) )
then
530 if (
present(pole) )
then
535 if (
present(missing) )
then
541 ii0 = ( ia_ref + 1 ) / 2
542 jj0 = ( ja_ref + 1 ) / 2
545 ite_max = ia_ref + ja_ref
575 if ( ii == ia_ref )
then
583 if ( i2 > ia_ref ) i2 = i2 - ia_ref
585 if ( i1 > ia_ref ) i1 = i1 - ia_ref
587 if ( jj == ja_ref )
then
591 if ( i3 > ia_ref ) i3 = i3 - ia_ref
593 if ( i4 > ia_ref ) i4 = i4 - ia_ref
595 if ( abs( x_ref(i1,j1) - undef ) < eps .or. &
596 abs( x_ref(i2,j2) - undef ) < eps .or. &
597 abs( x_ref(i3,j3) - undef ) < eps .or. &
598 abs( x_ref(i4,j4) - undef ) < eps )
then
599 if ( ii == ia_ref-1 )
then
601 if ( jj == ja_ref-1 )
then
609 if ( ii == ia_ref )
then
613 if ( jj == ja_ref )
then
616 if ( ii == ia_ref ) ii = 1
619 call interp_check_inside( &
620 x_ref(i1,j1), x_ref(i2,j2), x_ref(i3,j3), x_ref(i4,j4), &
621 y_ref(i1,j1), y_ref(i2,j2), y_ref(i3,j3), y_ref(i4,j4), &
625 if ( err ) error = .true.
627 if ( inc_i == 0 .and. inc_j == 0 )
then
629 x_ref(i1,j1), x_ref(i2,j2), x_ref(i3,j3), x_ref(i4,j4), &
630 y_ref(i1,j1), y_ref(i2,j2), y_ref(i3,j3), y_ref(i4,j4), &
634 if ( err ) error = .true.
644 hfact(i,j,1) = ( 1.0_rp - u ) * ( 1.0_rp - v )
645 hfact(i,j,2) = ( u ) * ( 1.0_rp - v )
646 hfact(i,j,3) = ( u ) * ( v )
647 hfact(i,j,4) = ( 1.0_rp - u ) * ( v )
652 if ( zonal_ .or. pole_ )
then
653 if ( ii == 0 ) ii = ia_ref
654 if ( ii == ia_ref+1 ) ii = 1
657 jj = min( jj, ja_ref )
660 jj = min( jj, ja_ref-1 )
663 if ( ii == 0 .and. jj == 0 )
then
667 if ( ii == 0 .and. jj == ja_ref )
then
671 if ( ii == ia_ref .and. jj == 0 )
then
675 if ( ii == ia_ref .and. jj == ja_ref )
then
679 ii = max( min( ii, ia_ref-1 ), 1 )
680 jj = max( min( jj, ja_ref-1 ), 1 )
684 if ( ite == ite_max+1 )
then
687 hfact(i,j,:) = 0.0_rp
688 if ( .not. missing_ )
then
691 log_error(
"INTERP_factor2d_linear_xy",*)
'iteration max has been reached'
692 log_error_cont(*)
'The point may be out of region.', i, j, x(i), y(j)
693 log_error_cont(*) minval(x_ref), maxval(x_ref), minval(y_ref), maxval(y_ref)
694 log_error_cont(*) x_ref(1,1), x_ref(ia_ref,1),x_ref(1,ja_ref),x_ref(ia_ref,ja_ref)
695 log_error_cont(*) y_ref(1,1), y_ref(ia_ref,1),y_ref(1,ja_ref),y_ref(ia_ref,ja_ref)
711 workh(l) = hfact(i,j,l)
712 worki(l) = idx_i(i,j,l)
713 workj(l) = idx_j(i,j,l)
716 workh(:), worki(:), workj(:), &
719 hfact(i,j,l) = workh(l)
720 idx_i(i,j,l) = worki(l)
721 idx_j(i,j,l) = workj(l)
743 idx_i, idx_j, hfact, &
751 integer,
intent(in) :: npoints
752 integer,
intent(in) :: ia_ref
753 integer,
intent(in) :: ja_ref
754 integer,
intent(in) :: ia
755 integer,
intent(in) :: ja
756 real(rp),
intent(in) :: lon_ref(ia_ref,ja_ref)
757 real(rp),
intent(in) :: lat_ref(ia_ref,ja_ref)
758 real(rp),
intent(in) :: lon (ia,ja)
759 real(rp),
intent(in) :: lat (ia,ja)
760 integer,
intent(out) :: idx_i(ia,ja,npoints)
761 integer,
intent(out) :: idx_j(ia,ja,npoints)
762 real(rp),
intent(out) :: hfact(ia,ja,npoints)
764 real(rp),
intent(in),
optional :: search_limit
765 logical,
intent(in),
optional :: latlon_structure
766 real(rp),
intent(in),
optional :: lon_1d(ia_ref), lat_1d(ja_ref)
767 integer,
intent(in),
optional :: weight_order
769 logical :: ll_struct_
771 real(rp) :: lon_min, lon_max
772 real(rp) :: lat_min, lat_max
773 real(rp) :: dlon, dlat
776 integer :: psizex, psizey
777 real(rp) :: lon0, lat0
778 integer,
allocatable :: i0(:), i1(:), j0(:), j1(:)
781 integer :: nsize, psize, nidx_max
782 integer,
allocatable :: idx_blk(:,:,:), nidx(:,:)
783 integer :: idx_ref(npoints)
785 integer :: idx_it(npoints)
786 integer :: idx_jt(npoints)
787 real(rp) :: hfactt(npoints)
789 integer :: i, j, ii, jj, n
794 if (
present(latlon_structure) )
then
795 ll_struct_ = latlon_structure
800 hfact(:,:,:) = 0.0_rp
803 if ( ll_struct_ )
then
805 if ( ia_ref > 10 )
then
806 psizex = int( 2.0_rp*sqrt(real(ia_ref+1,rp)) )
810 if ( ja_ref > 10 )
then
811 psizey = int( 2.0_rp*sqrt(real(ja_ref+1,rp)) )
816 allocate( i0(psizex), i1(psizex) )
817 allocate( j0(psizey), j1(psizey) )
819 dlon = ( lon_max - lon_min ) / psizex
820 dlat = ( lat_max - lat_min ) / psizey
823 lon0 = lon_min + dlon * (ii-1)
825 if ( lon_1d(i) >= lon0 )
then
832 i1(ii) = i0(ii+1) - 1
837 lat0 = lat_min + dlat * (jj-1)
839 if ( lat_1d(j) >= lat0 )
then
846 j1(jj) = j0(jj+1) - 1
860 lon_1d(:), lat_1d(:), &
863 i0(:), i1(:), j0(:), j1(:), &
864 lon(i,j), lat(i,j), &
865 idx_it(:), idx_jt(:), &
867 search_limit = search_limit, &
868 weight_order = weight_order )
870 idx_i(i,j,n) = idx_it(n)
871 idx_j(i,j,n) = idx_jt(n)
872 hfact(i,j,n) = hfactt(n)
878 deallocate( i0, i1, j0, j1 )
882 nsize = ia_ref * ja_ref
883 if ( nsize > 100 )
then
884 psize = int( sqrt(2.0_rp*sqrt(real(nsize,rp))) )
885 nidx_max = nsize / psize * interp_buffer_size_fact
891 allocate(idx_blk(nidx_max,psize,psize))
892 allocate(nidx( psize,psize))
897 lon_ref(:,:), lat_ref(:,:), &
898 idx_blk(:,:,:), nidx(:,:), &
911 call interp_search_horiz( npoints, &
913 lon_ref(:,:), lat_ref(:,:), &
918 idx_blk(:,:,:), nidx(:,:), &
919 lon(i,j), lat(i,j), &
922 search_limit = search_limit, &
923 weight_order = weight_order )
925 idx_i(i,j,n) = mod(idx_ref(n) - 1, ia_ref) + 1
926 idx_j(i,j,n) = ( idx_ref(n) - 1 ) / ia_ref + 1
927 hfact(i,j,n) = hfactt(n)
935 deallocate(idx_blk, nidx)
948 KA_ref, KS_ref, KE_ref, &
963 integer,
intent(in) :: ka_ref, ks_ref, ke_ref
964 integer,
intent(in) :: ia_ref
965 integer,
intent(in) :: ja_ref
966 integer,
intent(in) :: ka, ks, ke
967 integer,
intent(in) :: ia
968 integer,
intent(in) :: ja
969 real(rp),
intent(in) :: lon_ref(ia_ref)
970 real(rp),
intent(in) :: lat_ref(ja_ref)
971 real(rp),
intent(in) :: hgt_ref(ka_ref,ia_ref,ja_ref)
972 real(rp),
intent(in) :: lon(ia,ja)
973 real(rp),
intent(in) :: lat(ia,ja)
974 real(rp),
intent(in) :: hgt(ka,ia,ja)
976 integer,
intent(out) :: idx_i(ia,ja,4)
977 integer,
intent(out) :: idx_j(ia,ja,4)
978 real(rp),
intent(out) :: hfact(ia,ja,4)
979 integer,
intent(out) :: idx_k(ka,2,ia,ja,4)
980 real(rp),
intent(out) :: vfact(ka, ia,ja,4)
982 logical,
intent(in),
optional :: flag_extrap
984 integer :: i, j, ii, jj, n
991 lon_ref(:), lat_ref(:), &
992 lon(:,:), lat(:,:), &
993 idx_i(:,:,:), idx_j(:,:,:), hfact(:,:,:) )
1014 flag_extrap = flag_extrap )
1032 KA_ref, KS_ref, KE_ref, &
1048 integer,
intent(in) :: ka_ref, ks_ref, ke_ref
1049 integer,
intent(in) :: ia_ref
1050 integer,
intent(in) :: ja_ref
1051 integer,
intent(in) :: ka, ks, ke
1052 integer,
intent(in) :: ia
1053 integer,
intent(in) :: ja
1054 real(rp),
intent(in) :: x_ref(ia_ref,ja_ref)
1055 real(rp),
intent(in) :: y_ref(ia_ref,ja_ref)
1056 real(rp),
intent(in) :: hgt_ref(ka_ref,ia_ref,ja_ref)
1057 real(rp),
intent(in) :: x (ia)
1058 real(rp),
intent(in) :: y (ja)
1059 real(rp),
intent(in) :: hgt(ka,ia,ja)
1061 integer,
intent(out) :: idx_i(ia,ja,4)
1062 integer,
intent(out) :: idx_j(ia,ja,4)
1063 real(rp),
intent(out) :: hfact(ia,ja,4)
1064 integer,
intent(out) :: idx_k(ka,2,ia,ja,4)
1065 real(rp),
intent(out) :: vfact(ka, ia,ja,4)
1067 logical,
intent(in),
optional :: flag_extrap
1068 logical,
intent(in),
optional :: zonal
1069 logical,
intent(in),
optional :: pole
1070 logical,
intent(in),
optional :: missing
1072 integer :: i, j, ii, jj, n
1079 x_ref(:,:), y_ref(:,:), &
1081 idx_i(:,:,:), idx_j(:,:,:), hfact(:,:,:), &
1082 zonal = zonal, pole = pole, &
1104 flag_extrap = flag_extrap )
1122 KA_ref, KS_ref, KE_ref, &
1138 integer,
intent(in) :: npoints
1139 integer,
intent(in) :: ka_ref, ks_ref, ke_ref
1140 integer,
intent(in) :: ia_ref
1141 integer,
intent(in) :: ja_ref
1142 integer,
intent(in) :: ka, ks, ke
1143 integer,
intent(in) :: ia
1144 integer,
intent(in) :: ja
1146 real(rp),
intent(in) :: lon_ref(ia_ref,ja_ref)
1147 real(rp),
intent(in) :: lat_ref(ia_ref,ja_ref)
1148 real(rp),
intent(in) :: hgt_ref(ka_ref,ia_ref,ja_ref)
1149 real(rp),
intent(in) :: lon (ia,ja)
1150 real(rp),
intent(in) :: lat (ia,ja)
1151 real(rp),
intent(in) :: hgt (ka,ia,ja)
1153 integer,
intent(out) :: idx_i(ia,ja,npoints)
1154 integer,
intent(out) :: idx_j(ia,ja,npoints)
1155 real(rp),
intent(out) :: hfact(ia,ja,npoints)
1156 integer,
intent(out) :: idx_k(ka,2,ia,ja,npoints)
1157 real(rp),
intent(out) :: vfact(ka, ia,ja,npoints)
1159 logical,
intent(in),
optional :: flag_extrap
1161 integer :: nsize, psize, nidx_max
1162 integer,
allocatable :: idx_blk(:,:,:), nidx(:,:)
1163 real(rp) :: lon_min, lon_max
1164 real(rp) :: lat_min, lat_max
1165 real(rp) :: dlon, dlat
1166 integer :: idx_ref(npoints)
1167 real(rp) :: hfactt(npoints)
1169 integer :: i, j, ii, jj, n
1174 nsize = ia_ref * ja_ref
1175 if ( nsize > 100 )
then
1176 psize = int( sqrt(2.0_rp*sqrt(real(nsize,rp))) )
1177 nidx_max = nsize / psize * interp_buffer_size_fact
1183 allocate(idx_blk(nidx_max,psize,psize))
1184 allocate(nidx( psize,psize))
1191 lon_ref(:,:), lat_ref(:,:), &
1192 idx_blk(:,:,:), nidx(:,:), &
1206 call interp_search_horiz( npoints, &
1208 lon_ref(:,:), lat_ref(:,:), &
1213 idx_blk(:,:,:), nidx(:,:), &
1214 lon(i,j), lat(i,j), &
1215 idx_ref(:), hfactt(:) )
1219 ii = mod(idx_ref(n) - 1, ia_ref) + 1
1220 jj = ( idx_ref(n) - 1 ) / ia_ref + 1
1223 hfact(i,j,n) = hfactt(n)
1230 flag_extrap = flag_extrap )
1239 deallocate(idx_blk, nidx)
1250 KA_ref, KS_ref, KE_ref, &
1268 integer,
intent(in) :: ka_ref, ks_ref, ke_ref
1269 integer,
intent(in) :: ka, ks, ke
1271 integer,
intent(in) :: idx_k(ka,2)
1272 real(rp),
intent(in) :: vfact(ka )
1273 real(rp),
intent(in) :: hgt_ref(ka_ref)
1274 real(rp),
intent(in) :: hgt (ka)
1275 real(rp),
intent(in),
target :: val_ref(ka_ref)
1277 real(rp),
intent(out) :: val (ka)
1279 logical,
intent(in),
optional :: spline
1280 logical,
intent(in),
optional :: logwgt
1285 real(rp),
pointer :: work(:)
1288 real(rp),
intent(out),
target :: workr(ka_ref,7)
1289 integer,
intent(out) :: worki(ka_ref,2)
1290 #define idx_i1(k) worki(k,1)
1291 #define idx_r_i1(k) worki(k,2)
1292 #define FDZ_i1(k) workr(k,1)
1293 #define U_i1(k) workr(k,2)
1295 integer :: idx_i1 (ka_ref)
1296 integer :: idx_r_i1(ka_ref)
1297 real(rp) :: fdz_i1 (ka_ref)
1298 real(rp) :: u_i1 (ka_ref)
1305 spline_ = interp_use_spline_vert
1306 if (
present(spline) )
then
1311 if (
present(logwgt) )
then
1319 allocate( work(ka_ref) )
1321 do k = ks_ref, ke_ref
1322 if ( abs( val_ref(k) - undef ) < eps )
then
1325 work(k) = log( val_ref(k) )
1332 call spline_coef( ka_ref, ks_ref, ke_ref, &
1336 hgt_ref(:), work(:), &
1339 idx_i1(:), idx_r_i1(:), &
1340 u_i1(:), fdz_i1(:) )
1343 idx_k(:,:), vfact(:), &
1344 hgt_ref(:), hgt(:), &
1346 idx_i1(:), idx_r_i1(:), &
1347 u_i1(:), fdz_i1(:), &
1355 if ( abs( val(k) - undef ) > eps )
then
1356 val(k) = exp( val(k) )
1381 integer,
intent(in) :: npoints
1382 integer,
intent(in) :: ia_ref
1383 integer,
intent(in) :: ja_ref
1384 integer,
intent(in) :: ia
1385 integer,
intent(in) :: ja
1386 integer,
intent(in) :: idx_i (ia,ja,npoints)
1387 integer,
intent(in) :: idx_j (ia,ja,npoints)
1388 real(rp),
intent(in) :: hfact (ia,ja,npoints)
1389 real(rp),
intent(in) :: val_ref(ia_ref,ja_ref)
1391 real(rp),
intent(out) :: val (ia,ja)
1393 real(rp),
intent(in),
optional :: threshold_undef
1394 real(rp),
intent(out),
optional :: wsum(ia,ja)
1395 real(rp),
intent(out),
optional :: val2(ia,ja)
1397 real(rp) :: th_undef
1399 real(rp) :: fact, valn, f, w
1408 if (
present(threshold_undef) )
then
1409 th_undef = threshold_undef
1411 th_undef = interp_threshold_undef
1413 th_undef = min( max( th_undef, eps * 2.0_rp ), 1.0_rp - eps * 2.0_rp )
1415 lval2 =
present(wsum) .and.
present(val2)
1428 w = val_ref(idx_i(i,j,n),idx_j(i,j,n))
1429 if ( f > eps .and. abs( w - undef ) > eps )
then
1434 sw = 0.5_rp - sign( 0.5_rp, fact - th_undef + eps )
1435 val(i,j) = valn / ( fact + sw ) * ( 1.0_rp - sw ) + undef * sw
1438 sw = 0.5_rp - sign( 0.5_rp, fact - eps )
1439 val2(i,j) = valn / ( fact + sw ) * ( 1.0_rp - sw ) + undef * sw
1454 KA_ref, KS_ref, KE_ref, &
1473 integer,
intent(in) :: npoints
1474 integer,
intent(in) :: ka_ref, ks_ref, ke_ref
1475 integer,
intent(in) :: ia_ref
1476 integer,
intent(in) :: ja_ref
1477 integer,
intent(in) :: ka, ks, ke
1478 integer,
intent(in) :: ia
1479 integer,
intent(in) :: ja
1481 integer,
intent(in) :: idx_i (ia,ja,npoints)
1482 integer,
intent(in) :: idx_j (ia,ja,npoints)
1483 real(rp),
intent(in) :: hfact (ia,ja,npoints)
1484 integer,
intent(in) :: idx_k (ka,2,ia,ja,npoints)
1485 real(rp),
intent(in) :: vfact (ka, ia,ja,npoints)
1486 real(rp),
intent(in) :: hgt_ref(ka_ref,ia_ref,ja_ref)
1487 real(rp),
intent(in) :: hgt (ka,ia,ja)
1488 real(rp),
intent(in),
target :: val_ref(ka_ref,ia_ref,ja_ref)
1490 real(rp),
intent(out) :: val (ka,ia,ja)
1492 logical,
intent(in),
optional :: spline
1493 logical,
intent(in),
optional :: logwgt
1494 real(rp),
intent(in),
optional :: threshold_undef
1495 real(rp),
intent(out),
optional :: wsum(ka,ia,ja)
1496 real(rp),
intent(out),
optional :: val2(ka,ia,ja)
1498 real(rp) :: th_undef
1502 real(rp),
pointer :: work(:,:,:)
1504 integer,
allocatable :: kmax(:,:)
1505 integer,
allocatable :: idx(:,:,:), idx_r(:,:,:)
1506 real(rp),
allocatable :: u(:,:,:), fdz(:,:,:)
1512 real(rp) :: w(ka,npoints)
1516 real(rp) :: workr(ka_ref,4)
1519 integer :: imin, imax
1520 integer :: jmin, jmax
1522 integer :: k, i, j, n
1527 if (
present(threshold_undef) )
then
1528 th_undef = threshold_undef
1530 th_undef = interp_threshold_undef
1532 th_undef = min( max( th_undef, eps * 2.0_rp ), 1.0_rp - eps * 2.0_rp )
1535 spline_ = interp_use_spline_vert
1536 if (
present(spline) )
then
1541 if (
present(logwgt) )
then
1546 lval2 =
present(wsum) .and.
present(val2)
1569 imin = min(imin, idx_i(i,j,n))
1570 imax = max(imax, idx_i(i,j,n))
1571 jmin = min(jmin, idx_j(i,j,n))
1572 jmax = max(jmax, idx_j(i,j,n))
1578 allocate( kmax(imin:imax,jmin:jmax) )
1579 allocate( idx(ka_ref,imin:imax,jmin:jmax), idx_r(ka_ref,imin:imax,jmin:jmax) )
1580 allocate( u(ka_ref,imin:imax,jmin:jmax), fdz(ka_ref,imin:imax,jmin:jmax) )
1584 allocate( work(ka_ref,imin:imax,jmin:jmax) )
1593 do k = ks_ref, ke_ref
1594 if ( abs( val_ref(k,i,j) - undef ) < eps )
then
1597 work(k,i,j) = log( val_ref(k,i,j) )
1613 call spline_coef( ka_ref, ks_ref, ke_ref, &
1617 hgt_ref(:,i,j), work(:,i,j), &
1620 idx(:,i,j), idx_r(:,i,j), &
1621 u(:,i,j), fdz(:,i,j) )
1636 if ( hfact(i,j,n) > eps )
then
1639 call spline_exec( ka_ref, kmax(ii,jj), ka, ks, ke, &
1640 idx_k(:,:,i,j,n), vfact(:, i,j,n), &
1641 hgt_ref(:,ii,jj), hgt(:,i,j), &
1643 idx(:,ii,jj), idx_r(:,ii,jj), &
1644 u(:,ii,jj), fdz(:,ii,jj), &
1655 if ( f > eps .and. abs( w(k,n) - undef ) > eps )
then
1657 valn = valn + f * w(k,n)
1660 sw = 0.5_rp - sign( 0.5_rp, fact - th_undef )
1661 val(k,i,j) = valn / ( fact + sw ) * ( 1.0_rp - sw ) + undef * sw
1664 sw = 0.5_rp - sign( 0.5_rp, fact - eps )
1665 val2(k,i,j) = valn / ( fact + sw ) * ( 1.0_rp - sw ) + undef * sw
1674 deallocate( kmax, idx, idx_r )
1675 deallocate( u, fdz )
1685 if ( abs( val(k,i,j) - undef ) > eps )
then
1686 val(k,i,j) = exp( val(k,i,j) )
1710 subroutine interp_search_horiz( &
1730 integer,
intent(in) :: npoints
1731 integer,
intent(in) :: nsize
1732 real(rp),
intent(in) :: lon_ref(nsize)
1733 real(rp),
intent(in) :: lat_ref(nsize)
1734 real(rp),
intent(in) :: lon_min
1735 real(rp),
intent(in) :: lon_max
1736 real(rp),
intent(in) :: lat_min
1737 real(rp),
intent(in) :: lat_max
1738 integer,
intent(in) :: psize
1739 integer,
intent(in) :: nidx_max
1740 real(rp),
intent(in) :: dlon
1741 real(rp),
intent(in) :: dlat
1742 integer,
intent(in) :: idx_blk(nidx_max,psize,psize)
1743 integer,
intent(in) :: nidx (psize,psize)
1744 real(rp),
intent(in) :: lon
1745 real(rp),
intent(in) :: lat
1746 integer,
intent(out) :: idx_ref(npoints)
1747 real(rp),
intent(out) :: hfact(npoints)
1749 real(rp),
intent(in),
optional :: search_limit
1750 integer,
intent(in),
optional :: weight_order
1752 real(rp) :: drad(npoints)
1754 real(rp) :: search_limit_
1755 integer :: weight_order_
1757 real(rp) :: lon0, lon1, lat0, lat1
1758 real(rp) :: dlon_sl, dlat_sl
1760 integer :: ii, jj, ii0, jj0
1763 if (
present(search_limit) )
then
1764 search_limit_ = search_limit
1766 search_limit_ = interp_search_limit
1768 search_limit_ = search_limit_ / radius
1770 if (
present(weight_order) )
then
1771 weight_order_ = weight_order
1773 weight_order_ = interp_weight_order
1778 drad(:) = large_number
1782 ii0 = max( min( int(( lon - lon_min ) / dlon) + 1, psize ), 1 )
1783 jj0 = max( min( int(( lat - lat_min ) / dlat) + 1, psize ), 1 )
1784 do i = 1, nidx(ii0,jj0)
1785 n = idx_blk(i,ii0,jj0)
1786 call interp_insert( npoints, &
1788 lon_ref(n), lat_ref(n), &
1790 drad(:), idx_ref(:) )
1793 if ( abs(drad(1)) < eps )
then
1798 else if ( drad(1) > search_limit_ )
then
1805 dlon_sl = max(dlon * 0.5_rp, drad(npoints))
1806 dlat_sl = max(dlat * 0.5_rp, drad(npoints))
1808 lat0 = lat_min + dlat * (jj-1)
1809 lat1 = lat_min + dlat * jj
1810 if ( lat < lat0 - dlat_sl &
1811 .or. lat >= lat1 + dlat_sl ) cycle
1813 if ( ii==ii0 .and. jj==jj0 ) cycle
1814 lon0 = lon_min + dlon * (ii-1)
1815 lon1 = lon_min + dlon * ii
1816 if ( lon < lon0 - dlon_sl &
1817 .or. lon >= lon1 + dlon_sl ) cycle
1818 do i = 1, nidx(ii,jj)
1819 n = idx_blk(i,ii,jj)
1820 call interp_insert( npoints, &
1822 lon_ref(n), lat_ref(n), &
1824 drad(:), idx_ref(:) )
1826 dlon_sl = max(dlon * 0.5_rp, drad(npoints))
1827 dlat_sl = max(dlat * 0.5_rp, drad(npoints))
1832 if ( weight_order_ < 0 )
then
1834 hfact(n) = 1.0_rp / drad(n)**(-1.0_rp/weight_order_)
1838 hfact(n) = 1.0_rp / drad(n)**weight_order_
1844 if ( drad(n) >= search_limit_ )
then
1852 sum = sum + hfact(n)
1855 if ( sum > 0.0_rp )
then
1857 hfact(n) = hfact(n) / sum
1862 end subroutine interp_search_horiz
1886 integer,
intent(in) :: npoints
1887 integer,
intent(in) :: psizex
1888 integer,
intent(in) :: psizey
1889 integer,
intent(in) :: IA_ref
1890 integer,
intent(in) :: JA_ref
1891 real(RP),
intent(in) :: lon_ref(IA_ref)
1892 real(RP),
intent(in) :: lat_ref(JA_ref)
1893 real(RP),
intent(in) :: lon_min
1894 real(RP),
intent(in) :: lat_min
1895 real(RP),
intent(in) :: dlon
1896 real(RP),
intent(in) :: dlat
1897 integer,
intent(in) :: i0(psizex)
1898 integer,
intent(in) :: i1(psizex)
1899 integer,
intent(in) :: j0(psizey)
1900 integer,
intent(in) :: j1(psizey)
1901 real(RP),
intent(in) :: lon
1902 real(RP),
intent(in) :: lat
1903 integer,
intent(out) :: idx_i(npoints)
1904 integer,
intent(out) :: idx_j(npoints)
1905 real(RP),
intent(out) :: hfact(npoints)
1907 real(RP),
intent(in),
optional :: search_limit
1908 integer,
intent(in),
optional :: weight_order
1910 real(RP) :: drad(npoints)
1912 real(RP) :: search_limit_
1913 integer :: weight_order_
1915 real(RP) :: lon0, lon1, lat0, lat1
1916 real(RP) :: dlon_sl, dlat_sl
1919 integer :: ii, jj, ii0, jj0
1922 if (
present(search_limit) )
then
1923 search_limit_ = search_limit
1925 search_limit_ = interp_search_limit
1927 search_limit_ = search_limit_ / radius
1929 if (
present(weight_order) )
then
1930 weight_order_ = weight_order
1932 weight_order_ = interp_weight_order
1936 drad(:) = large_number
1941 ii0 = max( min( int(( lon - lon_min ) / dlon) + 1, psizex ), 1)
1942 jj0 = max( min( int(( lat - lat_min ) / dlat) + 1, psizey ), 1)
1943 do j = j0(jj0), j1(jj0)
1944 do i = i0(ii0), i1(ii0)
1947 lon_ref(i), lat_ref(j), &
1949 drad(:), idx_i(:), idx_j(:) )
1953 if ( abs(drad(1)) < eps )
then
1958 else if ( drad(1) > search_limit_ )
then
1966 dlon_sl = max(dlon * 0.5_rp, drad(npoints))
1967 dlat_sl = max(dlat * 0.5_rp, drad(npoints))
1969 lat0 = lat_min + dlat * (jj-1)
1970 lat1 = lat_min + dlat * jj
1971 if ( lat < lat0 - dlat_sl &
1972 .or. lat >= lat1 + dlat_sl ) cycle
1974 if ( ii==ii0 .and. jj==jj0 ) cycle
1975 lon0 = lon_min + dlon * (ii-1)
1976 lon1 = lon_min + dlon * ii
1977 if ( lon < lon0 - dlon_sl &
1978 .or. lon >= lon1 + dlon_sl ) cycle
1979 do j = j0(jj0), j1(jj0)
1980 do i = i0(ii0), i1(ii0)
1983 lon_ref(i), lat_ref(j), &
1985 drad(:), idx_i(:), idx_j(:) )
1988 dlon_sl = max(dlon * 0.5_rp, drad(npoints))
1989 dlat_sl = max(dlat * 0.5_rp, drad(npoints))
1995 if ( weight_order_ < 0 )
then
1997 hfact(n) = 1.0_rp / drad(n)**(-1.0_rp/weight_order_)
2001 hfact(n) = 1.0_rp / drad(n)**weight_order_
2007 if ( drad(n) >= search_limit_ )
then
2015 sum = sum + hfact(n)
2018 if ( sum > 0.0_rp )
then
2020 hfact(n) = hfact(n) / sum
2029 subroutine interp_insert( npoints, &
2041 integer,
intent(in) :: npoints
2042 real(RP),
intent(in) :: lon, lat
2043 real(RP),
intent(in) :: lon_ref, lat_ref
2044 integer,
intent(in),
value :: i
2046 real(RP),
intent(inout) :: drad(npoints)
2047 integer,
intent(inout) :: idx_i(npoints)
2051 if ( abs( lon_ref - undef ) < eps )
return
2053 dradian = haversine( lon, lat, lon_ref, lat_ref )
2055 if ( dradian <= drad(npoints) )
then
2057 drad(npoints) = dradian
2061 call sort_exec( npoints, &
2067 end subroutine interp_insert
2074 drad, idx_i, idx_j )
2082 integer,
intent(in) :: npoints
2083 real(RP),
intent(in) :: lon, lat
2084 real(RP),
intent(in) :: lon_ref, lat_ref
2085 integer,
intent(in),
value :: i, j
2087 real(RP),
intent(inout) :: drad(npoints)
2088 integer,
intent(inout) :: idx_i(npoints)
2089 integer,
intent(inout) :: idx_j(npoints)
2093 if ( abs( lon_ref - undef ) < eps )
return
2095 dradian = haversine( lon, lat, lon_ref, lat_ref )
2097 if ( dradian <= drad(npoints) )
then
2099 drad(npoints) = dradian
2104 call sort_exec( npoints, &
2125 integer,
intent(in) :: nsize
2126 integer,
intent(in) :: psize
2127 integer,
intent(in) :: nidx_max
2128 real(RP),
intent(in) :: lon_ref(nsize)
2129 real(RP),
intent(in) :: lat_ref(nsize)
2131 integer,
intent(out) :: idx (nidx_max,psize,psize)
2132 integer,
intent(out) :: nidx(psize,psize)
2133 real(RP),
intent(out) :: lon_min, lon_max
2134 real(RP),
intent(out) :: lat_min, lat_max
2135 real(RP),
intent(out) :: dlon, dlat
2137 integer :: i, ii, jj, n
2149 if ( abs(lon_ref(i) - undef) > eps )
then
2150 lon_min = min( lon_min, lon_ref(i) )
2151 lon_max = max( lon_max, lon_ref(i) )
2153 if ( abs(lat_ref(i) - undef) > eps )
then
2154 lat_min = min( lat_min, lat_ref(i) )
2155 lat_max = max( lat_max, lat_ref(i) )
2160 dlon = ( lon_max - lon_min ) / psize
2161 dlat = ( lat_max - lat_min ) / psize
2169 if ( abs( lon_ref(i) - undef ) < eps ) cycle
2170 ii = min(int((lon_ref(i) - lon_min) / dlon) + 1, psize)
2171 jj = min(int((lat_ref(i) - lat_min) / dlat) + 1, psize)
2177 if ( n <= nidx_max ) idx(n,ii,jj) = i
2183 if ( maxval(nidx) > nidx_max )
then
2184 log_error(
"INTERP_search_horiz",*)
'Buffer size is not enough'
2185 log_error_cont(*)
' Use larger INTERP_buffer_size_fact: ', interp_buffer_size_fact * maxval(nidx)/nidx_max
2194 x_ref0, x_ref1, x_ref2, x_ref3, &
2195 y_ref0, y_ref1, y_ref2, y_ref3, &
2201 real(RP),
intent(in),
value :: x_ref0, x_ref1, x_ref2, x_ref3
2202 real(RP),
intent(in),
value :: y_ref0, y_ref1, y_ref2, y_ref3
2203 real(RP),
intent(in),
value :: x, y
2205 real(RP),
intent(out) :: u, v
2206 logical,
intent(out) :: error
2208 real(RP) :: e_x, e_y
2209 real(RP) :: f_x, f_y
2210 real(RP) :: g_x, g_y
2211 real(RP) :: h_x, h_y
2212 real(RP) :: k0, k1, k2
2216 e_x = x_ref1 - x_ref0
2217 e_y = y_ref1 - y_ref0
2219 f_x = x_ref3 - x_ref0
2220 f_y = y_ref3 - y_ref0
2222 g_x = x_ref0 - x_ref1 + x_ref2 - x_ref3
2223 g_y = y_ref0 - y_ref1 + y_ref2 - y_ref3
2228 k0 =
cross(h_x, h_y, e_x, e_y)
2229 k1 =
cross(e_x, e_y, f_x, f_y) +
cross(h_x, h_y, g_x, g_y)
2230 k2 =
cross(g_x, g_y, f_x, f_y)
2232 w = k1**2 - 4.0_rp * k0 * k2
2233 if ( w < 0.0_rp )
then
2235 log_error(
"INTERP_bilinear_inv",*)
'Outside of the quadrilateral'
2241 if ( abs(k1) < eps_bilinear )
then
2243 log_error(
"INTERP_bilinear_inv",*)
'Unexpected error occured', k1
2244 log_error_cont(*) x_ref0, x_ref1, x_ref2, x_ref3
2245 log_error_cont(*) y_ref0, y_ref1, y_ref2, y_ref3
2246 log_error_cont(*) x, y
2251 if ( abs(k2) < eps_bilinear * sqrt( (x_ref2-x_ref0)**2+(y_ref2-y_ref0)**2 ) )
then
2254 sig = sign( 1.0_rp,
cross(x_ref1-x_ref0, y_ref1-y_ref0, x_ref3-x_ref0, y_ref3-y_ref0) )
2255 v = ( - k1 + sig * sqrt(w) ) / ( 2.0_rp * k2 )
2257 u = ( h_x - f_x * v ) / ( e_x + g_x * v )
2259 if ( u < -eps_bilinear .or. u > 1.0_rp+eps_bilinear .or. v < -eps_bilinear .or. v > 1.0_rp+eps_bilinear )
then
2261 log_error(
"INTERP_bilinear_inv",*)
'Unexpected error occured', u, v
2262 log_error_cont(*) x_ref0, x_ref1, x_ref2, x_ref3
2263 log_error_cont(*) y_ref0, y_ref1, y_ref2, y_ref3
2264 log_error_cont(*) x, y
2265 log_error_cont(*) k0, k1, k2, sig
2270 u = min( max( u, 0.0_rp ), 1.0_rp )
2271 v = min( max( v, 0.0_rp ), 1.0_rp )
2280 subroutine interp_check_inside( &
2281 x_ref0, x_ref1, x_ref2, x_ref3, &
2282 y_ref0, y_ref1, y_ref2, y_ref3, &
2290 real(RP),
intent(in),
value :: x_ref0, x_ref1, x_ref2, x_ref3
2291 real(RP),
intent(in),
value :: y_ref0, y_ref1, y_ref2, y_ref3
2292 real(RP),
intent(in),
value :: x, y
2294 integer,
intent(out) :: inc_i, inc_j
2295 logical,
intent(out) :: error
2298 real(RP) :: c1, c2, c3, c4
2304 sig = sign( 1.0_rp,
cross(x_ref1-x_ref0, y_ref1-y_ref0, x_ref3-x_ref0, y_ref3-y_ref0) )
2306 c1 = sig *
cross(x_ref1-x_ref0, y_ref1-y_ref0, x-x_ref0, y-y_ref0)
2307 c2 = sig *
cross(x_ref2-x_ref1, y_ref2-y_ref1, x-x_ref1, y-y_ref1)
2308 c3 = sig *
cross(x_ref3-x_ref2, y_ref3-y_ref2, x-x_ref2, y-y_ref2)
2309 c4 = sig *
cross(x_ref0-x_ref3, y_ref0-y_ref3, x-x_ref3, y-y_ref3)
2311 th = - max( abs(c1), abs(c2), abs(c3), abs(c4) ) * eps * 1.e4_rp
2316 if ( c1 < th ) inc_j = -1
2317 if ( c2 < th ) inc_i = 1
2318 if ( c3 < th ) inc_j = 1
2319 if ( c4 < th ) inc_i = -1
2321 fx = c2 < th .and. c4 < th
2322 fy = c1 < th .and. c3 < th
2323 if ( fx .and. fy )
then
2325 log_error(
"INTERP_check_inside",*)
'Unexpected error occured', c1, c2, c3, c4
2326 log_error_cont(*) x_ref0, x_ref1, x_ref2, x_ref3
2327 log_error_cont(*) y_ref0, y_ref1, y_ref2, y_ref3
2328 log_error_cont(*) x, y
2339 end subroutine interp_check_inside
2348 real(rp),
intent(in) :: x0, y0
2349 real(rp),
intent(in) :: x1, y1
2352 cross = x0 * y1 - x1 * y0
2359 function haversine( &
2366 real(rp),
intent(in) :: lon0
2367 real(rp),
intent(in) :: lat0
2368 real(rp),
intent(in) :: lon1
2369 real(rp),
intent(in) :: lat1
2372 real(rp) :: dlonh, dlath
2376 dlonh = 0.5_rp * ( lon0 - lon1 )
2377 dlath = 0.5_rp * ( lat0 - lat1 )
2379 work1 = sin(dlath)**2 + cos(lat0) * cos(lat1) * sin(dlonh)**2
2381 d = 2.0_rp * asin( min(sqrt(work1),1.0_rp) )
2383 end function haversine
2387 subroutine spline_coef( &
2388 KA_ref, KS_ref, KE_ref, &
2404 integer,
intent(in) :: ka_ref, ks_ref, ke_ref
2406 real(rp),
intent(in) :: hgt_ref(ka_ref)
2407 real(rp),
intent(in) :: val_ref(ka_ref)
2408 logical,
intent(in) :: spline
2410 integer,
intent(out) :: kmax
2411 integer,
intent(out) :: idx (ka_ref)
2412 integer,
intent(out) :: idx_r(ka_ref)
2413 real(rp),
intent(out) :: u (ka_ref)
2414 real(rp),
intent(out) :: fdz(ka_ref)
2417 real(rp),
intent(out) :: work(ka_ref,4)
2418 #define MD_sc(k) work(k,1)
2419 #define V_sc(k) work(k,2)
2421 real(rp) :: md_sc(ka_ref)
2422 real(rp) :: v_sc (ka_ref)
2431 do k = ks_ref, ke_ref-1
2432 if ( hgt_ref(k) > undef .and. abs( val_ref(k) - undef ) > eps )
then
2438 if ( idx(1) == -999 )
return
2440 do k = idx(1)+1, ke_ref
2441 if ( hgt_ref(k) > undef )
then
2442 dz = hgt_ref(k) - hgt_ref(idx(kmax))
2443 if ( abs( val_ref(k) - undef ) > eps .and. dz > eps )
then
2444 do while ( kmax > 1 .and. fdz(kmax) < dz * 0.1_rp )
2449 if ( idx(kmax-1)+1 <= k-1 ) idx_r(idx(kmax-1)+1:k-1) = kmax-1
2451 fdz(kmax) = hgt_ref(k) - hgt_ref(idx(kmax-1))
2456 if ( kmax > 3 )
then
2458 md_sc(2) = 2.0_rp * ( fdz(2) + fdz(3) ) + fdz(2)
2460 md_sc(k) = 2.0_rp * ( fdz(k) + fdz(k+1) )
2462 md_sc(kmax-1) = 2.0_rp * ( fdz(kmax-1) + fdz(kmax) ) + fdz(kmax)
2465 v_sc(k) = ( val_ref(idx(k+1)) - val_ref(idx(k )) ) / fdz(k+1) &
2466 - ( val_ref(idx(k )) - val_ref(idx(k-1)) ) / fdz(k )
2473 fdz(2:), md_sc(:), fdz(:), &
2495 end subroutine spline_coef
2499 KA_ref, kmax, KA, KS, KE, &
2511 integer,
intent(in) :: KA_ref, kmax
2512 integer,
intent(in) :: KA, KS, KE
2513 integer,
intent(in) :: idx_k(KA,2)
2514 real(RP),
intent(in) :: vfact(KA)
2515 real(RP),
intent(in) :: hgt_ref(KA_ref)
2516 real(RP),
intent(in) :: hgt (KA)
2517 real(RP),
intent(in) :: val_ref(KA_ref)
2518 integer,
intent(in) :: idx (KA_ref)
2519 integer,
intent(in) :: idx_r (KA_ref)
2520 real(RP),
intent(in) :: U (KA_ref)
2521 real(RP),
intent(in) :: FDZ (KA_ref)
2523 real(RP),
intent(out) :: val(KA)
2525 real(RP) :: c1, c2, c3, d
2526 integer :: k, kk, kk2
2530 if ( kk == -1 )
then
2532 else if ( idx_k(k,2) == -1 )
then
2533 val(k) = val_ref(kk)
2534 else if ( kk < idx(1) .or. kk >= idx(kmax) )
then
2535 if ( abs( val_ref(kk) - undef ) < eps .or. abs( val_ref(kk+1) - undef ) < eps )
then
2538 val(k) = val_ref(kk) * vfact(k) + val_ref(kk+1) * ( 1.0_rp - vfact(k) )
2543 c3 = ( u(kk2+1) - u(kk2) ) / fdz(kk2+1)
2544 c2 = 3.0_rp * u(kk2)
2545 c1 = ( val_ref(idx(kk2+1)) - val_ref(kk) ) / fdz(kk2+1) - ( 2.0_rp * u(kk2) + u(kk2+1) ) * fdz(kk2+1)
2546 d = hgt(k) - hgt_ref(kk)
2548 val(k) = ( ( c3 * d + c2 ) * d + c1 ) * d + val_ref(kk)