20 use missing_values_mod
21 use fckit_log_module,
only : fckit_log
30 logical :: vert_interp_ops
32 integer :: nlevp, nlevq, nlocs, iflip
33 real(kind_real),
allocatable :: k(:,:)
50 use fckit_configuration_module,
only: fckit_configuration
53 type(fckit_configuration),
intent(in) :: f_conf
55 call f_conf%get_or_die(
"vert_interp_ops", self % vert_interp_ops)
56 call f_conf%get_or_die(
"pseudo_ops", self % pseudo_ops)
71 type(c_ptr),
value,
intent(in) :: obss
74 character(len=*),
parameter :: myname_=
"ufo_gnssro_bendmetoffice_tlad_settraj"
77 character(max_string) :: err_msg
85 real(kind_real),
allocatable :: obsLat(:)
86 real(kind_real),
allocatable :: impact_param(:)
87 real(kind_real),
allocatable :: obsLocR(:)
88 real(kind_real),
allocatable :: obsGeoid(:)
90 write(err_msg,*)
"TRACE: ufo_gnssro_bendmetoffice_tlad_settraj: begin"
91 call fckit_log%info(err_msg)
103 self % nlevp = prs % nval
104 self % nlevq = q % nval
105 self % nlocs = obsspace_get_nlocs(obss)
109 if (prs%vals(1,1) .lt. prs%vals(prs%nval,1) )
then
111 write(err_msg,
'(a)')
' ufo_gnssro_bendmetoffice_tlad_settraj:'//new_line(
'a')// &
112 ' Model vertical height profile is in descending order,'//new_line(
'a')// &
113 ' The data will be flipped for processing'
114 call fckit_log%info(err_msg)
118 allocate(obslat(self%nlocs))
119 allocate(impact_param(self%nlocs))
120 allocate(obslocr(self%nlocs))
121 allocate(obsgeoid(self%nlocs))
122 call obsspace_get_db(obss,
"MetaData",
"latitude", obslat)
123 call obsspace_get_db(obss,
"MetaData",
"impact_parameter", impact_param)
124 call obsspace_get_db(obss,
"MetaData",
"earth_radius_of_curvature", obslocr)
125 call obsspace_get_db(obss,
"MetaData",
"geoid_height_above_reference_ellipsoid", obsgeoid)
126 nstate = prs % nval + q % nval
127 ALLOCATE(self % K(1:self%nlocs, 1:nstate))
130 obs_loop:
do iobs = 1, self % nlocs
131 if (self%iflip == 1)
then
134 rho_heights % vals(rho_heights%nval:1:-1, iobs), &
135 theta_heights % vals(theta_heights%nval:1:-1, iobs), &
136 q % vals(q%nval:1:-1, iobs), &
137 prs % vals(prs%nval:1:-1, iobs), &
139 self % vert_interp_ops, &
144 impact_param(iobs:iobs), &
145 self % K(iobs:iobs,1:nstate))
149 rho_heights % vals(:,iobs), &
150 theta_heights % vals(:,iobs), &
152 prs % vals(:,iobs), &
154 self % vert_interp_ops, &
159 impact_param(iobs:iobs), &
160 self % K(iobs:iobs,1:nstate))
168 deallocate(impact_param)
185 real(kind_real),
intent(inout) :: hofx(:)
186 type(c_ptr),
value,
intent(in) :: obss
189 character(len=*),
parameter :: myname_=
"ufo_gnssro_bendmetoffice_simobs_tl"
194 character(max_string) :: err_msg
197 real(kind_real),
allocatable :: x_d(:)
199 write(err_msg,*)
"TRACE: ufo_gnssro_bendmetoffice_simobs_tl: begin"
200 call fckit_log%info(err_msg)
203 if (.not. self%ltraj)
then
204 write(err_msg,*) myname_,
' trajectory wasnt set!'
205 call abor1_ftn(err_msg)
209 if (geovals%nlocs /=
size(hofx))
then
210 write(err_msg,*) myname_,
' error: nlocs inconsistent!'
211 call abor1_ftn(err_msg)
220 allocate(x_d(1:prs_d%nval+q_d%nval))
222 obs_loop:
do iobs = 1, nlocs
224 x_d(1:prs_d%nval) = prs_d % vals(:,iobs)
225 x_d(prs_d%nval+1:prs_d%nval+q_d%nval) = q_d % vals(:,iobs)
226 hofx(iobs) = sum(self % K(iobs,:) * x_d)
232 write(err_msg,*)
"TRACE: ufo_gnssro_bendmetoffice_simobs_tl: complete"
233 call fckit_log%info(err_msg)
245 use typesizes,
only: wp => eightbytereal
252 real(kind_real),
intent(in) :: hofx(:)
253 type(c_ptr),
value,
intent(in) :: obss
256 character(len=*),
parameter :: myname_=
"ufo_gnssro_bendmetoffice_simobs_ad"
259 real(c_double) :: missing
263 real(kind_real),
allocatable :: x_d(:)
264 character(max_string) :: err_msg
266 write(err_msg,*)
"TRACE: ufo_gnssro_bendmetoffice_simobs_ad: begin"
267 call fckit_log%info(err_msg)
270 if (.not. self%ltraj)
then
271 write(err_msg,*) myname_,
' trajectory wasnt set!'
272 call abor1_ftn(err_msg)
276 if (geovals%nlocs /=
size(hofx))
then
277 write(err_msg,*) myname_,
' error: nlocs inconsistent!'
278 call abor1_ftn(err_msg)
286 if (.not.
allocated(prs_d%vals))
then
287 prs_d % nlocs = self % nlocs
288 prs_d % nval = self % nlevp
289 allocate(prs_d%vals(prs_d%nval, prs_d%nlocs))
290 prs_d % vals = 0.0_kind_real
294 if (.not.
allocated(q_d%vals))
then
295 q_d % nlocs = self % nlocs
296 q_d % nval = self % nlevq
297 allocate(q_d%vals(q_d%nval, q_d%nlocs))
298 q_d % vals = 0.0_kind_real
301 missing = missing_value(missing)
302 allocate(x_d(1:prs_d%nval + q_d%nval))
305 obs_loop:
do iobs = 1, self % nlocs
307 if (hofx(iobs) /= missing)
then
308 x_d = self % K(iobs,:) * hofx(iobs)
309 prs_d % vals(:,iobs) = x_d(1:prs_d%nval)
310 q_d % vals(:,iobs) = x_d(prs_d%nval+1:prs_d%nval+q_d%nval)
317 write(err_msg,*)
"TRACE: ufo_gnssro_bendmetoffice_simobs_ad: complete"
318 call fckit_log%info(err_msg)
331 character(len=*),
parameter :: myname_=
"ufo_gnssro_bendmetoffice_tlad_delete"
336 if (
allocated(self%K))
deallocate(self%K)
361 INTEGER,
INTENT(IN) :: nlevP
362 INTEGER,
INTENT(IN) :: nlevq
363 REAL(kind_real),
INTENT(IN) :: za(:)
364 REAL(kind_real),
INTENT(IN) :: zb(:)
365 REAL(kind_real),
INTENT(IN) :: q(1:nlevq)
366 REAL(kind_real),
INTENT(IN) :: prs(1:nlevp)
367 LOGICAL,
INTENT(IN) :: pseudo_ops
368 LOGICAL,
INTENT(IN) :: vert_interp_ops
369 REAL(kind_real),
INTENT(IN) :: ro_rad_curv
370 REAL(kind_real),
INTENT(IN) :: latitude
371 REAL(kind_real),
INTENT(IN) :: ro_geoid_und
372 INTEGER,
INTENT(IN) :: nobs
373 REAL(kind_real),
INTENT(IN) :: zobs(:)
374 REAL(kind_real),
INTENT(INOUT) :: K(:,:)
378 REAL(kind_real),
ALLOCATABLE :: z_pseudo(:)
379 REAL(kind_real),
ALLOCATABLE :: N_pseudo(:)
381 REAL(kind_real) :: T(1:nlevq)
382 REAL(kind_real),
ALLOCATABLE :: nr(:)
383 REAL(kind_real) :: ref_model(1:nlevq)
388 INTEGER :: num_pseudo
390 REAL(kind_real) :: x(1:nlevP+nlevQ)
392 CHARACTER(LEN=200) :: err_msg
395 nstate = nlevp + nlevq
398 x(nlevp+1:nstate) = q
403 num_pseudo = 2 * nlevq - 1
407 ALLOCATE(nr(1:num_pseudo))
428 IF (.NOT. baerr)
THEN
471 write(err_msg,*)
"Error in refractivity calculation"
472 CALL fckit_log % warning(err_msg)
476 IF (
ALLOCATED(z_pseudo))
DEALLOCATE(z_pseudo)
477 IF (
ALLOCATED(n_pseudo))
DEALLOCATE(n_pseudo)
508 INTEGER,
INTENT(IN) :: nstate
509 INTEGER,
INTENT(IN) :: nlevP
510 INTEGER,
INTENT(IN) :: nb
511 INTEGER,
INTENT(IN) :: nlevq
512 REAL(kind_real),
INTENT(IN) :: za(:)
513 REAL(kind_real),
INTENT(IN) :: zb(:)
514 REAL(kind_real),
INTENT(IN) :: zb_pseudo(:)
515 LOGICAL,
INTENT(IN) :: pseudo_ops
516 LOGICAL,
INTENT(IN) :: vert_interp_ops
517 REAL(kind_real),
INTENT(IN) :: x(:)
518 REAL(kind_real),
INTENT(IN) :: ro_rad_curv
519 REAL(kind_real),
INTENT(IN) :: latitude
520 REAL(kind_real),
INTENT(IN) :: ro_geoid_und
521 REAL(kind_real),
INTENT(IN) :: ref_model(nb)
522 INTEGER,
INTENT(IN) :: nobs
523 REAL(kind_real),
INTENT(IN) :: zobs(:)
524 REAL(kind_real),
INTENT(IN) :: nr(nb)
525 REAL(kind_real),
INTENT(OUT) :: K(nobs,nstate)
527 REAL(kind_real) :: m1(nobs, nb)
528 REAL(kind_real),
ALLOCATABLE :: dref_dp(:, :)
529 REAL(kind_real),
ALLOCATABLE :: dref_dq(:, :)
530 REAL(kind_real) :: dnr_dref(nb, nb)
531 REAL(kind_real) :: dalpha_dref(nobs, nb)
532 REAL(kind_real) :: dalpha_dnr(nobs, nb)
577 m1 = matmul(dalpha_dnr,dnr_dref)
578 k(1:nobs, 1:nlevp) = matmul(dalpha_dref,dref_dp) + matmul(m1,dref_dp)
579 k(1:nobs, nlevp + 1:nstate) = matmul(dalpha_dref,dref_dq) + matmul(m1,dref_dq)
581 IF (
ALLOCATED(dref_dp))
DEALLOCATE(dref_dp)
582 IF (
ALLOCATED(dref_dq))
DEALLOCATE(dref_dq)