12 use fckit_log_module,
only : fckit_log
99 real(kind_real),
intent(in) :: b_matrix(:,:)
100 real(kind_real),
intent(in) :: b_inv(:,:)
101 real(kind_real),
intent(in) :: b_sigma(:)
106 logical,
intent(out) :: onedvar_success
109 character(len=*),
parameter :: routinename =
"ufo_rttovonedvarcheck_minimize_ml"
110 integer :: inversionstatus
111 logical :: outofrange
115 integer :: rterrorcode
118 integer :: nprofelements
119 real(kind_real) :: gamma
120 real(kind_real) :: jcost
121 real(kind_real) :: jcostold
122 real(kind_real) :: jcostorig
123 real(kind_real) :: deltaj
124 real(kind_real) :: deltajo
126 real(kind_real),
allocatable :: oldprofile(:)
127 real(kind_real),
allocatable :: guessprofile(:)
128 real(kind_real),
allocatable :: guessprofilebefore(:)
129 real(kind_real),
allocatable :: backprofile(:)
130 real(kind_real),
allocatable :: h_matrix(:,:)
131 real(kind_real),
allocatable :: diffprofile(:)
132 real(kind_real),
allocatable :: absdiffprofile(:)
133 real(kind_real),
allocatable :: ydiff(:)
134 real(kind_real),
allocatable :: y(:)
135 real(kind_real),
allocatable :: y0(:)
136 real(kind_real),
allocatable :: out_h_matrix(:,:)
137 real(kind_real),
allocatable :: out_y(:)
138 real(kind_real) :: jout(3)
146 onedvar_success = .false.
148 nchans =
size(ob % channels_used)
149 gamma = 1.0e-4_kind_real
150 jcost = 1.0e4_kind_real
151 jcostold = 1.0e4_kind_real
152 nprofelements = profile_index % nprofelements
153 allocate(oldprofile(nprofelements))
154 allocate(guessprofile(nprofelements))
155 allocate(guessprofilebefore(nprofelements))
156 allocate(backprofile(nprofelements))
157 allocate(h_matrix(nchans,nprofelements))
158 allocate(diffprofile(nprofelements))
159 allocate(absdiffprofile(nprofelements))
160 allocate(ydiff(nchans))
163 geovals = local_geovals
165 call fckit_log % debug(
"Using ML solver")
170 iterations:
do iter = 1, self % max1DVarIterations
177 oldprofile(:) = guessprofile(:)
181 profile_index, guessprofile(:), &
182 hofxdiags, rttov_simobs, y(:), h_matrix)
186 diffprofile(:) =
zero
187 backprofile(:) = guessprofile(:)
192 if (rterrorcode /= 0)
then
193 write(*,*)
"Radiative transfer error"
198 ydiff(:) = ob % yobs(:) - y(:)
200 diffprofile(:) = guessprofile(:) - backprofile(:)
212 if (self % UseJForConvergence)
then
220 if (self % JConvergenceOption == 1)
then
223 deltaj = abs((jcost - jcostold) / max(jcost, tiny(
zero)))
226 deltajo = -1.0_kind_real
231 deltaj = abs(jcost - jcostold)
234 deltajo = jcost - jcostorig
238 if (deltaj < self % cost_convergencefactor .and. &
257 transpose(h_matrix), &
272 if (inversionstatus /= 0)
then
274 write(*,*)
"inversion failed"
291 guessprofile, self % UseQtSplitRain)
296 if ((.not. outofrange) .and. profile_index % qt(1) > 0)
then
298 if (iter >= self % IterNumForLWPCheck)
then
314 absdiffprofile(:) =
zero
316 if ((.not. outofrange) .and. (.not. self % UseJForConvergence))
then
317 absdiffprofile(:) = abs(guessprofile(:) - oldprofile(:))
318 if (all(absdiffprofile(:) <= b_sigma(:) * self % ConvergenceFactor))
then
319 write(*,*)
"Profile used for convergence"
328 if (self % FullDiagnostics)
then
329 write (*,
'(A,I0)')
'Iteration', iter
330 write (*,
'(A)')
'------------'
331 write (*,
'(A,L1)')
'Status: converged = ', converged
332 if (outofrange)
write (*,
'(A)')
'exiting with bad increments'
333 write (*,
'(A)')
'New profile:'
340 if (converged .OR. outofrange)
exit iterations
345 onedvar_success = converged
349 ob % final_cost = jout(1)
351 ob % final_bt_diff = ydiff
355 ob % output_profile(:) = guessprofile(:)
358 if (self % Store1DVarLWP)
then
367 allocate(out_h_matrix(
size(ob % channels_all),nprofelements))
368 allocate(out_y(
size(ob % channels_all)))
370 profile_index, guessprofile(:), &
371 hofxdiags, rttov_simobs, out_y(:), out_h_matrix)
372 ob % output_BT(:) = out_y(:)
374 deallocate(out_h_matrix)
381 if (self % UseJForConvergence .and. self % FullDiagnostics)
then
382 write(*,
'(A45,3F10.3,I5,L5)')
"ML J initial, final, lowest, iter, converged = ", &
383 jcostorig, jcost, jcost, iter, onedvar_success
389 if (
allocated(oldprofile))
deallocate(oldprofile)
390 if (
allocated(guessprofile))
deallocate(guessprofile)
391 if (
allocated(guessprofilebefore))
deallocate(guessprofilebefore)
392 if (
allocated(backprofile))
deallocate(backprofile)
393 if (
allocated(h_matrix))
deallocate(h_matrix)
394 if (
allocated(diffprofile))
deallocate(diffprofile)
395 if (
allocated(absdiffprofile))
deallocate(absdiffprofile)
396 if (
allocated(ydiff))
deallocate(ydiff)
397 if (
allocated(y))
deallocate(y)
398 if (
allocated(y0))
deallocate(y0)
476 real(kind_real),
intent(in) :: DeltaBT(:)
477 integer,
intent(in) :: nChans
479 real(kind_real),
intent(in) :: H_Matrix(:,:)
480 real(kind_real),
intent(in) :: H_Matrix_T(:,:)
481 integer,
intent(in) :: nprofelements
483 real(kind_real),
intent(inout) :: DeltaProfile(:)
484 real(kind_real),
intent(inout) :: GuessProfile(:)
485 real(kind_real),
intent(in) :: BackProfile(:)
486 real(kind_real),
intent(in) :: b_inv(:,:)
491 real(kind_real),
intent(inout) :: gamma
492 real(kind_real),
intent(inout) :: Jold
493 integer,
intent(out) :: Status
496 character(len=*),
parameter :: RoutineName =
'ufo_rttovonedvarcheck_ML_RTTOV12'
499 real(kind_real) :: JOut(3)
500 real(kind_real) :: JCost
501 logical :: OutOfRange
502 real(kind_real) :: HTR(nprofelements, nChans)
503 real(kind_real) :: U(nprofelements, nprofelements)
504 real(kind_real) :: V(nprofelements)
505 real(kind_real) :: USave(nprofelements, nprofelements)
506 real(kind_real) :: VSave(nprofelements)
507 real(kind_real) :: New_DeltaProfile(nprofelements)
508 real(kind_real) :: Tau_Surf(nchans)
509 real(kind_real) :: BriTemp(nchans)
510 real(kind_real) :: Ydiff(nchans)
511 real(kind_real) :: Emiss(nchans)
512 real(kind_real) :: H_matrix_tmp(nchans,nprofelements)
513 logical :: CalcEmiss(nchans)
514 integer :: StatusOK = 0
515 integer :: RTStatus = 0
526 call r_matrix % multiply_inverse_matrix(h_matrix_t, htr)
532 u = matmul(htr, h_matrix)
533 v = matmul(htr, deltabt)
534 v = v + matmul(u, deltaprofile)
547 jcost = 1.0e10_kind_real
553 descentloop :
do while (jcost > jold .and. &
554 iter_ml < self % MaxMLIterations .and. &
555 gamma <= 1.0e25_kind_real)
557 iter_ml = iter_ml + 1
565 do i = 1, nprofelements
566 u(i,i) = usave(i,i) + gamma
568 v = vsave + gamma * deltaprofile
579 if (status /= 0)
then
580 write(*,*)
'Error in Cholesky decomposition'
587 guessprofile(:) = backprofile(:) + new_deltaprofile(:)
595 if (.not. outofrange)
then
597 guessprofile, self % UseQtSplitRain)
604 profile_index, guessprofile(:), &
605 hofxdiags, rttov_simobs, britemp(:), h_matrix_tmp)
611 if (rtstatus > 0)
then
616 jcost = 1.0e10_kind_real
618 deltaprofile(:) = guessprofile(:) - backprofile(:)
619 ydiff(:) = ob % yobs(:) - britemp(:)
622 if (status /= statusok)
goto 9999
630 jcost = 1.0e10_kind_real
636 deltaprofile = new_deltaprofile
real(kind_real), parameter, public ten
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 containing the routines to perform a Marquardt-Levenberg minimization.
subroutine, public ufo_rttovonedvarcheck_minimize_ml(self, ob, r_matrix, b_matrix, b_inv, b_sigma, local_geovals, hofxdiags, rttov_simobs, profile_index, onedvar_success)
Perform a minimization using the Marquardt-Levenberg method.
subroutine ufo_rttovonedvarcheck_ml_rttov12(self, DeltaBT, nChans, ob, H_Matrix, H_Matrix_T, nprofelements, profile_index, DeltaProfile, GuessProfile, BackProfile, b_inv, r_matrix, geovals, hofxdiags, rttov_simobs, gamma, Jold, Status)
Updates the profile vector during the Marquardt-Levenberg minimization.
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_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.