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
861 lon_1d(:), lat_1d(:), &
864 i0(:), i1(:), j0(:), j1(:), &
865 lon(i,j), lat(i,j), &
866 idx_it(:), idx_jt(:), &
868 search_limit = search_limit, &
869 weight_order = weight_order )
871 idx_i(i,j,n) = idx_it(n)
872 idx_j(i,j,n) = idx_jt(n)
873 hfact(i,j,n) = hfactt(n)
879 deallocate( i0, i1, j0, j1 )
883 nsize = ia_ref * ja_ref
884 if ( nsize > 100 )
then
885 psize = int( sqrt(2.0_rp*sqrt(real(nsize,rp))) )
886 nidx_max = nsize / psize * interp_buffer_size_fact
892 allocate(idx_blk(nidx_max,psize,psize))
893 allocate(nidx( psize,psize))
898 lon_ref(:,:), lat_ref(:,:), &
899 idx_blk(:,:,:), nidx(:,:), &
912 call interp_search_horiz( npoints, &
914 lon_ref(:,:), lat_ref(:,:), &
919 idx_blk(:,:,:), nidx(:,:), &
920 lon(i,j), lat(i,j), &
923 search_limit = search_limit, &
924 weight_order = weight_order )
926 idx_i(i,j,n) = mod(idx_ref(n) - 1, ia_ref) + 1
927 idx_j(i,j,n) = ( idx_ref(n) - 1 ) / ia_ref + 1
928 hfact(i,j,n) = hfactt(n)
936 deallocate(idx_blk, nidx)
949 KA_ref, KS_ref, KE_ref, &
964 integer,
intent(in) :: ka_ref, ks_ref, ke_ref
965 integer,
intent(in) :: ia_ref
966 integer,
intent(in) :: ja_ref
967 integer,
intent(in) :: ka, ks, ke
968 integer,
intent(in) :: ia
969 integer,
intent(in) :: ja
970 real(rp),
intent(in) :: lon_ref(ia_ref)
971 real(rp),
intent(in) :: lat_ref(ja_ref)
972 real(rp),
intent(in) :: hgt_ref(ka_ref,ia_ref,ja_ref)
973 real(rp),
intent(in) :: lon(ia,ja)
974 real(rp),
intent(in) :: lat(ia,ja)
975 real(rp),
intent(in) :: hgt(ka,ia,ja)
977 integer,
intent(out) :: idx_i(ia,ja,4)
978 integer,
intent(out) :: idx_j(ia,ja,4)
979 real(rp),
intent(out) :: hfact(ia,ja,4)
980 integer,
intent(out) :: idx_k(ka,2,ia,ja,4)
981 real(rp),
intent(out) :: vfact(ka, ia,ja,4)
983 logical,
intent(in),
optional :: flag_extrap
985 integer :: i, j, ii, jj, n
992 lon_ref(:), lat_ref(:), &
993 lon(:,:), lat(:,:), &
994 idx_i(:,:,:), idx_j(:,:,:), hfact(:,:,:) )
1015 flag_extrap = flag_extrap )
1033 KA_ref, KS_ref, KE_ref, &
1049 integer,
intent(in) :: ka_ref, ks_ref, ke_ref
1050 integer,
intent(in) :: ia_ref
1051 integer,
intent(in) :: ja_ref
1052 integer,
intent(in) :: ka, ks, ke
1053 integer,
intent(in) :: ia
1054 integer,
intent(in) :: ja
1055 real(rp),
intent(in) :: x_ref(ia_ref,ja_ref)
1056 real(rp),
intent(in) :: y_ref(ia_ref,ja_ref)
1057 real(rp),
intent(in) :: hgt_ref(ka_ref,ia_ref,ja_ref)
1058 real(rp),
intent(in) :: x (ia)
1059 real(rp),
intent(in) :: y (ja)
1060 real(rp),
intent(in) :: hgt(ka,ia,ja)
1062 integer,
intent(out) :: idx_i(ia,ja,4)
1063 integer,
intent(out) :: idx_j(ia,ja,4)
1064 real(rp),
intent(out) :: hfact(ia,ja,4)
1065 integer,
intent(out) :: idx_k(ka,2,ia,ja,4)
1066 real(rp),
intent(out) :: vfact(ka, ia,ja,4)
1068 logical,
intent(in),
optional :: flag_extrap
1069 logical,
intent(in),
optional :: zonal
1070 logical,
intent(in),
optional :: pole
1071 logical,
intent(in),
optional :: missing
1073 integer :: i, j, ii, jj, n
1080 x_ref(:,:), y_ref(:,:), &
1082 idx_i(:,:,:), idx_j(:,:,:), hfact(:,:,:), &
1083 zonal = zonal, pole = pole, &
1105 flag_extrap = flag_extrap )
1123 KA_ref, KS_ref, KE_ref, &
1139 integer,
intent(in) :: npoints
1140 integer,
intent(in) :: ka_ref, ks_ref, ke_ref
1141 integer,
intent(in) :: ia_ref
1142 integer,
intent(in) :: ja_ref
1143 integer,
intent(in) :: ka, ks, ke
1144 integer,
intent(in) :: ia
1145 integer,
intent(in) :: ja
1147 real(rp),
intent(in) :: lon_ref(ia_ref,ja_ref)
1148 real(rp),
intent(in) :: lat_ref(ia_ref,ja_ref)
1149 real(rp),
intent(in) :: hgt_ref(ka_ref,ia_ref,ja_ref)
1150 real(rp),
intent(in) :: lon (ia,ja)
1151 real(rp),
intent(in) :: lat (ia,ja)
1152 real(rp),
intent(in) :: hgt (ka,ia,ja)
1154 integer,
intent(out) :: idx_i(ia,ja,npoints)
1155 integer,
intent(out) :: idx_j(ia,ja,npoints)
1156 real(rp),
intent(out) :: hfact(ia,ja,npoints)
1157 integer,
intent(out) :: idx_k(ka,2,ia,ja,npoints)
1158 real(rp),
intent(out) :: vfact(ka, ia,ja,npoints)
1160 logical,
intent(in),
optional :: flag_extrap
1162 integer :: nsize, psize, nidx_max
1163 integer,
allocatable :: idx_blk(:,:,:), nidx(:,:)
1164 real(rp) :: lon_min, lon_max
1165 real(rp) :: lat_min, lat_max
1166 real(rp) :: dlon, dlat
1167 integer :: idx_ref(npoints)
1168 real(rp) :: hfactt(npoints)
1170 integer :: i, j, ii, jj, n
1175 nsize = ia_ref * ja_ref
1176 if ( nsize > 100 )
then
1177 psize = int( sqrt(2.0_rp*sqrt(real(nsize,rp))) )
1178 nidx_max = nsize / psize * interp_buffer_size_fact
1184 allocate(idx_blk(nidx_max,psize,psize))
1185 allocate(nidx( psize,psize))
1192 lon_ref(:,:), lat_ref(:,:), &
1193 idx_blk(:,:,:), nidx(:,:), &
1207 call interp_search_horiz( npoints, &
1209 lon_ref(:,:), lat_ref(:,:), &
1214 idx_blk(:,:,:), nidx(:,:), &
1215 lon(i,j), lat(i,j), &
1216 idx_ref(:), hfactt(:) )
1220 ii = mod(idx_ref(n) - 1, ia_ref) + 1
1221 jj = ( idx_ref(n) - 1 ) / ia_ref + 1
1224 hfact(i,j,n) = hfactt(n)
1231 flag_extrap = flag_extrap )
1240 deallocate(idx_blk, nidx)
1251 KA_ref, KS_ref, KE_ref, &
1269 integer,
intent(in) :: ka_ref, ks_ref, ke_ref
1270 integer,
intent(in) :: ka, ks, ke
1272 integer,
intent(in) :: idx_k(ka,2)
1273 real(rp),
intent(in) :: vfact(ka )
1274 real(rp),
intent(in) :: hgt_ref(ka_ref)
1275 real(rp),
intent(in) :: hgt (ka)
1276 real(rp),
intent(in),
target :: val_ref(ka_ref)
1278 real(rp),
intent(out) :: val (ka)
1280 logical,
intent(in),
optional :: spline
1281 logical,
intent(in),
optional :: logwgt
1286 real(rp),
pointer :: work(:)
1289 real(rp),
intent(out),
target :: workr(ka_ref,7)
1290 integer,
intent(out) :: worki(ka_ref,2)
1291 #define idx_i1(k) worki(k,1)
1292 #define idx_r_i1(k) worki(k,2)
1293 #define FDZ_i1(k) workr(k,1)
1294 #define U_i1(k) workr(k,2)
1296 integer :: idx_i1 (ka_ref)
1297 integer :: idx_r_i1(ka_ref)
1298 real(rp) :: fdz_i1 (ka_ref)
1299 real(rp) :: u_i1 (ka_ref)
1306 spline_ = interp_use_spline_vert
1307 if (
present(spline) )
then
1312 if (
present(logwgt) )
then
1320 allocate( work(ka_ref) )
1322 do k = ks_ref, ke_ref
1323 if ( abs( val_ref(k) - undef ) < eps )
then
1326 work(k) = log( val_ref(k) )
1333 call spline_coef( ka_ref, ks_ref, ke_ref, &
1337 hgt_ref(:), work(:), &
1340 idx_i1(:), idx_r_i1(:), &
1341 u_i1(:), fdz_i1(:) )
1344 idx_k(:,:), vfact(:), &
1345 hgt_ref(:), hgt(:), &
1347 idx_i1(:), idx_r_i1(:), &
1348 u_i1(:), fdz_i1(:), &
1356 if ( abs( val(k) - undef ) > eps )
then
1357 val(k) = exp( val(k) )
1382 integer,
intent(in) :: npoints
1383 integer,
intent(in) :: ia_ref
1384 integer,
intent(in) :: ja_ref
1385 integer,
intent(in) :: ia
1386 integer,
intent(in) :: ja
1387 integer,
intent(in) :: idx_i (ia,ja,npoints)
1388 integer,
intent(in) :: idx_j (ia,ja,npoints)
1389 real(rp),
intent(in) :: hfact (ia,ja,npoints)
1390 real(rp),
intent(in) :: val_ref(ia_ref,ja_ref)
1392 real(rp),
intent(out) :: val (ia,ja)
1394 real(rp),
intent(in),
optional :: threshold_undef
1395 real(rp),
intent(out),
optional :: wsum(ia,ja)
1396 real(rp),
intent(out),
optional :: val2(ia,ja)
1398 real(rp) :: th_undef
1400 real(rp) :: fact, valn, f, w
1409 if (
present(threshold_undef) )
then
1410 th_undef = threshold_undef
1412 th_undef = interp_threshold_undef
1414 th_undef = min( max( th_undef, eps * 2.0_rp ), 1.0_rp - eps * 2.0_rp )
1416 lval2 =
present(wsum) .and.
present(val2)
1429 w = val_ref(idx_i(i,j,n),idx_j(i,j,n))
1430 if ( f > eps .and. abs( w - undef ) > eps )
then
1435 sw = 0.5_rp - sign( 0.5_rp, fact - th_undef + eps )
1436 val(i,j) = valn / ( fact + sw ) * ( 1.0_rp - sw ) + undef * sw
1439 sw = 0.5_rp - sign( 0.5_rp, fact - eps )
1440 val2(i,j) = valn / ( fact + sw ) * ( 1.0_rp - sw ) + undef * sw
1455 KA_ref, KS_ref, KE_ref, &
1474 integer,
intent(in) :: npoints
1475 integer,
intent(in) :: ka_ref, ks_ref, ke_ref
1476 integer,
intent(in) :: ia_ref
1477 integer,
intent(in) :: ja_ref
1478 integer,
intent(in) :: ka, ks, ke
1479 integer,
intent(in) :: ia
1480 integer,
intent(in) :: ja
1482 integer,
intent(in) :: idx_i (ia,ja,npoints)
1483 integer,
intent(in) :: idx_j (ia,ja,npoints)
1484 real(rp),
intent(in) :: hfact (ia,ja,npoints)
1485 integer,
intent(in) :: idx_k (ka,2,ia,ja,npoints)
1486 real(rp),
intent(in) :: vfact (ka, ia,ja,npoints)
1487 real(rp),
intent(in) :: hgt_ref(ka_ref,ia_ref,ja_ref)
1488 real(rp),
intent(in) :: hgt (ka,ia,ja)
1489 real(rp),
intent(in),
target :: val_ref(ka_ref,ia_ref,ja_ref)
1491 real(rp),
intent(out) :: val (ka,ia,ja)
1493 logical,
intent(in),
optional :: spline
1494 logical,
intent(in),
optional :: logwgt
1495 real(rp),
intent(in),
optional :: threshold_undef
1496 real(rp),
intent(out),
optional :: wsum(ka,ia,ja)
1497 real(rp),
intent(out),
optional :: val2(ka,ia,ja)
1499 real(rp) :: th_undef
1503 real(rp),
pointer :: work(:,:,:)
1505 integer,
allocatable :: kmax(:,:)
1506 integer,
allocatable :: idx(:,:,:), idx_r(:,:,:)
1507 real(rp),
allocatable :: u(:,:,:), fdz(:,:,:)
1513 real(rp) :: w(ka,npoints)
1517 real(rp) :: workr(ka_ref,4)
1520 integer :: imin, imax
1521 integer :: jmin, jmax
1523 integer :: k, i, j, n
1528 if (
present(threshold_undef) )
then
1529 th_undef = threshold_undef
1531 th_undef = interp_threshold_undef
1533 th_undef = min( max( th_undef, eps * 2.0_rp ), 1.0_rp - eps * 2.0_rp )
1536 spline_ = interp_use_spline_vert
1537 if (
present(spline) )
then
1542 if (
present(logwgt) )
then
1547 lval2 =
present(wsum) .and.
present(val2)
1570 imin = min(imin, idx_i(i,j,n))
1571 imax = max(imax, idx_i(i,j,n))
1572 jmin = min(jmin, idx_j(i,j,n))
1573 jmax = max(jmax, idx_j(i,j,n))
1579 allocate( kmax(imin:imax,jmin:jmax) )
1580 allocate( idx(ka_ref,imin:imax,jmin:jmax), idx_r(ka_ref,imin:imax,jmin:jmax) )
1581 allocate( u(ka_ref,imin:imax,jmin:jmax), fdz(ka_ref,imin:imax,jmin:jmax) )
1585 allocate( work(ka_ref,imin:imax,jmin:jmax) )
1594 do k = ks_ref, ke_ref
1595 if ( abs( val_ref(k,i,j) - undef ) < eps )
then
1598 work(k,i,j) = log( val_ref(k,i,j) )
1614 call spline_coef( ka_ref, ks_ref, ke_ref, &
1618 hgt_ref(:,i,j), work(:,i,j), &
1621 idx(:,i,j), idx_r(:,i,j), &
1622 u(:,i,j), fdz(:,i,j) )
1637 if ( hfact(i,j,n) > eps )
then
1640 call spline_exec( ka_ref, kmax(ii,jj), ka, ks, ke, &
1641 idx_k(:,:,i,j,n), vfact(:, i,j,n), &
1642 hgt_ref(:,ii,jj), hgt(:,i,j), &
1644 idx(:,ii,jj), idx_r(:,ii,jj), &
1645 u(:,ii,jj), fdz(:,ii,jj), &
1656 if ( f > eps .and. abs( w(k,n) - undef ) > eps )
then
1658 valn = valn + f * w(k,n)
1661 sw = 0.5_rp - sign( 0.5_rp, fact - th_undef )
1662 val(k,i,j) = valn / ( fact + sw ) * ( 1.0_rp - sw ) + undef * sw
1665 sw = 0.5_rp - sign( 0.5_rp, fact - eps )
1666 val2(k,i,j) = valn / ( fact + sw ) * ( 1.0_rp - sw ) + undef * sw
1675 deallocate( kmax, idx, idx_r )
1676 deallocate( u, fdz )
1686 if ( abs( val(k,i,j) - undef ) > eps )
then
1687 val(k,i,j) = exp( val(k,i,j) )
1711 subroutine interp_search_horiz( &
1731 integer,
intent(in) :: npoints
1732 integer,
intent(in) :: nsize
1733 real(rp),
intent(in) :: lon_ref(nsize)
1734 real(rp),
intent(in) :: lat_ref(nsize)
1735 real(rp),
intent(in) :: lon_min
1736 real(rp),
intent(in) :: lon_max
1737 real(rp),
intent(in) :: lat_min
1738 real(rp),
intent(in) :: lat_max
1739 integer,
intent(in) :: psize
1740 integer,
intent(in) :: nidx_max
1741 real(rp),
intent(in) :: dlon
1742 real(rp),
intent(in) :: dlat
1743 integer,
intent(in) :: idx_blk(nidx_max,psize,psize)
1744 integer,
intent(in) :: nidx (psize,psize)
1745 real(rp),
intent(in) :: lon
1746 real(rp),
intent(in) :: lat
1747 integer,
intent(out) :: idx_ref(npoints)
1748 real(rp),
intent(out) :: hfact(npoints)
1750 real(rp),
intent(in),
optional :: search_limit
1751 integer,
intent(in),
optional :: weight_order
1753 real(rp) :: drad(npoints)
1755 real(rp) :: search_limit_
1756 integer :: weight_order_
1758 real(rp) :: lon0, lon1, lat0, lat1
1759 real(rp) :: dlon_sl, dlat_sl
1761 integer :: ii, jj, ii0, jj0
1764 if (
present(search_limit) )
then
1765 search_limit_ = search_limit
1767 search_limit_ = interp_search_limit
1769 search_limit_ = search_limit_ / radius
1771 if (
present(weight_order) )
then
1772 weight_order_ = weight_order
1774 weight_order_ = interp_weight_order
1779 drad(:) = large_number
1783 ii0 = max( min( int(( lon - lon_min ) / dlon) + 1, psize ), 1 )
1784 jj0 = max( min( int(( lat - lat_min ) / dlat) + 1, psize ), 1 )
1785 do i = 1, nidx(ii0,jj0)
1786 n = idx_blk(i,ii0,jj0)
1787 call interp_insert( npoints, &
1789 lon_ref(n), lat_ref(n), &
1791 drad(:), idx_ref(:) )
1794 if ( abs(drad(1)) < eps )
then
1799 else if ( drad(1) > search_limit_ )
then
1806 dlon_sl = max(dlon * 0.5_rp, drad(npoints))
1807 dlat_sl = max(dlat * 0.5_rp, drad(npoints))
1809 lat0 = lat_min + dlat * (jj-1)
1810 lat1 = lat_min + dlat * jj
1811 if ( lat < lat0 - dlat_sl &
1812 .or. lat >= lat1 + dlat_sl ) cycle
1814 if ( ii==ii0 .and. jj==jj0 ) cycle
1815 lon0 = lon_min + dlon * (ii-1)
1816 lon1 = lon_min + dlon * ii
1817 if ( lon < lon0 - dlon_sl &
1818 .or. lon >= lon1 + dlon_sl ) cycle
1819 do i = 1, nidx(ii,jj)
1820 n = idx_blk(i,ii,jj)
1821 call interp_insert( npoints, &
1823 lon_ref(n), lat_ref(n), &
1825 drad(:), idx_ref(:) )
1827 dlon_sl = max(dlon * 0.5_rp, drad(npoints))
1828 dlat_sl = max(dlat * 0.5_rp, drad(npoints))
1833 if ( weight_order_ < 0 )
then
1835 hfact(n) = 1.0_rp / drad(n)**(-1.0_rp/weight_order_)
1839 hfact(n) = 1.0_rp / drad(n)**weight_order_
1845 if ( drad(n) >= search_limit_ )
then
1853 sum = sum + hfact(n)
1856 if ( sum > 0.0_rp )
then
1858 hfact(n) = hfact(n) / sum
1863 end subroutine interp_search_horiz
1887 integer,
intent(in) :: npoints
1888 integer,
intent(in) :: psizex
1889 integer,
intent(in) :: psizey
1890 integer,
intent(in) :: IA_ref
1891 integer,
intent(in) :: JA_ref
1892 real(RP),
intent(in) :: lon_ref(IA_ref)
1893 real(RP),
intent(in) :: lat_ref(JA_ref)
1894 real(RP),
intent(in) :: lon_min
1895 real(RP),
intent(in) :: lat_min
1896 real(RP),
intent(in) :: dlon
1897 real(RP),
intent(in) :: dlat
1898 integer,
intent(in) :: i0(psizex)
1899 integer,
intent(in) :: i1(psizex)
1900 integer,
intent(in) :: j0(psizey)
1901 integer,
intent(in) :: j1(psizey)
1902 real(RP),
intent(in) :: lon
1903 real(RP),
intent(in) :: lat
1904 integer,
intent(out) :: idx_i(npoints)
1905 integer,
intent(out) :: idx_j(npoints)
1906 real(RP),
intent(out) :: hfact(npoints)
1908 real(RP),
intent(in),
optional :: search_limit
1909 integer,
intent(in),
optional :: weight_order
1911 real(RP) :: drad(npoints)
1913 real(RP) :: search_limit_
1914 integer :: weight_order_
1916 real(RP) :: lon0, lon1, lat0, lat1
1917 real(RP) :: dlon_sl, dlat_sl
1920 integer :: ii, jj, ii0, jj0
1923 if (
present(search_limit) )
then
1924 search_limit_ = search_limit
1926 search_limit_ = interp_search_limit
1928 search_limit_ = search_limit_ / radius
1930 if (
present(weight_order) )
then
1931 weight_order_ = weight_order
1933 weight_order_ = interp_weight_order
1937 drad(:) = large_number
1942 ii0 = max( min( int(( lon - lon_min ) / dlon) + 1, psizex ), 1)
1943 jj0 = max( min( int(( lat - lat_min ) / dlat) + 1, psizey ), 1)
1944 do j = j0(jj0), j1(jj0)
1945 do i = i0(ii0), i1(ii0)
1948 lon_ref(i), lat_ref(j), &
1950 drad(:), idx_i(:), idx_j(:) )
1954 if ( abs(drad(1)) < eps )
then
1959 else if ( drad(1) > search_limit_ )
then
1967 dlon_sl = max(dlon * 0.5_rp, drad(npoints))
1968 dlat_sl = max(dlat * 0.5_rp, drad(npoints))
1970 lat0 = lat_min + dlat * (jj-1)
1971 lat1 = lat_min + dlat * jj
1972 if ( lat < lat0 - dlat_sl &
1973 .or. lat >= lat1 + dlat_sl ) cycle
1975 if ( ii==ii0 .and. jj==jj0 ) cycle
1976 lon0 = lon_min + dlon * (ii-1)
1977 lon1 = lon_min + dlon * ii
1978 if ( lon < lon0 - dlon_sl &
1979 .or. lon >= lon1 + dlon_sl ) cycle
1980 do j = j0(jj0), j1(jj0)
1981 do i = i0(ii0), i1(ii0)
1984 lon_ref(i), lat_ref(j), &
1986 drad(:), idx_i(:), idx_j(:) )
1989 dlon_sl = max(dlon * 0.5_rp, drad(npoints))
1990 dlat_sl = max(dlat * 0.5_rp, drad(npoints))
1996 if ( weight_order_ < 0 )
then
1998 hfact(n) = 1.0_rp / drad(n)**(-1.0_rp/weight_order_)
2002 hfact(n) = 1.0_rp / drad(n)**weight_order_
2008 if ( drad(n) >= search_limit_ )
then
2016 sum = sum + hfact(n)
2019 if ( sum > 0.0_rp )
then
2021 hfact(n) = hfact(n) / sum
2030 subroutine interp_insert( npoints, &
2042 integer,
intent(in) :: npoints
2043 real(RP),
intent(in) :: lon, lat
2044 real(RP),
intent(in) :: lon_ref, lat_ref
2045 integer,
intent(in),
value :: i
2047 real(RP),
intent(inout) :: drad(npoints)
2048 integer,
intent(inout) :: idx_i(npoints)
2052 if ( abs( lon_ref - undef ) < eps )
return
2054 dradian = haversine( lon, lat, lon_ref, lat_ref )
2056 if ( dradian <= drad(npoints) )
then
2058 drad(npoints) = dradian
2062 call sort_exec( npoints, &
2068 end subroutine interp_insert
2075 drad, idx_i, idx_j )
2083 integer,
intent(in) :: npoints
2084 real(RP),
intent(in) :: lon, lat
2085 real(RP),
intent(in) :: lon_ref, lat_ref
2086 integer,
intent(in),
value :: i, j
2088 real(RP),
intent(inout) :: drad(npoints)
2089 integer,
intent(inout) :: idx_i(npoints)
2090 integer,
intent(inout) :: idx_j(npoints)
2094 if ( abs( lon_ref - undef ) < eps )
return
2096 dradian = haversine( lon, lat, lon_ref, lat_ref )
2098 if ( dradian <= drad(npoints) )
then
2100 drad(npoints) = dradian
2105 call sort_exec( npoints, &
2126 integer,
intent(in) :: nsize
2127 integer,
intent(in) :: psize
2128 integer,
intent(in) :: nidx_max
2129 real(RP),
intent(in) :: lon_ref(nsize)
2130 real(RP),
intent(in) :: lat_ref(nsize)
2132 integer,
intent(out) :: idx (nidx_max,psize,psize)
2133 integer,
intent(out) :: nidx(psize,psize)
2134 real(RP),
intent(out) :: lon_min, lon_max
2135 real(RP),
intent(out) :: lat_min, lat_max
2136 real(RP),
intent(out) :: dlon, dlat
2138 integer :: i, ii, jj, n
2150 if ( abs(lon_ref(i) - undef) > eps )
then
2151 lon_min = min( lon_min, lon_ref(i) )
2152 lon_max = max( lon_max, lon_ref(i) )
2154 if ( abs(lat_ref(i) - undef) > eps )
then
2155 lat_min = min( lat_min, lat_ref(i) )
2156 lat_max = max( lat_max, lat_ref(i) )
2161 dlon = ( lon_max - lon_min ) / psize
2162 dlat = ( lat_max - lat_min ) / psize
2170 if ( abs( lon_ref(i) - undef ) < eps ) cycle
2171 ii = min(int((lon_ref(i) - lon_min) / dlon) + 1, psize)
2172 jj = min(int((lat_ref(i) - lat_min) / dlat) + 1, psize)
2178 if ( n <= nidx_max ) idx(n,ii,jj) = i
2184 if ( maxval(nidx) > nidx_max )
then
2185 log_error(
"INTERP_search_horiz",*)
'Buffer size is not enough'
2186 log_error_cont(*)
' Use larger INTERP_buffer_size_fact: ', interp_buffer_size_fact * maxval(nidx)/nidx_max
2195 x_ref0, x_ref1, x_ref2, x_ref3, &
2196 y_ref0, y_ref1, y_ref2, y_ref3, &
2202 real(RP),
intent(in),
value :: x_ref0, x_ref1, x_ref2, x_ref3
2203 real(RP),
intent(in),
value :: y_ref0, y_ref1, y_ref2, y_ref3
2204 real(RP),
intent(in),
value :: x, y
2206 real(RP),
intent(out) :: u, v
2207 logical,
intent(out) :: error
2209 real(RP) :: e_x, e_y
2210 real(RP) :: f_x, f_y
2211 real(RP) :: g_x, g_y
2212 real(RP) :: h_x, h_y
2213 real(RP) :: k0, k1, k2
2217 e_x = x_ref1 - x_ref0
2218 e_y = y_ref1 - y_ref0
2220 f_x = x_ref3 - x_ref0
2221 f_y = y_ref3 - y_ref0
2223 g_x = x_ref0 - x_ref1 + x_ref2 - x_ref3
2224 g_y = y_ref0 - y_ref1 + y_ref2 - y_ref3
2229 k0 =
cross(h_x, h_y, e_x, e_y)
2230 k1 =
cross(e_x, e_y, f_x, f_y) +
cross(h_x, h_y, g_x, g_y)
2231 k2 =
cross(g_x, g_y, f_x, f_y)
2233 w = k1**2 - 4.0_rp * k0 * k2
2234 if ( w < 0.0_rp )
then
2236 log_error(
"INTERP_bilinear_inv",*)
'Outside of the quadrilateral'
2242 if ( abs(k1) < eps_bilinear )
then
2244 log_error(
"INTERP_bilinear_inv",*)
'Unexpected error occured', k1
2245 log_error_cont(*) x_ref0, x_ref1, x_ref2, x_ref3
2246 log_error_cont(*) y_ref0, y_ref1, y_ref2, y_ref3
2247 log_error_cont(*) x, y
2252 if ( abs(k2) < eps_bilinear * sqrt( (x_ref2-x_ref0)**2+(y_ref2-y_ref0)**2 ) )
then
2255 sig = sign( 1.0_rp,
cross(x_ref1-x_ref0, y_ref1-y_ref0, x_ref3-x_ref0, y_ref3-y_ref0) )
2256 v = ( - k1 + sig * sqrt(w) ) / ( 2.0_rp * k2 )
2258 u = ( h_x - f_x * v ) / ( e_x + g_x * v )
2260 if ( u < -eps_bilinear .or. u > 1.0_rp+eps_bilinear .or. v < -eps_bilinear .or. v > 1.0_rp+eps_bilinear )
then
2262 log_error(
"INTERP_bilinear_inv",*)
'Unexpected error occured', u, v
2263 log_error_cont(*) x_ref0, x_ref1, x_ref2, x_ref3
2264 log_error_cont(*) y_ref0, y_ref1, y_ref2, y_ref3
2265 log_error_cont(*) x, y
2266 log_error_cont(*) k0, k1, k2, sig
2271 u = min( max( u, 0.0_rp ), 1.0_rp )
2272 v = min( max( v, 0.0_rp ), 1.0_rp )
2281 subroutine interp_check_inside( &
2282 x_ref0, x_ref1, x_ref2, x_ref3, &
2283 y_ref0, y_ref1, y_ref2, y_ref3, &
2291 real(RP),
intent(in),
value :: x_ref0, x_ref1, x_ref2, x_ref3
2292 real(RP),
intent(in),
value :: y_ref0, y_ref1, y_ref2, y_ref3
2293 real(RP),
intent(in),
value :: x, y
2295 integer,
intent(out) :: inc_i, inc_j
2296 logical,
intent(out) :: error
2299 real(RP) :: c1, c2, c3, c4
2305 sig = sign( 1.0_rp,
cross(x_ref1-x_ref0, y_ref1-y_ref0, x_ref3-x_ref0, y_ref3-y_ref0) )
2307 c1 = sig *
cross(x_ref1-x_ref0, y_ref1-y_ref0, x-x_ref0, y-y_ref0)
2308 c2 = sig *
cross(x_ref2-x_ref1, y_ref2-y_ref1, x-x_ref1, y-y_ref1)
2309 c3 = sig *
cross(x_ref3-x_ref2, y_ref3-y_ref2, x-x_ref2, y-y_ref2)
2310 c4 = sig *
cross(x_ref0-x_ref3, y_ref0-y_ref3, x-x_ref3, y-y_ref3)
2312 th = - max( abs(c1), abs(c2), abs(c3), abs(c4) ) * eps * 1.e4_rp
2317 if ( c1 < th ) inc_j = -1
2318 if ( c2 < th ) inc_i = 1
2319 if ( c3 < th ) inc_j = 1
2320 if ( c4 < th ) inc_i = -1
2322 fx = c2 < th .and. c4 < th
2323 fy = c1 < th .and. c3 < th
2324 if ( fx .and. fy )
then
2326 log_error(
"INTERP_check_inside",*)
'Unexpected error occured', c1, c2, c3, c4
2327 log_error_cont(*) x_ref0, x_ref1, x_ref2, x_ref3
2328 log_error_cont(*) y_ref0, y_ref1, y_ref2, y_ref3
2329 log_error_cont(*) x, y
2340 end subroutine interp_check_inside
2349 real(rp),
intent(in) :: x0, y0
2350 real(rp),
intent(in) :: x1, y1
2353 cross = x0 * y1 - x1 * y0
2360 function haversine( &
2367 real(rp),
intent(in) :: lon0
2368 real(rp),
intent(in) :: lat0
2369 real(rp),
intent(in) :: lon1
2370 real(rp),
intent(in) :: lat1
2373 real(rp) :: dlonh, dlath
2377 dlonh = 0.5_rp * ( lon0 - lon1 )
2378 dlath = 0.5_rp * ( lat0 - lat1 )
2380 work1 = sin(dlath)**2 + cos(lat0) * cos(lat1) * sin(dlonh)**2
2382 d = 2.0_rp * asin( min(sqrt(work1),1.0_rp) )
2384 end function haversine
2388 subroutine spline_coef( &
2389 KA_ref, KS_ref, KE_ref, &
2405 integer,
intent(in) :: ka_ref, ks_ref, ke_ref
2407 real(rp),
intent(in) :: hgt_ref(ka_ref)
2408 real(rp),
intent(in) :: val_ref(ka_ref)
2409 logical,
intent(in) :: spline
2411 integer,
intent(out) :: kmax
2412 integer,
intent(out) :: idx (ka_ref)
2413 integer,
intent(out) :: idx_r(ka_ref)
2414 real(rp),
intent(out) :: u (ka_ref)
2415 real(rp),
intent(out) :: fdz(ka_ref)
2418 real(rp),
intent(out) :: work(ka_ref,4)
2419 #define MD_sc(k) work(k,1)
2420 #define V_sc(k) work(k,2)
2422 real(rp) :: md_sc(ka_ref)
2423 real(rp) :: v_sc (ka_ref)
2432 do k = ks_ref, ke_ref-1
2433 if ( hgt_ref(k) > undef .and. abs( val_ref(k) - undef ) > eps )
then
2439 if ( idx(1) == -999 )
return
2441 do k = idx(1)+1, ke_ref
2442 if ( hgt_ref(k) > undef )
then
2443 dz = hgt_ref(k) - hgt_ref(idx(kmax))
2444 if ( abs( val_ref(k) - undef ) > eps .and. dz > eps )
then
2445 do while ( kmax > 1 .and. fdz(kmax) < dz * 0.1_rp )
2450 if ( idx(kmax-1)+1 <= k-1 ) idx_r(idx(kmax-1)+1:k-1) = kmax-1
2452 fdz(kmax) = hgt_ref(k) - hgt_ref(idx(kmax-1))
2457 if ( kmax > 3 )
then
2459 md_sc(2) = 2.0_rp * ( fdz(2) + fdz(3) ) + fdz(2)
2461 md_sc(k) = 2.0_rp * ( fdz(k) + fdz(k+1) )
2463 md_sc(kmax-1) = 2.0_rp * ( fdz(kmax-1) + fdz(kmax) ) + fdz(kmax)
2466 v_sc(k) = ( val_ref(idx(k+1)) - val_ref(idx(k )) ) / fdz(k+1) &
2467 - ( val_ref(idx(k )) - val_ref(idx(k-1)) ) / fdz(k )
2474 fdz(2:), md_sc(:), fdz(:), &
2496 end subroutine spline_coef
2500 KA_ref, kmax, KA, KS, KE, &
2512 integer,
intent(in) :: KA_ref, kmax
2513 integer,
intent(in) :: KA, KS, KE
2514 integer,
intent(in) :: idx_k(KA,2)
2515 real(RP),
intent(in) :: vfact(KA)
2516 real(RP),
intent(in) :: hgt_ref(KA_ref)
2517 real(RP),
intent(in) :: hgt (KA)
2518 real(RP),
intent(in) :: val_ref(KA_ref)
2519 integer,
intent(in) :: idx (KA_ref)
2520 integer,
intent(in) :: idx_r (KA_ref)
2521 real(RP),
intent(in) :: U (KA_ref)
2522 real(RP),
intent(in) :: FDZ (KA_ref)
2524 real(RP),
intent(out) :: val(KA)
2526 real(RP) :: c1, c2, c3, d
2527 integer :: k, kk, kk2
2531 if ( kk == -1 )
then
2533 else if ( idx_k(k,2) == -1 )
then
2534 val(k) = val_ref(kk)
2535 else if ( kk < idx(1) .or. kk >= idx(kmax) )
then
2536 if ( abs( val_ref(kk) - undef ) < eps .or. abs( val_ref(kk+1) - undef ) < eps )
then
2539 val(k) = val_ref(kk) * vfact(k) + val_ref(kk+1) * ( 1.0_rp - vfact(k) )
2544 c3 = ( u(kk2+1) - u(kk2) ) / fdz(kk2+1)
2545 c2 = 3.0_rp * u(kk2)
2546 c1 = ( val_ref(idx(kk2+1)) - val_ref(kk) ) / fdz(kk2+1) - ( 2.0_rp * u(kk2) + u(kk2+1) ) * fdz(kk2+1)
2547 d = hgt(k) - hgt_ref(kk)
2549 val(k) = ( ( c3 * d + c2 ) * d + c1 ) * d + val_ref(kk)