10 use fckit_log_module,
only: fckit_log
11 use kinds,
only: kind_real
14 use missing_values_mod
55 INTEGER,
INTENT(IN) :: nobs
56 INTEGER,
INTENT(IN) :: nlev
57 REAL(kind_real),
INTENT(IN) :: a(nobs)
58 REAL(kind_real),
INTENT(IN) :: refrac(nlev)
59 REAL(kind_real),
INTENT(IN) :: nr(nlev)
60 REAL(kind_real),
INTENT(OUT) :: alpha(nobs)
63 CHARACTER(len=*),
PARAMETER :: routinename =
"Ops_GPSROcalc_alpha"
69 REAL(kind_real) :: kval(nlev - 1)
70 REAL(kind_real) :: root_2pia
71 REAL(kind_real) :: ref_low
72 REAL(kind_real) :: nr_low
73 REAL(kind_real) :: tup
74 REAL(kind_real) :: tlow
75 REAL(kind_real) :: diff_erf
76 REAL(kind_real) :: dalpha
77 REAL(kind_real) :: erf_tup
78 REAL(kind_real) :: erf_tlow
80 REAL(kind_real),
PARAMETER :: a1 = 0.3480242
81 REAL(kind_real),
PARAMETER :: a2 = -0.0958798
82 REAL(kind_real),
PARAMETER :: a3 = 0.7478556
83 REAL(kind_real),
PARAMETER :: p = 0.47047
89 IF (refrac(jbot) > 0.0 .AND. nr(jbot) > 0.0)
EXIT
101 DO i = nlev,jbot + 1,-1
104 IF ((nr(kbot) - nr(kbot - 1)) < 10.0)
EXIT
110 jbot = max(jbot,kbot)
118 kval(i) = log(refrac(i) / refrac(i + 1)) / &
119 max(1.0,(nr(i + 1) - nr(i)))
120 kval(i) = max(1.0e-6,kval(i))
128 alpha(:) = missing_value(alpha(1))
132 IF (a(n) < nr(jbot) .OR. a(n) > nr(nlev)) cycle
134 root_2pia = sqrt(2.0 * pi * a(n))
143 IF (((nr(ibot + 1) - a(n)) > 1.0) .OR. ibot == nlev - 1)
EXIT
158 DO i = ibot, nlev - 1
162 ref_low = refrac(ibot) * exp(-kval(ibot) * (a(n) - nr(ibot)))
175 IF (i == nlev - 1)
THEN
179 tup = sqrt(kval(i) * (nr(i + 1) + 1.0e5 - a(n)))
183 tup = sqrt(kval(i) * (nr(i + 1) - a(n)))
189 IF (i > ibot) tlow = sqrt(kval(i) * (nr(i) - a(n)))
193 t = 1.0 / (1.0 + p * tup)
194 erf_tup = 1.0 - exp(-(tup ** 2)) * (a1 + (a2 + a3 * t) * t) * t
196 t = 1.0 / (1.0 + p * tlow)
197 erf_tlow = 1.0 - exp(-(tlow ** 2)) * (a1 + (a2 + a3 * t) * t) * t
199 diff_erf = erf_tup - erf_tlow
201 dalpha = 1.0e-6 * root_2pia * sqrt(kval(i)) * &
202 ref_low * exp(kval(i) * (nr_low - a(n))) * diff_erf
206 alpha(n) = alpha(n) + dalpha
220 nb, & ! number of levels in zb
221 Rad, & ! radius of curvature of earth at observation
222 lat, & ! latitude at observation
223 und, & ! geoid undulation above WGS-84
224 refrac, & ! refractivity of model on model levels
230 INTEGER,
INTENT(IN) :: nb
231 REAL(kind_real),
INTENT(IN) :: zb(nb)
232 REAL(kind_real),
INTENT(IN) :: rad
233 REAL(kind_real),
INTENT(IN) :: lat
234 REAL(kind_real),
INTENT(IN) :: und
235 REAL(kind_real),
INTENT(IN) :: refrac(nb)
236 REAL(kind_real),
INTENT(OUT) :: nr(nb)
239 CHARACTER(len=*),
PARAMETER :: routinename =
"Ops_GPSROcalc_nr"
240 REAL(kind_real) :: r(nb)
241 REAL(kind_real) :: z(nb)
244 nr(:) = missing_value(nr(1))
260 IF (zb(i) > 0.0 .AND. refrac(i) > 0.0)
THEN
261 nr(i) = (1.0e0 + 1.0e-6 * refrac(i)) * r(i)
279 REAL(kind_real),
INTENT(IN) :: lat
280 REAL(kind_real),
INTENT(INOUT) :: z(:)
283 CHARACTER(len=*),
PARAMETER :: routinename =
"Ops_GPSRO_geop_geom"
284 REAL(kind_real) :: r_eff
285 REAL(kind_real) :: g_somig
286 REAL(kind_real) :: latrad
292 latrad = lat * (pi / 180.0)
298 r_eff = a_earth / (1.0 + flatt + m_ratio - 2.0 * flatt * (sin(latrad)) ** 2)
300 g_somig = g_equat * (1.0 + k_somig * (sin(latrad)) ** 2) / (sqrt(1.0 - (ecc ** 2) * (sin(latrad)) ** 2))
306 z(:) = (r_eff * z(:)) / ((g_somig / grav) * r_eff - z(:))
326 GPSRO_vert_interp_ops, &
337 INTEGER,
INTENT(IN) :: nstate
338 INTEGER,
INTENT(IN) :: nlevp
339 INTEGER,
INTENT(IN) :: nb
340 INTEGER,
INTENT(IN) :: nlevq
341 REAL(kind_real),
INTENT(IN) :: za(:)
342 REAL(kind_real),
INTENT(IN) :: zb(:)
343 REAL(kind_real),
INTENT(IN) :: x(:)
344 LOGICAL,
INTENT(IN) :: gpsro_pseudo_ops
345 LOGICAL,
INTENT(IN) :: gpsro_vert_interp_ops
346 LOGICAL,
INTENT(OUT) :: refracerr
347 REAL(kind_real),
INTENT(OUT) :: refrac(nb)
348 REAL(kind_real),
INTENT(OUT) :: t(nb)
349 REAL(kind_real),
ALLOCATABLE,
INTENT(OUT),
OPTIONAL :: z_pseudo(:)
350 REAL(kind_real),
ALLOCATABLE,
INTENT(OUT),
OPTIONAL :: n_pseudo(:)
351 INTEGER,
INTENT(OUT),
OPTIONAL :: nb_pseudo
355 CHARACTER(len=*),
PARAMETER :: routinename =
"Ops_GPSRO_refrac"
356 CHARACTER(len=max_string) :: message
359 INTEGER :: search_lev
362 REAL(kind_real) :: p(nlevp)
363 REAL(kind_real) :: exner(nlevp)
364 REAL(kind_real) :: q(nlevq)
365 REAL(kind_real) :: pb(nb)
366 REAL(kind_real) :: tv
367 REAL(kind_real) :: ex_theta
368 REAL(kind_real) :: pwt1
369 REAL(kind_real) :: pwt2
370 REAL(kind_real) :: ndry
371 REAL(kind_real) :: nwet
372 REAL(kind_real),
ALLOCATABLE :: p_pseudo(:)
373 REAL(kind_real),
ALLOCATABLE :: q_pseudo(:)
374 REAL(kind_real),
ALLOCATABLE :: t_pseudo(:)
375 REAL(kind_real) :: gamma
376 REAL(kind_real) :: beta
382 IF (gpsro_pseudo_ops)
THEN
383 nb_pseudo = 2 * nb - 1
384 ALLOCATE (p_pseudo(nb_pseudo))
385 ALLOCATE (q_pseudo(nb_pseudo))
386 ALLOCATE (t_pseudo(nb_pseudo))
387 ALLOCATE (z_pseudo(nb_pseudo))
388 ALLOCATE (n_pseudo(nb_pseudo))
393 q(:) = x(nlevp + 1:nstate)
396 refrac(:) = missing_value(refrac(1))
397 t(:) = missing_value(t(1))
403 IF (p(i) == missing_value(p(i)))
THEN
405 WRITE(message, *) routinename,
"Missing value P", i
406 CALL fckit_log % warning(message)
412 IF (p(i) - p(i + 1) < 0.0)
THEN
415 WRITE(message,*)
"Non monotonic", i, p(i), p(i+1)
416 CALL fckit_log % warning(message)
421 IF (any(p(:) <= 0.0))
THEN
426 IF (any(q(:) < 0.0))
THEN
434 CALL fckit_log%warning (routinename //
": GPSRO Pressure non-monotonic")
435 ELSE IF (unphys)
THEN
436 CALL fckit_log%warning (routinename //
": GPSRO Pressure <= zero")
438 CALL fckit_log%warning (routinename //
": GPSRO Pressure missing")
443 exner(:) = (p(:) / pref) ** rd_over_cp
454 DO this_lev = search_lev, nlevp
455 IF (za(this_lev) > zb(i))
THEN
459 IF (this_lev == 1)
THEN
462 CALL fckit_log%warning (routinename //
": Bottom temperature level is below bottom pressure level! Extrapolating!")
463 CALL fckit_log%warning (routinename //
": Results could be very inaccurate")
466 pwt1 = (za(this_lev) - zb(i)) / (za(this_lev) - za(this_lev-1))
467 search_lev = this_lev
471 IF (gpsro_vert_interp_ops)
THEN
473 pb(i) = exp(pwt1 * log(p(this_lev-1)) + pwt2 * log(p(this_lev)))
476 pb(i) = pref * (pwt1 * (p(this_lev-1) / pref) ** rd_over_cp + pwt2 * &
477 (p(this_lev) / pref) ** rd_over_cp) ** (1.0 / rd_over_cp)
482 ex_theta = (pb(i) / pref) ** rd_over_cp
485 tv = grav * (za(this_lev) - za(this_lev-1)) * ex_theta / &
486 (cp * (exner(this_lev-1) - exner(this_lev)))
498 t(i) = tv / (1.0 + c_virtual * q(i))
502 nwet = n_beta * pb(i) * q(i) / (t(i) ** 2 * (mw_ratio + (1.0 - mw_ratio) * q(i)))
506 ndry = n_alpha * pb(i) / t(i)
508 refrac(i) = ndry + nwet
513 IF (gpsro_pseudo_ops)
THEN
518 IF (mod(i, 2) > 0)
THEN
519 z_pseudo(i) = zb(counter)
520 p_pseudo(i) = pb(counter)
521 q_pseudo(i) = q(counter)
522 t_pseudo(i) = t(counter)
523 counter = counter + 1
527 z_pseudo(i) = (zb(counter - 1) + zb(counter)) / 2.0
530 IF (min(q(counter - 1), q(counter)) > 0.0)
THEN
531 gamma = log(q(counter - 1) / q(counter)) / (zb(counter) - zb(counter - 1))
532 q_pseudo(i) = q(counter - 1) * exp(-gamma * (z_pseudo(i) - z_pseudo(i - 1)))
536 q_pseudo(i) = q(counter - 1) + (q(counter) - q(counter - 1)) / (zb(counter) - &
537 zb(counter - 1)) * (z_pseudo(i) - zb(counter - 1))
541 beta = (t(counter) - t(counter - 1)) / (zb(counter) - zb(counter - 1))
542 t_pseudo(i) = t(counter - 1) + beta * (z_pseudo(i) - zb(counter - 1))
545 IF (abs(t(counter) - t(counter - 1)) > 1.0e-10)
THEN
546 c = ((pb(counter) / pb(counter - 1)) * (t(counter) / t(counter - 1)) ** (grav / (
rd * beta)) - &
547 1.0) / (zb(counter) - zb(counter - 1))
548 p_pseudo(i) = (pb(counter - 1) * (t_pseudo(i) / t(counter - 1)) ** &
549 (-grav / (
rd * beta))) * (1.0 + c * (z_pseudo(i) - zb(counter - 1)))
552 p_pseudo(i) = pb(counter - 1) * exp(log(pb(counter) / pb(counter - 1)) * &
553 ((z_pseudo(i) - zb(counter - 1)) / (zb(counter) - zb(counter - 1))))
558 n_pseudo = n_alpha * p_pseudo / t_pseudo + n_beta * p_pseudo * q_pseudo / &
559 (t_pseudo ** 2 * (mw_ratio + (1.0 - mw_ratio) * q_pseudo))
564 IF (gpsro_pseudo_ops)
THEN
565 IF (
ALLOCATED (p_pseudo))
DEALLOCATE (p_pseudo)
566 IF (
ALLOCATED (q_pseudo))
DEALLOCATE (q_pseudo)
567 IF (
ALLOCATED (t_pseudo))
DEALLOCATE (t_pseudo)