1 SUBROUTINE da_gpseph_create_ob ( nlevel, h, ref, lat, lon, azim, pseudo_ob, lowest_level )
3 !---------------------------------------------------------------------------------------
4 ! Purpose: calculate pseudo obs (refractivity) at the mean height of each model level.
5 ! (Chen et al., 2009, doi:10.3319/TAO.2007.11.29.01(F3C))
6 ! It is called by da_read_obs_bufrgpsro_eph (when ob_format_gpsro=1)
7 ! or da_read_obs_ascii (when ob_format_gpsro=2).
8 !---------------------------------------------------------------------------------------
12 type (ob_in_mean_h), intent(inout) :: pseudo_ob
13 integer, intent(out) :: lowest_level
14 integer, intent(in) :: nlevel
15 real, intent(in) :: h(nlevel)
16 real, intent(in) :: ref(nlevel)
17 real, intent(in) :: lat(nlevel)
18 real, intent(in) :: lon(nlevel)
19 real, intent(in) :: azim(nlevel)
22 integer :: nlevel_valid, icount
25 real, dimension(kds:kde) :: mean_h
27 real, allocatable :: log_ref(:) !nlevel_valid
28 real, allocatable :: h_km(:) !nlevel_valid
29 real, allocatable :: lat_used(:) !nlevel_valid
30 real, allocatable :: lon_used(:) !nlevel_valid
31 real, allocatable :: azim_used(:) !nlevel_valid
33 real, dimension(interpolate_level) :: tmp_z ! obs. levels are interpolated
34 ! into levels of interpolate_level
35 real, dimension(interpolate_level) :: tmp_ref
36 real, dimension(interpolate_level) :: tmp_lat
37 real, dimension(interpolate_level) :: tmp_lon
38 real, dimension(interpolate_level) :: tmp_azim
42 pseudo_ob%ref(:) = 0.0
43 pseudo_ob%lat(:) = 0.0
44 pseudo_ob%lon(:) = 0.0
45 pseudo_ob%azim(:)= 0.0
47 ! exclude the levels with invalid ref and h data
48 ! first find out the nlevel_valid for allocating the working arrays
51 if ( (ref(k) > 0.0) .and. (h(k) > 0.0) .and. &
52 (abs(lat(k)) <= 90.0) .and. &
53 (abs(lon(k)) <= 180.0) .and. &
54 (abs(azim(k)) <= 180.0) ) then
59 if ( nlevel_valid < 1 ) return
60 allocate (log_ref (nlevel_valid))
61 allocate (h_km (nlevel_valid))
62 allocate (lat_used (nlevel_valid))
63 allocate (lon_used (nlevel_valid))
64 allocate (azim_used(nlevel_valid))
66 ! copy the valid levels to the working arrays
69 if ( (ref(k) > 0.0) .and. (h(k) > 0.0) .and. &
70 (abs(lat(k)) <= 90.0) .and. &
71 (abs(lon(k)) <= 180.0) .and. &
72 (abs(azim(k)) <= 180.0) ) then
74 log_ref(icount) = log(ref(k))
75 h_km(icount) = h(k)*0.001 !m to km, observation height
76 lat_used(icount) = lat(k)
77 lon_used(icount) = lon(k)
78 azim_used(icount) = azim(k)
82 mean_h(:) = global_h_mean(:) !km, model mean height
85 if ( mean_h(k) > h_km(1) ) exit
89 ! interpolate_level =2000, tmp_z(k) increase with constant interval(0.01 km) in the vertical direction
90 !hcl-todo make 0.01 and 20km_top (used to derive interpolate_level) namelist options
91 do k=1,interpolate_level
92 tmp_z(k) = h_km(1)+0.01*(k-1)
95 ! interpolate variables and smooth them on the standard height grid
96 CALL lintp( nlevel_valid, h_km, log_ref, &
97 interpolate_level, tmp_z, tmp_ref )
98 CALL lintp( nlevel_valid, h_km, lat_used, &
99 interpolate_level, tmp_z, tmp_lat )
100 CALL lintp( nlevel_valid, h_km, lon_used, &
101 interpolate_level, tmp_z, tmp_lon )
102 CALL lintp( nlevel_valid, h_km, azim_used, &
103 interpolate_level, tmp_z, tmp_azim )
105 do i = lowest_level+1, kte-1
107 do j = 1, interpolate_level
108 if (tmp_z(j) < (mean_h(i)+mean_h(i-1))/2.0) nstart = j
109 if (tmp_z(j) < (mean_h(i)+mean_h(i+1))/2.0) nstop = j
112 pseudo_ob%ref(i) = 0.0
113 pseudo_ob%lat(i) = 0.0
114 pseudo_ob%lon(i) = 0.0
115 pseudo_ob%azim(i)= 0.0
118 pseudo_ob%ref(i) = pseudo_ob%ref(i) + tmp_ref(j)
119 pseudo_ob%lat(i) = pseudo_ob%lat(i) + tmp_lat(j)
120 pseudo_ob%lon(i) = pseudo_ob%lon(i) + tmp_lon(j)
121 pseudo_ob%azim(i) = pseudo_ob%azim(i) + tmp_azim(j)
124 pseudo_ob%ref(i) = pseudo_ob%ref(i) / (nstop-nstart+1)
125 pseudo_ob%lat(i) = pseudo_ob%lat(i) / (nstop-nstart+1)
126 pseudo_ob%lon(i) = pseudo_ob%lon(i) / (nstop-nstart+1)
127 pseudo_ob%azim(i) = pseudo_ob%azim(i)/ (nstop-nstart+1)
131 do k = lowest_level+1, kte-1
132 pseudo_ob%ref(k) = exp(pseudo_ob%ref(k))
133 if ( pseudo_ob%lon(k) < 0.0 ) then
134 pseudo_ob%lon(k) = pseudo_ob%lon(k) + 360.0
138 deallocate (log_ref )
140 deallocate (lat_used )
141 deallocate (lon_used )
142 deallocate (azim_used)
144 END SUBROUTINE da_gpseph_create_ob
146 ! ................................................................
148 SUBROUTINE lintp ( n1, x1, y1, n2, x2, y2 )
150 ! **********************************************************
151 ! This subroutine provides linear interpolation of function
152 ! y(x) from one grid x1(i), onto another grid x2(i)
154 ! y1(i), i=1,n1 are input grid function values
155 ! y2(i), i=1,n2 are output grid function values
156 ! **********************************************************
157 ! both x1(i) and x2(i) should increase with 'i'
158 ! **********************************************************
160 integer :: i, j, k, l, m, n
161 integer, intent(in)::n1
162 integer, intent(in)::n2
163 real,dimension(n1),intent(in)::x1
164 real,dimension(n2),intent(in)::x2
165 real,dimension(n1),intent(in)::y1
166 real,dimension(n2),intent(out)::y2
169 if (x2(i).le.x1(1)) then
170 y2(i)=y1(1)+(x2(i)-x1(1))*(y1(2)-y1(1))/(x1(2)-x1(1))
171 else if (x2(i).ge.x1(n1)) then
172 y2(i)=y1(n1)+(x2(i)-x1(n1))*(y1(n1)-y1(n1-1))/(x1(n1)-x1(n1-1))
177 if ((x1(j).le.x2(i)).and.(x1(j+1).ge.x2(i))) goto 1
180 1 y2(i)=y1(k)+(x2(i)-x1(k))*(y1(k+1)-y1(k))/(x1(k+1)-x1(k))