37 class(ufo_gnssro_bndGSI),
intent(in) :: self
38 type(ufo_geovals),
intent(in) :: geovals
39 real(kind_real),
intent(inout) :: hofx(:)
40 type(c_ptr),
value,
intent(in) :: obss
42 character(len=*),
parameter :: myname_ =
"ufo_gnssro_bndgsi_simobs" 43 logical,
parameter :: use_compress = .true.
44 real(kind_real),
parameter :: r1em6 = 1.0e-6_kind_real
45 real(kind_real),
parameter :: r1em3 = 1.0e-3_kind_real
46 real(kind_real),
parameter :: six = 6.0_kind_real
47 real(kind_real),
parameter :: ds = 10000.0_kind_real
48 integer,
parameter :: nlevAdd = 13
49 integer,
parameter :: newAdd = 20
50 integer,
parameter :: ngrd = 80
51 integer,
parameter :: max_string = 800
52 real(kind_real),
parameter :: miss_values = -99999.00
53 real(kind_real),
parameter :: crit_gradRefr = 157.0_kind_real
55 character(max_string) :: err_msg
56 integer :: iobs, ilev, igrd, klev
57 integer :: nlev, nlev1, nobs, nlevExt, nlevCheck
58 real(kind_real) :: rnlevExt
59 real(kind_real) :: w4(4), dw4(4)
61 type(ufo_geoval),
pointer :: t, gphi, prsi, q
62 real(kind_real),
allocatable :: gesT(:,:), gesZi(:,:), gesPi(:,:), gesQ(:,:)
63 real(kind_real),
allocatable :: refr(:,:), radius(:,:)
64 real(kind_real),
allocatable :: refrIndex(:), refrXrad(:), geomzi(:), refrXrad_new(:)
65 real(kind_real),
allocatable :: lagConst(:,:)
66 real(kind_real),
allocatable :: obsLat(:), obsImpP(:), obsLocR(:), obsGeoid(:)
67 real(kind_real) :: specHmean, tmean
68 real(kind_real) :: d_refrXrad
69 real(kind_real) :: derivRefr_s(ngrd),grids(ngrd),refrXrad_s(ngrd)
70 real(kind_real) :: sIndx, sIndxExt
72 real(kind_real) :: bndIntgd, bendingAngle, obsImpH, gradRefr
73 logical :: obs_check, qc_layer_SR
74 integer :: nobs_outIntgl
75 integer :: count_SR, top_layer_SP, top_layer_SR, bot_layer_SR
76 integer :: count_rejection
77 real(kind_real) :: jacob
86 if (geovals%nobs /=
size(hofx))
then 87 write(err_msg,*) myname_,
' error: nobs inconsistent!' 88 call abor1_ftn(err_msg)
93 write(err_msg,*) myname_, trim(
var_prsi),
' doesnt exist' 94 call abor1_ftn(err_msg)
99 write(err_msg,*) myname_, trim(
var_t),
' doesnt exist' 100 call abor1_ftn(err_msg)
105 write(err_msg,*) myname_, trim(
var_q),
' doesnt exist' 106 call abor1_ftn(err_msg)
111 write(err_msg,*) myname_, trim(
var_zi),
' doesnt exist' 112 call abor1_ftn(err_msg)
118 if (nlev1 /= nlev+1)
then 119 write(err_msg,*) myname_,
' Numbers of vertical profiles, nlev1 and nlev, dont match' 120 call abor1_ftn(err_msg)
122 nlevext = nlev + nlevadd
123 nlevcheck =
min(23, nlev)
126 allocate(gespi(nlev1,nobs))
127 allocate(geszi(nlev1,nobs))
128 allocate(gest(nlev,nobs))
129 allocate(gesq(nlev,nobs))
133 gest(ilev,:) = t%vals(nlev-ilev+1,:)
134 gesq(ilev,:) = q%vals(nlev-ilev+1,:)
138 gespi(ilev,:) = prsi%vals(nlev1-ilev+1,:)
139 geszi(ilev,:) = gphi%vals(nlev1-ilev+1,:)
143 grids(igrd+1) = igrd * ds
146 allocate(geomzi(nlev))
147 allocate(radius(nlev,nobs))
149 allocate(refr(nlevext,nobs))
150 allocate(refrindex(nlev))
151 allocate(refrxrad(0:nlevext+1))
152 allocate(lagconst(3,nlevext))
153 allocate(refrxrad_new(nlevext+newadd))
155 allocate(obslat(nobs))
156 allocate(obsimpp(nobs))
157 allocate(obslocr(nobs))
158 allocate(obsgeoid(nobs))
168 obs_loop:
do iobs = 1, nobs
172 call geop2geometric( obslat(iobs), geszi(ilev,iobs), geomzi(ilev), jacob)
175 radius(ilev,iobs) = geomzi(ilev) + obsgeoid(iobs) + obslocr(iobs)
179 spechmean = (gesq(ilev,iobs) + gesq(ilev-1,iobs))/
two 180 tmean = (gest(ilev,iobs) + gest(ilev-1,iobs) )/
two 182 spechmean = gesq(1,iobs)
186 refrindex(ilev) =
one + (r1em6*refr(ilev,iobs))
187 refrxrad(ilev) = refrindex(ilev) * radius(ilev,iobs)
194 if (sindx <
one .or. sindx > float(nlev))
then 195 count_rejection = count_rejection + 1
204 obsimph = (obsimpp(iobs) - obslocr(iobs)) * r1em3
205 if (obsimph <= six)
then 206 do klev=nlevcheck,1,-1
209 gradrefr = 1000.0_kind_real * (refr(klev+1,iobs)-refr(klev,iobs)) / (radius(klev+1,iobs)-radius(klev,iobs))
211 if (abs(gradrefr)>=
half*crit_gradrefr)
then 216 if (abs(gradrefr) >= 0.75_kind_real*crit_gradrefr)
then 219 if (count_sr > 1 )
then 224 bot_layer_sr=top_layer_sr
229 if (top_layer_sr >= 1 .and. obsimpp(iobs) <= refrxrad(top_layer_sr+2))
then 230 count_rejection = count_rejection + 1
237 d_refrxrad = refrxrad(nlev) - refrxrad(nlev-1)
239 refrxrad(nlev+ilev)=refrxrad(nlev)+ ilev*d_refrxrad
240 refr(nlev+ilev,iobs)=refr(nlev+ilev-1,iobs)**2/refr(nlev+ilev-2,iobs)
243 refrxrad(0)=refrxrad(3)
244 refrxrad(nlevext+1)=refrxrad(nlevext-2)
253 grids_loop:
do igrd =1,ngrd
255 refrxrad_s(igrd)=sqrt(grids(igrd)**2 + obsimpp(iobs)**2)
259 rnlevext = float(nlevext)
261 if (sindx < rnlevext)
then 267 lagconst(:,indx),lagconst(:,indx+1),&
270 w4(4)=w4(4)+w4(1); w4(1:3)=w4(2:4);w4(4)=
zero 271 dw4(4)=dw4(4)+dw4(1);dw4(1:3)=dw4(2:4);dw4(4)=
zero 274 if(indx==nlevext-1)
then 275 w4(1)=w4(1)+w4(4); w4(2:4)=w4(1:3);w4(1)=
zero 276 dw4(1)=dw4(1)+dw4(4); dw4(2:4)=dw4(1:3);dw4(1)=
zero 280 derivrefr_s(igrd)=dot_product(dw4,refr(indx-1:indx+2,iobs))
281 derivrefr_s(igrd)=
max(
zero,abs(derivrefr_s(igrd)))
285 nobs_outintgl=nobs_outintgl+1
286 d_refrxrad=refrxrad(nlev)-refrxrad(nlev-1)
288 refrxrad_new(nlevext+klev)=refrxrad(nlevext)+ klev*d_refrxrad
291 refrxrad_new(klev)=refrxrad(klev)
293 call get_coordinate_value(refrxrad_s(igrd), sindx,refrxrad_new(1:nlevext+newadd),nlevext+newadd,
"increasing")
294 sindxext=
max(sindx,sindxext)
299 bendingangle = ds*derivrefr_s(1)/refrxrad_s(1)
301 bndintgd = ds*derivrefr_s(igrd)/refrxrad_s(igrd)
302 bendingangle = bendingangle +
two*bndintgd
304 bendingangle=r1em6 * obsimpp(iobs) * bendingangle
305 hofx(iobs) = bendingangle
309 write(6,*)
'bndGSI: hofx ', &
310 'min = ', minval(hofx, mask=hofx > miss_values),
'min index = ', minloc(hofx), &
311 'max = ', maxval(hofx, mask=hofx > miss_values),
'max index = ', maxloc(hofx)
312 write(6,*)
'bndGSI: ', count_rejection,
' out of ', nobs,
' rejected due to model vertical range and super refraction' 315 if (nobs_outintgl>=1)
then 316 write(6,*)
'bndGSI: Warning',nobs_outintgl,
'obs outside integration grid. Increase nlevExt to',&
330 deallocate(refrindex)
335 deallocate(refrxrad_new)
subroutine, public ufo_geovals_get_var(self, varname, geoval, status)
real(fp), parameter, public zero
character(len=maxvarlen), public var_prsi
subroutine, public lag_interp_smthweights(x, xt, aq, bq, w, dw, n)
real(kind_real), parameter, public half
subroutine, public get_coordinate_value(fin, fout, x, nx, flag)
Fortran module to prepare for Lagrange polynomial interpolation. based on GSI: lagmod.f90.
Fortran module to perform linear interpolation.
real(fp), parameter, public one
character(len=maxvarlen), public var_q
real(fp), parameter, public two
subroutine ufo_gnssro_bndgsi_simobs(self, geovals, hofx, obss)
type(registry_t), public ufo_geovals_registry
Linked list interface - defines registry_t type.
subroutine, public lag_interp_const(q, x, n)
Fortran module to handle gnssro bending angle observations following the NCEP/GSI (2018 Aug) implemen...
character(len=maxvarlen), public var_zi
character(len=maxvarlen), public var_t
Fortran interface to ObsSpace.
Fortran derived type for gnssro trajectory.