12 use kinds,
only: kind_real
13 use missing_values_mod,
only: missing_value
14 use fckit_log_module,
only: fckit_log
26 nlevp, & ! no. of press. levels
27 nb, & ! no. of theta levels
28 nlevq, & ! no. of q levels
30 za, & ! height of rho levels
31 zb, & ! height of theta levels
32 xb, & ! background vector
34 zobs, & ! ob. impact parameters
35 Bsig, & ! standard dev. of b errors
36 Bm1, & ! Inverse Back. cov matrix
37 Om1, & ! Inverse Ob cov matrix
38 it, & ! no of iterations
39 x, & ! solution vector
40 yb, & ! obs first guess
41 ycalc, & ! obs at solution
42 J_pen, & ! penalty value
43 Amat, & ! solution cov. matrix
44 converged, & ! convergence flag
46 Do1DVar_error, & ! error flag
47 Iter_max, & ! Max number of iterations
50 GPSRO_pseudo_ops, & ! Whether to use pseudo levels
51 GPSRO_vert_interp_ops, & ! Whether to vertically interpolate using exner or ln(p)
52 gpsro_min_temp_grad, &
90 INTEGER,
INTENT(IN) :: nstate
91 INTEGER,
INTENT(IN) :: nlevp
92 INTEGER,
INTENT(IN) :: nb
93 INTEGER,
INTENT(IN) :: nlevq
94 INTEGER,
INTENT(IN) :: nobs
95 INTEGER,
INTENT(IN) :: iter_max
96 REAL(kind_real),
INTENT(IN) :: delta_ct2
97 REAL(kind_real),
INTENT(IN) :: za(:)
98 REAL(kind_real),
INTENT(IN) :: zb(:)
99 REAL(kind_real),
INTENT(IN) :: xb(:)
100 REAL(kind_real),
INTENT(IN) :: yobs(:)
101 REAL(kind_real),
INTENT(IN) :: zobs(:)
102 REAL(kind_real),
INTENT(IN) :: bsig(:)
103 REAL(kind_real),
INTENT(IN) :: bm1(:,:)
104 REAL(kind_real),
INTENT(IN) :: om1(:,:)
105 REAL(kind_real),
INTENT(IN) :: delta
106 LOGICAL,
INTENT(IN) :: gpsro_pseudo_ops
107 LOGICAL,
INTENT(IN) :: gpsro_vert_interp_ops
108 REAL(kind_real),
INTENT(IN) :: gpsro_min_temp_grad
109 LOGICAL,
INTENT(IN) :: capsupersat
110 INTEGER,
INTENT(OUT) :: it
111 REAL(kind_real),
INTENT(OUT) :: x(:)
112 REAL(kind_real),
INTENT(OUT) :: yb(:)
113 REAL(kind_real),
INTENT(OUT) :: ycalc(:)
114 REAL(kind_real),
INTENT(OUT) :: j_pen
115 REAL(kind_real),
INTENT(OUT) :: amat(:,:)
116 LOGICAL,
INTENT(OUT) :: converged
117 LOGICAL,
INTENT(OUT) :: baerr
118 LOGICAL,
INTENT(OUT) :: do1dvar_error
119 REAL(kind_real),
INTENT(OUT) :: o_bdiff
120 REAL(kind_real),
INTENT(IN) :: ro_rad_curv
121 REAL(kind_real),
INTENT(IN) :: latitude
122 REAL(kind_real),
INTENT(IN) :: ro_geoid_und
123 REAL(kind_real),
INTENT(INOUT) :: tb(nlevq)
124 REAL(kind_real),
INTENT(INOUT) :: ts(nlevq)
125 REAL(kind_real),
INTENT(INOUT) :: dfs
128 CHARACTER(len=*),
PARAMETER :: routinename =
"Ops_GPSRO_rootsolv_BA"
129 INTEGER,
PARAMETER :: max_string = 800
135 REAL(kind_real) :: j_old
136 REAL(kind_real) :: j_min
137 REAL(kind_real) :: pen_ob
138 REAL(kind_real) :: pen_back
139 REAL(kind_real) :: xold(nstate)
140 REAL(kind_real) :: x_temp(nstate)
141 REAL(kind_real) :: xmin(nstate)
142 REAL(kind_real) :: ymin(nobs)
143 REAL(kind_real) :: lambda
144 REAL(kind_real) :: lamp1
145 REAL(kind_real) :: d2j_dx2(nstate,nstate)
146 REAL(kind_real) :: dj_dx(nstate)
147 REAL(kind_real) :: diag_d2j(nstate)
148 REAL(kind_real) :: kmat(nobs,nstate)
149 REAL(kind_real) :: dx(nstate)
150 REAL(kind_real) :: conv_test
151 REAL(kind_real) :: ct2
152 REAL(kind_real) :: ct3
153 REAL(kind_real) :: d2
154 REAL(kind_real) :: sdx(nstate)
155 REAL(kind_real) :: ok(nobs,nstate)
156 REAL(kind_real) :: kok(nstate,nstate)
157 REAL(kind_real) :: akok(nstate,nstate)
158 REAL(kind_real),
ALLOCATABLE :: nr(:)
159 REAL(kind_real),
ALLOCATABLE :: dref_dp(:,:)
160 REAL(kind_real),
ALLOCATABLE :: dref_dq(:,:)
161 REAL(kind_real),
ALLOCATABLE :: dnr_dref(:,:)
162 REAL(kind_real),
ALLOCATABLE :: dalpha_dref(:,:)
163 REAL(kind_real),
ALLOCATABLE :: dalpha_dnr(:,:)
164 REAL(kind_real),
ALLOCATABLE :: m1(:,:)
165 REAL(kind_real) :: t(nlevq)
166 REAL(kind_real) :: pressure(1:nlevp)
167 REAL(kind_real) :: humidity(1:nlevq)
169 REAL(kind_real),
ALLOCATABLE :: model_heights(:)
170 REAL(kind_real),
ALLOCATABLE :: refractivity(:)
171 INTEGER :: nreflevels
172 CHARACTER(LEN=max_string) :: message
178 IF (gpsro_pseudo_ops)
THEN
179 ALLOCATE(nr(2 * nlevq - 1))
180 ALLOCATE(dref_dp(2 * nlevq - 1,nlevp))
181 ALLOCATE(dref_dq(2 * nlevq - 1,nlevq))
182 ALLOCATE(dnr_dref(2 * nlevq - 1,2 * nlevq - 1))
183 ALLOCATE(dalpha_dref(nobs,2 * nlevq - 1))
184 ALLOCATE(dalpha_dnr(nobs,2 * nlevq - 1))
185 ALLOCATE(m1(nobs,2 * nlevq - 1))
188 ALLOCATE(dref_dp(nlevq,nlevp))
189 ALLOCATE(dref_dq(nlevq,nlevq))
190 ALLOCATE(dnr_dref(nlevq,nlevq))
191 ALLOCATE(dalpha_dref(nobs,nlevq))
192 ALLOCATE(dalpha_dnr(nobs,nlevq))
193 ALLOCATE(m1(nobs,nlevq))
200 t(:) = missing_value(t(1))
201 tb(:) = missing_value(tb(1))
202 ts(:) = missing_value(ts(1))
203 yb(:) = missing_value(yb(1))
204 ycalc(:) = missing_value(ycalc(1))
209 do1dvar_error = .false.
223 lambda = 1.0e-4_kind_real
228 o_bdiff = missing_value(o_bdiff)
229 dfs = missing_value(dfs)
230 ycalc(:) = missing_value(ycalc(1))
231 ymin(:) = missing_value(ymin(1))
232 errorcode = missing_value(errorcode)
239 CALL fckit_log % info(
'J_pen|Conv_test|ct2|lambda|d2|(dJ/dx)^2|')
243 IF (it > iter_max .OR. &
244 (conv_test < delta .AND. &
245 ct2 < delta_ct2 * (nobs / 200.0_kind_real)))
EXIT
258 pressure = 100 * x(1:nlevp)
259 humidity = 0.001 * x(nlevp+1:nlevp+nlevq)
268 gpsro_vert_interp_ops, &
269 gpsro_min_temp_grad, &
298 IF (it == 1) yb(:) = ycalc(:)
301 IF (it == 1) tb(:) = t(:)
318 IF (it == 1) o_bdiff = 2.0_kind_real * j_pen / real(nobs)
322 IF (j_min > j_pen)
THEN
332 conv_test = abs((j_old - j_pen) / min( j_old, real(nobs, kind=kind_real)))
334 IF (it == 1 .OR. j_pen - j_old < 0.1_kind_real .OR. lambda > 1.0e6_kind_real)
THEN
340 IF (.NOT. marq) lambda = 0.1_kind_real * lambda
356 gpsro_vert_interp_ops, &
357 gpsro_min_temp_grad, &
362 dref_dp(:,:) = 1.0e2 * dref_dp(:,:)
363 dref_dq(:,:) = 1.0e-3 * dref_dq(:,:)
385 m1 = matmul(dalpha_dnr,dnr_dref)
386 kmat(1:nobs,1:nlevp) = matmul(dalpha_dref,dref_dp) + matmul(m1,dref_dp)
387 kmat(1:nobs,nlevp + 1:nstate) = matmul(dalpha_dref,dref_dq) + matmul(m1,dref_dq)
409 amat(:,:) = d2j_dx2(:,:)
417 it_marq = it_marq + 1
418 lambda = 10.0_kind_real * lambda
424 lamp1 = lambda + 1.0_kind_real
428 d2j_dx2(i,i) = diag_d2j(i)
432 d2j_dx2(i,i) = d2j_dx2(i,i) * lamp1
449 IF (errorcode /= 0)
EXIT
454 x(:) = xold(:) + sign(min(abs(dx(:)), 2.0_kind_real * bsig(:), xold(:) / 2.0_kind_real), dx(:))
468 ct2 = dot_product(abs(x(:) - xold(:)), abs(dj_dx(:)))
469 ct3 = dot_product(dj_dx(:), dj_dx(:))
474 sdx(:) = matmul(amat(:,:) , (x(:) - xold(:)))
475 d2 = dot_product((x(:) - xold(:)) , sdx(:))
477 WRITE (message,
'(6E14.6)') j_pen, conv_test, ct2, lambda, d2, ct3
478 CALL fckit_log % info(message)
480 END DO iteration_loop
484 WRITE (message,
'(A,I0)')
'Number of iterations ', it
485 CALL fckit_log % info(message)
486 WRITE (message,
'(A,F16.4)')
'O-B size ', o_bdiff
487 CALL fckit_log % info(message)
491 IF (j_min < j_pen)
THEN
499 IF (it <= iter_max) converged = .true.
503 IF (errorcode == 0 .AND. it <= iter_max)
THEN
512 IF (errorcode /= 0) do1dvar_error = .true.
515 ok = matmul(om1(:,:) , kmat(:,:))
516 kok = matmul(transpose(kmat(:,:)) , ok(:,:))
517 akok = matmul(amat(:,:) , kok(:,:))
521 dfs = dfs + akok(i,i)
524 WRITE (message,
'(A,F16.4)')
'DFS', dfs
525 CALL fckit_log % info(message)
528 do1dvar_error = .true.
532 IF (
ALLOCATED (nr))
DEALLOCATE (nr)
533 IF (
ALLOCATED (dref_dp))
DEALLOCATE (dref_dp)
534 IF (
ALLOCATED (dref_dq))
DEALLOCATE (dref_dq)
535 IF (
ALLOCATED (dnr_dref))
DEALLOCATE (dnr_dref)
536 IF (
ALLOCATED (dalpha_dref))
DEALLOCATE (dalpha_dref)
537 IF (
ALLOCATED (dalpha_dnr))
DEALLOCATE (dalpha_dnr)
538 IF (
ALLOCATED (m1))
DEALLOCATE (m1)
subroutine, public ops_gpsrocalc_nrk(zb, nb, Rad, lat, und, refrac, dnr_dref)
subroutine, public ops_gpsrocalc_alphak(nobs, nlev, a, refrac, nr, Kmat_ref, Kmat_nr)
subroutine, public ops_gpsrocalc_nr(nb, zb, refrac, Rad, lat, und, nr)
subroutine, public ops_gpsrocalc_alpha(nobs, nlev, a, refrac, nr, alpha)
Evaluate the 1st and 2nd deriv. of the cost function.
subroutine, public ops_gpsro_eval_derivs_ba(Nstate, Nobs, x, xb, yobs, ycalc, BM1, OM1, Kmat, dJ_dx, d2J_dx2, diag_d2J)
subroutine, public ops_gpsro_humidcheck(nstate, nlevp, nlevq, za, zb, capsupersat, x)
Calculates GPSRO penalty.
subroutine, public ops_gpsro_pen(Nstate, Nobs, x, xb, yobs, ycalc, BM1, OM1, pen_ob, pen_back, pen_func)
Fortran module for gnssro bending angle Met Office forward operator.
subroutine, public ops_gpsro_rootsolv_ba(nstate, nlevp, nb, nlevq, Nobs, za, zb, xb, yobs, zobs, Bsig, Bm1, Om1, it, x, yb, ycalc, J_pen, Amat, converged, BAerr, Do1DVar_error, Iter_max, Delta, Delta_ct2, GPSRO_pseudo_ops, GPSRO_vert_interp_ops, GPSRO_min_temp_grad, capsupersat, O_Bdiff, RO_Rad_Curv, Latitude, RO_geoid_und, Tb, Ts, DFS)
Fortran module with various useful routines.
subroutine, public ops_cholesky(U, V, N, Q, ErrorCode)
Do cholesky decomposition.
subroutine, public invertmatrix(n, m, a, status, matrix)
Module for containing a general refractivity forward operator and its K-matrix.
subroutine, public ufo_calculate_refractivity(nlevP, nlevq, za, zb, P, q, vert_interp_ops, pseudo_ops, min_temp_grad, refracerr, nRefLevels, refractivity, model_heights, temperature, interp_pressure)
Calculation of the refractivity from the pressure and specific humidity.
subroutine, public ufo_refractivity_kmat(nlevP, nlevq, nRefLevels, za, zb, P, q, pseudo_ops, vert_interp_ops, min_temp_grad, dref_dP, dref_dq, dPb_dP, refractivity)
Calculate general refractivity K matrix.