11 use fckit_log_module,
only : fckit_log
97 real(kind_real),
intent(in) :: b_matrix(:,:)
98 real(kind_real),
intent(in) :: b_inv(:,:)
99 real(kind_real),
intent(in) :: b_sigma(:)
104 logical,
intent(out) :: onedvar_success
107 character(len=*),
parameter :: routinename =
"ufo_rttovonedvarcheck_minimize_newton"
108 integer :: inversionstatus
109 logical :: outofrange
113 integer :: rterrorcode
115 integer :: nprofelements
116 real(kind_real) :: jcost
117 real(kind_real) :: jcostold
118 real(kind_real) :: jcostorig
119 real(kind_real) :: deltaj
120 real(kind_real) :: deltajo
122 real(kind_real),
allocatable :: oldprofile(:)
123 real(kind_real),
allocatable :: guessprofile(:)
124 real(kind_real),
allocatable :: backprofile(:)
125 real(kind_real),
allocatable :: h_matrix(:,:)
126 real(kind_real),
allocatable :: diffprofile(:)
127 real(kind_real),
allocatable :: absdiffprofile(:)
128 real(kind_real),
allocatable :: xdiff(:)
129 real(kind_real),
allocatable :: ydiff(:)
130 real(kind_real),
allocatable :: y(:)
131 real(kind_real),
allocatable :: y0(:)
132 real(kind_real),
allocatable :: out_h_matrix(:,:)
133 real(kind_real),
allocatable :: out_y(:)
135 real(kind_real) :: jout(3)
143 onedvar_success = .false.
145 nchans =
size(ob % channels_used)
147 nprofelements = profile_index % nprofelements
148 allocate(oldprofile(nprofelements))
149 allocate(guessprofile(nprofelements))
150 allocate(backprofile(nprofelements))
151 allocate(h_matrix(nchans,nprofelements))
152 allocate(diffprofile(nprofelements))
153 allocate(absdiffprofile(nprofelements))
154 allocate(xdiff(nprofelements))
155 allocate(ydiff(nchans))
158 geovals = local_geovals
161 call fckit_log % debug(
"Using Newton solver")
163 jcost = 1.0e4_kind_real
165 iterations:
do iter = 1, self % max1DVarIterations
171 if (self % UseJForConvergence)
then
179 diffprofile(:) =
zero
180 jcostold = 1.0e4_kind_real
186 if (self % FullDiagnostics) &
187 write(*,*)
"Humidity GuessProfile 1st iteration = ",guessprofile(profile_index % qt(1):profile_index % qt(2))
192 oldprofile(:) = guessprofile(:)
196 profile_index, guessprofile(:), &
197 hofxdiags, rttov_simobs, y(:), h_matrix)
200 backprofile(:) = guessprofile(:)
202 do ii = 1,
size(ob % channels_all)
203 do jj = 1,
size(ob % channels_used)
204 if (ob % channels_all(ii) == ob % channels_used(jj))
then
205 ob % background_BT(ii) = y0(jj)
212 if (rterrorcode /= 0)
then
213 write(*,*)
"Radiative transfer error"
224 xdiff(:) = guessprofile(:) - backprofile(:)
225 ydiff(:) = ob % yobs(:) - y(:)
227 if (self % FullDiagnostics)
then
228 write(*,*)
"Ob BT = "
229 write(*,
'(10F10.3)') ob % yobs(:)
230 write(*,*)
"HofX BT = "
231 write(*,
'(10F10.3)') y(:)
234 if (self % UseJForConvergence)
then
240 if (inversionstatus /= 0)
exit iterations
243 if (iter == 1) jcostorig = jcost
248 if (self % JConvergenceOption == 1)
then
251 deltaj = abs((jcost - jcostold) / max(jcost, tiny(
zero)))
254 deltajo = -1.0_kind_real
259 deltaj = abs(jcost - jcostold)
262 deltajo = jcost - jcostorig
266 if (self % FullDiagnostics)
THEN
267 write (*,
'(A,F12.5)')
'Cost Function = ', jcost
268 write (*,
'(A,F12.5)')
'Cost Function old = ', jcostold
269 write (*,
'(A,F12.5)')
'Cost Function Increment = ', deltaj
272 if (deltaj < self % cost_convergencefactor .and. &
275 if (self % FullDiagnostics)
then
276 write (*,
'(A,I0)')
'Iteration', iter
277 write (*,
'(A)')
'------------'
278 write (*,
'(A,L1)')
'Status: converged = ', converged
279 write (*,
'(A)')
'New profile:'
282 write (*,
'(A,3F12.5)')
'Cost Function, increment, cost_convergencefactor = ', &
283 jcost, deltaj, self % cost_convergencefactor
293 if (nchans > nprofelements)
then
294 call fckit_log % debug(
"Many Chans")
298 transpose(h_matrix(:,:)), &
305 call fckit_log % debug(
"Few Chans")
309 transpose(h_matrix(:,:)), &
316 if (self % FullDiagnostics)
then
317 write(*,*)
"After newton fewchans start"
319 ob % channels_used, guessprofile, &
320 backprofile, diffprofile, b_inv, h_matrix )
321 write(*,*)
"After newton fewchans finish"
326 if (inversionstatus /= 0)
then
328 write(*,*)
"inversion failed"
332 guessprofile(:) = backprofile(:) + diffprofile(:)
347 ob, guessprofile, self % UseQtSplitRain)
352 if ((.NOT. outofrange) .and. profile_index % qt(1) > 0)
then
354 if (iter >= self % IterNumForLWPCheck)
then
370 absdiffprofile(:) =
zero
372 if ((.NOT. outofrange) .and. (.NOT. self % UseJForConvergence))
then
373 absdiffprofile(:) = abs(guessprofile(:) - oldprofile(:))
374 if (all(absdiffprofile(:) <= b_sigma(:) * self % ConvergenceFactor))
then
375 call fckit_log % debug(
"Profile used for convergence")
384 if (self % FullDiagnostics)
then
385 write (*,
'(A,I0)')
'Iteration', iter
386 write (*,
'(A)')
'------------'
387 write (*,
'(A,L1)')
'Status: converged = ', converged
388 if (outofrange)
write (*,
'(A)')
'exiting with bad increments'
389 write (*,
'(A)')
'New profile:'
396 if (converged .OR. outofrange)
exit iterations
401 onedvar_success = converged
405 ob % final_cost = jout(1)
407 ob % final_bt_diff = ydiff
411 ob % output_profile(:) = guessprofile(:)
414 if (self % Store1DVarLWP)
then
423 allocate(out_h_matrix(
size(ob % channels_all),nprofelements))
424 allocate(out_y(
size(ob % channels_all)))
426 profile_index, guessprofile(:), &
427 hofxdiags, rttov_simobs, out_y(:), out_h_matrix)
428 ob % output_BT(:) = out_y(:)
430 deallocate(out_h_matrix)
437 if (self % UseJForConvergence .and. self % FullDiagnostics)
then
438 write(*,
'(A70,3F10.3,I5,2L5)')
"Newton J initial, final, lowest, iter, converged, outofrange = ", &
439 jcostorig, jcost, jcost, iter, onedvar_success, outofrange
445 if (
allocated(oldprofile))
deallocate(oldprofile)
446 if (
allocated(guessprofile))
deallocate(guessprofile)
447 if (
allocated(backprofile))
deallocate(backprofile)
448 if (
allocated(h_matrix))
deallocate(h_matrix)
449 if (
allocated(diffprofile))
deallocate(diffprofile)
450 if (
allocated(absdiffprofile))
deallocate(absdiffprofile)
451 if (
allocated(xdiff))
deallocate(xdiff)
452 if (
allocated(ydiff))
deallocate(ydiff)
453 if (
allocated(y))
deallocate(y)
454 if (
allocated(y0))
deallocate(y0)
456 call fckit_log % debug(
"finished with ufo_rttovonedvarcheck_minimize_newton")
522 real(kind_real),
intent(in) :: DeltaBT(:)
523 integer,
intent(in) :: nChans
524 real(kind_real),
intent(in) :: H_Matrix(:,:)
525 real(kind_real),
intent(in) :: H_Matrix_T(:,:)
526 integer,
intent(in) :: nprofelements
527 real(kind_real),
intent(inout) :: DeltaProfile(:)
528 real(kind_real),
intent(in) :: B_matrix(:,:)
530 integer,
intent(out) :: Status
533 character(len=*),
parameter :: RoutineName =
"ufo_rttovonedvarcheck_NewtonFewChans"
536 real(kind_real) :: HB(nChans,nprofelements)
537 real(kind_real) :: Q(nChans)
538 real(kind_real) :: U(nChans,nChans)
539 real(kind_real) :: V(nChans)
547 hb = matmul(h_matrix, b_matrix)
548 u = matmul(hb, h_matrix_t)
553 v = deltabt + matmul(h_matrix, deltaprofile)
559 call r_matrix % add_to_matrix(u, u)
569 if (status /= 0)
goto 9999
574 deltaprofile = matmul(transpose(hb), q)
637 real(kind_real),
intent(in) :: DeltaBT(:)
638 integer,
intent(in) :: nChans
639 real(kind_real),
intent(in) :: H_Matrix(:,:)
640 real(kind_real),
intent(in) :: H_Matrix_T(:,:)
641 integer,
intent(in) :: nprofelements
642 real(kind_real),
intent(inout) :: DeltaProfile(:)
643 real(kind_real),
intent(in) :: B_inverse(:,:)
645 integer,
intent(out) :: Status
648 character(len=*),
parameter :: RoutineName =
'ufo_rttovonedvarcheck_NewtonManyChans'
649 real(kind_real) :: HTR(nprofelements, nChans)
650 real(kind_real) :: U(nprofelements, nprofelements)
651 real(kind_real) :: V(nprofelements)
661 call r_matrix % multiply_inverse_matrix(h_matrix_t,htr)
667 u = matmul(htr, h_matrix)
668 v = matmul(htr, deltabt)
669 v = v + matmul(u, deltaprofile)
real(kind_real), parameter, public zero
subroutine, public ufo_geovals_print(self, iobs)
Fortran module for radiancerttov observation operator.
Fortran module constants used throughout the rttovonedvarcheck filter.
Fortran module to get the jacobian for the 1D-Var.
subroutine, public ufo_rttovonedvarcheck_get_jacobian(self, geovals, ob, channels, profindex, prof_x, hofxdiags, rttov_simobs, hofx, H_matrix)
Get the jacobian used in the 1D-Var.
Fortran module to perform newton steepest descent minimization.
subroutine ufo_rttovonedvarcheck_newtonfewchans(DeltaBT, nChans, H_Matrix, H_Matrix_T, nprofelements, DeltaProfile, B_matrix, r_matrix, Status)
Update the profile if newber of channels is less than number of elements in the profile.
subroutine, public ufo_rttovonedvarcheck_minimize_newton(self, ob, r_matrix, b_matrix, b_inv, b_sigma, local_geovals, hofxdiags, rttov_simobs, profile_index, onedvar_success)
Get the jacobian used in the 1D-Var.
subroutine ufo_rttovonedvarcheck_newtonmanychans(DeltaBT, nChans, H_Matrix, H_Matrix_T, nprofelements, DeltaProfile, B_inverse, r_matrix, Status)
Update the profile if number of channels is more than number of elements in the profile.
Fortran module containing subroutines used by both minimizers.
subroutine, public ufo_rttovonedvarcheck_geovals2profvec(geovals, profindex, ob, prof_x)
Copy geovals data (and ob) to profile.
subroutine, public ufo_rttovonedvarcheck_checkiteration(self, geovals, profindex, profile, OutOfRange)
Constrain profile humidity and check temperature values are okay.
subroutine, public ufo_rttovonedvarcheck_profvec2geovals(geovals, profindex, ob, prof_x, UseQtsplitRain)
Copy profile data to geovals (and ob).
subroutine, public ufo_rttovonedvarcheck_printiterinfo(yob, hofx, channels, guessprofile, backprofile, diffprofile, binv, hmatrix)
Print detailed information for each iteration for diagnostics.
subroutine, public ufo_rttovonedvarcheck_checkcloudyiteration(geovals, profindex, nlevels_1dvar, OutOfRange, OutLWP)
Check cloud during iteration.
subroutine, public ufo_rttovonedvarcheck_costfunction(DeltaProf, b_inv, DeltaObs, r_matrix, Jcost)
Calculate the cost function.
Fortran module which contains the observation metadata for a single observation.
Fortran module containing profile index.
Fortran derived type to hold data for the observation covariance.
Fortran module containing main type, setup and utilities for the main rttovonedvarcheck object.
Fortran module with various useful routines.
subroutine, public ops_cholesky(U, V, N, Q, ErrorCode)
Do cholesky decomposition.
type to hold interpolated fields required by the obs operators
Fortran derived type for the observation type.