UFO
ufo_rttovonedvarcheck_minimize_ml_mod.f90
Go to the documentation of this file.
1 ! (C) Copyright 2020 Met Office
2 ! This software is licensed under the terms of the Apache Licence Version 2.0
3 ! which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
4 
5 !> Fortran module containing the routines to perform a Marquardt-Levenberg
6 !! minimization.
7 
9 
10 use kinds
11 use ufo_constants_mod, only: zero, ten
12 use fckit_log_module, only : fckit_log
22 use ufo_utils_mod, only: ops_cholesky
23 
24 implicit none
25 private
26 
28 
29 contains
30 
31 !-------------------------------------------------------------------------------
32 !> Perform a minimization using the Marquardt-Levenberg method.
33 !!
34 !! \details Heritage: Ops_SatRad_MinimizeML_RTTOV12.f90
35 !!
36 !! Find the most probable atmospheric state vector by minimizing a cost function
37 !! through a series of iterations. if a solution exists, the iterations will
38 !! converge when the iterative increments are acceptably small. A limit on the
39 !! total number of iterations allowed is imposed.
40 !!
41 !! Using the formulation given by Rodgers (1976) :
42 !!
43 !! Delta_x = xn + (xb-xn).I' + Wn.(ym-y(xn) - H.(xb-xn)) <br>
44 !! where: <br>
45 !! x is an atmospheric state vector, subscripted b=background,n=nth
46 !! iteration <br>
47 !! I' is a diagonal matrix with I'(J,J) = B_damped(J,J)/B_undamped(J,J)
48 !! although, however, damping will no longer be used <br>
49 !! Wn = B.Hn'.(Hn.B.Hn'+R)^-1 <br>
50 !! B is the background error covariance matrix <br>
51 !! R is the combined forward model and ob error covariance matrix <br>
52 !!
53 !! Delta_x is checked for convergence after each iteration
54 !!
55 !! The loop is exited with convergence if either of the following conditions are
56 !! true, depending on whether UseJforConvergence is true or false
57 !! -# if UseJforConvergence is true then the change in total cost function from
58 !! one iteration to the next is sufficiently small to imply convergence
59 !! -# if UseJforConvergence is false then the increments to the atmospheric
60 !! state vector are sufficiently small to imply convergence at an acceptable
61 !! solution
62 !!
63 !! Either of the following two conditions will cause the 1dvar to stop and exit
64 !! with an error.
65 !! -# The increments are sufficiently large to suppose a solution will not
66 !! be found.
67 !! -# The maximum number of allowed iterations has been reached. In most
68 !! cases, one of the above criteria will have occurred.
69 !!
70 !! References:
71 !!
72 !! Rodgers, Retrieval of atmospheric temperature and composition from
73 !! remote measurements of thermal radiation, Rev. Geophys.Sp.Phys. 14, 1976.
74 !!
75 !! Eyre, Inversion of cloudy satellite sounding radiances by nonlinear
76 !! optimal estimation. I: Theory and simulation for TOVS,QJ,July 89.
77 !!
78 !! \author Met Office
79 !!
80 !! \date 09/06/2020: Created
81 !!
83  ob, &
84  r_matrix, &
85  b_matrix, &
86  b_inv, &
87  b_sigma, &
88  local_geovals, &
89  hofxdiags, &
90  rttov_simobs, &
91  profile_index, &
92  onedvar_success)
93 
94 implicit none
95 
96 type(ufo_rttovonedvarcheck), intent(inout) :: self !< structure containing settings
97 type(ufo_rttovonedvarcheck_ob), intent(inout) :: ob !< satellite metadata
98 type(ufo_rttovonedvarcheck_rsubmatrix), intent(in) :: r_matrix !< observation error covariance
99 real(kind_real), intent(in) :: b_matrix(:,:) !< state error covariance
100 real(kind_real), intent(in) :: b_inv(:,:) !< inverse state error covariance
101 real(kind_real), intent(in) :: b_sigma(:) !< standard deviations of the state error covariance diagonal
102 type(ufo_geovals), intent(inout) :: local_geovals !< model data at obs location
103 type(ufo_geovals), intent(inout) :: hofxdiags !< model data containing the jacobian
104 type(ufo_radiancerttov), intent(inout) :: rttov_simobs !< rttov simulated obs object
105 type(ufo_rttovonedvarcheck_profindex), intent(in) :: profile_index !< index array for x vector
106 logical, intent(out) :: onedvar_success !< convergence flag
107 
108 ! Local declarations:
109 character(len=*), parameter :: routinename = "ufo_rttovonedvarcheck_minimize_ml"
110 integer :: inversionstatus ! status of minimisation
111 logical :: outofrange ! out of range flag for check iteration
112 logical :: converged ! converged flag
113 logical :: error ! error flag
114 integer :: iter ! iteration counter
115 integer :: rterrorcode ! error code for RTTOV
116 integer :: nchans ! number of satellite channels used
117 integer :: ii ! counter
118 integer :: nprofelements ! number of profile elements
119 real(kind_real) :: gamma ! steepness of descent parameter
120 real(kind_real) :: jcost ! current cost value
121 real(kind_real) :: jcostold ! previous iteration cost value
122 real(kind_real) :: jcostorig ! initial cost value
123 real(kind_real) :: deltaj ! change in cost during iteration
124 real(kind_real) :: deltajo ! change in cost from original
125 
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)
139 type(ufo_geovals) :: geovals
140 
141 !------------
142 ! Setup
143 !------------
144 
145 converged = .false.
146 onedvar_success = .false.
147 error = .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))
161 allocate(y(nchans))
162 allocate(y0(nchans))
163 geovals = local_geovals
164 
165 call fckit_log % debug("Using ML solver")
166 
167 ! Map GeovaLs to 1D-var profile using B matrix profile structure
168 call ufo_rttovonedvarcheck_geovals2profvec(geovals, profile_index, ob, guessprofile(:))
169 
170 iterations: do iter = 1, self % max1DVarIterations
171 
172  !-------------------------
173  ! 1. Generate new profile
174  !-------------------------
175 
176  ! Save current profile
177  oldprofile(:) = guessprofile(:)
178 
179  ! Get jacobian and new hofx
180  call ufo_rttovonedvarcheck_get_jacobian(self, geovals, ob, ob % channels_used, &
181  profile_index, guessprofile(:), &
182  hofxdiags, rttov_simobs, y(:), h_matrix)
183 
184  if (iter == 1) then
185  rterrorcode = 0
186  diffprofile(:) = zero
187  backprofile(:) = guessprofile(:)
188  y0(:) = y(:)
189  end if
190 
191  ! exit on error
192  if (rterrorcode /= 0) then
193  write(*,*) "Radiative transfer error"
194  exit iterations
195  end if
196 
197  ! Calculate Obs diff and initial cost
198  ydiff(:) = ob % yobs(:) - y(:)
199  if (iter == 1) then
200  diffprofile(:) = guessprofile(:) - backprofile(:)
201  call ufo_rttovonedvarcheck_costfunction(diffprofile, b_inv, ydiff, r_matrix, jout)
202  jcost = jout(1)
203  jcostorig = jcost
204  end if
205 
206  !-----------------------------------------------------
207  ! 1a. if UseJForConvergence is true
208  ! then compute costfunction for latest profile
209  ! and determine convergence using change in cost fn
210  !-----------------------------------------------------
211 
212  if (self % UseJForConvergence) then
213 
214  ! exit on error
215  !if (inversionStatus /= 0) exit Iterations
216 
217  ! check for convergence
218  if (iter > 1) then
219 
220  if (self % JConvergenceOption == 1) then
221 
222  ! percentage change tested between iterations
223  deltaj = abs((jcost - jcostold) / max(jcost, tiny(zero)))
224 
225  ! default test for checking that overall cost is getting smaller
226  deltajo = -1.0_kind_real
227 
228  else
229 
230  ! absolute change tested between iterations
231  deltaj = abs(jcost - jcostold)
232 
233  ! change between current cost and initial
234  deltajo = jcost - jcostorig
235 
236  end if
237 
238  if (deltaj < self % cost_convergencefactor .and. &
239  deltajo < zero) then ! overall is cost getting smaller?
240  converged = .true.
241  exit iterations
242  end if
243 
244  end if
245 
246  end if ! end of specific code for cost test convergence
247 
248  ! store cost function from previous cycle
249  jcostold = jcost
250 
251  ! Iterate (Guess) profile vector
252  call ufo_rttovonedvarcheck_ml_rttov12 ( self, &
253  ydiff, &
254  nchans, &
255  ob, &
256  h_matrix, &
257  transpose(h_matrix), &
258  nprofelements, &
259  profile_index, &
260  diffprofile, &
261  guessprofile, &
262  backprofile, &
263  b_inv, &
264  r_matrix, &
265  geovals, &
266  hofxdiags, &
267  rttov_simobs, &
268  gamma, &
269  jcost, &
270  inversionstatus)
271 
272  if (inversionstatus /= 0) then
273  inversionstatus = 1
274  write(*,*) "inversion failed"
275  exit iterations
276  end if
277 
278  !---------------------------------------------------------
279  ! 2. Check new profile and transfer to forward model format
280  !---------------------------------------------------------
281 
282  ! Check profile and constrain humidity variables
283  call ufo_rttovonedvarcheck_checkiteration (self, & ! in
284  geovals, & ! in
285  profile_index, & ! in
286  guessprofile(:), & ! inout
287  outofrange) ! out
288 
289  ! Update geovals to be the same as guess profile
290  call ufo_rttovonedvarcheck_profvec2geovals(geovals, profile_index, ob, &
291  guessprofile, self % UseQtSplitRain)
292 
293  ! if qtotal in retrieval vector check cloud
294  ! variables for current iteration
295 
296  if ((.not. outofrange) .and. profile_index % qt(1) > 0) then
297 
298  if (iter >= self % IterNumForLWPCheck) then
299 
300  call ufo_rttovonedvarcheck_checkcloudyiteration( geovals, & ! in
301  profile_index, & ! in
302  self % nlevels, & ! in
303  outofrange ) ! out
304 
305  end if
306 
307  end if
308 
309  !-------------------------------------------------
310  ! 3. Check for convergence using change in profile
311  ! This is performed if UseJforConvergence is false
312  !-------------------------------------------------
313 
314  absdiffprofile(:) = zero
315 
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"
320  converged = .true.
321  end if
322  end if
323 
324  !---------------------
325  ! 4. output diagnostics
326  !---------------------
327 
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:'
334  call ufo_geovals_print(geovals, 1)
335  write (*, '(A)')
336  end if
337 
338  ! exit conditions
339 
340  if (converged .OR. outofrange) exit iterations
341 
342 end do iterations
343 
344 ! Pass convergence flag out
345 onedvar_success = converged
346 
347 ! Recalculate final cost - to make sure output when profile has not converged
348 call ufo_rttovonedvarcheck_costfunction(diffprofile, b_inv, ydiff, r_matrix, jout)
349 ob % final_cost = jout(1)
350 ob % niter = iter
351 ob % final_bt_diff = ydiff
352 
353 ! Pass output profile, final BTs and final cost out
354 if (converged) then
355  ob % output_profile(:) = guessprofile(:)
356 
357  ! If lwp output required then recalculate
358  if (self % Store1DVarLWP) then
359  call ufo_rttovonedvarcheck_checkcloudyiteration( geovals, & ! in
360  profile_index, & ! in
361  self % nlevels, & ! in
362  outofrange, & ! out
363  outlwp = ob % LWP ) ! out
364  end if
365 
366  ! Recalculate final BTs for all channels
367  allocate(out_h_matrix(size(ob % channels_all),nprofelements))
368  allocate(out_y(size(ob % channels_all)))
369  call ufo_rttovonedvarcheck_get_jacobian(self, geovals, ob, ob % channels_all, &
370  profile_index, guessprofile(:), &
371  hofxdiags, rttov_simobs, out_y(:), out_h_matrix)
372  ob % output_BT(:) = out_y(:)
373  deallocate(out_y)
374  deallocate(out_h_matrix)
375 end if
376 
377 !----------------------
378 ! 4. output diagnostics
379 !----------------------
380 
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
384 end if
385 
386 ! ----------
387 ! Tidy up
388 ! ----------
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)
399 
401 
402 !---------------------------------------------------------------------
403 !> Updates the profile vector during the Marquardt-Levenberg
404 !! minimization.
405 !!
406 !! \details Heritage: Ops_SatRad_MarquardtLevenberg_RTTOV12.f90
407 !!
408 !! Updates the profile vector DeltaProfile according to Rodgers (1976), Eqn. 100,
409 !! extended to allow for additional cost function terms and Marquardt-Levenberg
410 !! descent.
411 !!
412 !! x_(n+1) = xb + U^-1.V <br>
413 !! where <br>
414 !! U=(B^-1 + H^T R^-1 H + J2) <br>
415 !! V=H^T R^-1 [(ym-y(x_n))+H(x_n-xb)] - J1 <br>
416 !! and <br>
417 !! J_extra=J0+J1.(x-xb)+(x-xb)^T.J2.(x-xb) is the additional cost
418 !! function <br>
419 !! x is an atmospheric state vector, subscripted b=background,n=nth
420 !! iteration <br>
421 !! ym is the measurement vector (i.e. observed brightness temperatures) <br>
422 !! y(xn) is the observation vector calculated for xn <br>
423 !! ym and y(xn) are not used individually at all, hence these are input <br>
424 !! as a difference vector DeltaBT. <br>
425 !! B is the background error covariance matrix <br>
426 !! R is the combined forward model and ob error covariance matrix <br>
427 !! H is the forward model gradient (w.r.t. xn) matrix <br>
428 !! H' is the transpose of H <br>
429 !!
430 !! When J_extra is zero this is simply Rogers (1976), Eqn. 100.
431 !!
432 !! U^-1.V is solved using Cholesky decomposition.
433 !!
434 !! This routine should be used when:
435 !! -# The length of the observation vector is greater than the length
436 !! of the state vector,
437 !! -# Additional cost function terms are provided and
438 !! -# where Newtonian minimisation is desired.
439 !!
440 !! References:
441 !!
442 !! Rodgers, Retrieval of atmospheric temperature and composition from
443 !! remote measurements of thermal radiation, Rev. Geophys.Sp.Phys. 14, 1976.
444 !!
445 !! Rodgers, Inverse Methods for Atmospheres: Theory and Practice. World
446 !! Scientific Publishing, 2000.
447 !!
448 !! \author Met Office
449 !!
450 !! \date 09/06/2020: Created
451 !!
453  DeltaBT, &
454  nChans, &
455  ob, &
456  H_Matrix, &
457  H_Matrix_T, &
458  nprofelements, &
459  profile_index, &
460  DeltaProfile, &
461  GuessProfile, &
462  BackProfile, &
463  b_inv, &
464  r_matrix, &
465  geovals, &
466  hofxdiags, &
467  rttov_simobs, &
468  gamma, &
469  Jold, &
470  Status)
471 
472 implicit none
473 
474 ! subroutine arguments:
475 type(ufo_rttovonedvarcheck), intent(in) :: self !< structure containing settings
476 real(kind_real), intent(in) :: DeltaBT(:) !< y-y(x)
477 integer, intent(in) :: nChans !< number of channels
478 type(ufo_rttovonedvarcheck_ob), intent(inout) :: ob !< satellite metadata
479 real(kind_real), intent(in) :: H_Matrix(:,:) !< Jacobian
480 real(kind_real), intent(in) :: H_Matrix_T(:,:) !< transpose of the Jacobian
481 integer, intent(in) :: nprofelements !< number of profile elements
482 type(ufo_rttovonedvarcheck_profindex), intent(in) :: profile_index !< index array for x vector
483 real(kind_real), intent(inout) :: DeltaProfile(:) !< x_(n+1) - xb
484 real(kind_real), intent(inout) :: GuessProfile(:) !< x_(n+1)
485 real(kind_real), intent(in) :: BackProfile(:) !< xb
486 real(kind_real), intent(in) :: b_inv(:,:) !< inverse of the state error covariance
487 type(ufo_rttovonedvarcheck_rsubmatrix), intent(in) :: r_matrix !< observation error covariance
488 type(ufo_geovals), intent(inout) :: geovals !< model data at obs location
489 type(ufo_geovals), intent(inout) :: hofxdiags !< model data containing the jacobian
490 type(ufo_radiancerttov), intent(inout) :: rttov_simobs
491 real(kind_real), intent(inout) :: gamma !< steepness of descent parameter
492 real(kind_real), intent(inout) :: Jold !< previous steps cost which gets update by good step
493 integer, intent(out) :: Status !< code to capture failed Cholesky decomposition
494 
495 ! Local declarations:
496 character(len=*), parameter :: RoutineName = 'ufo_rttovonedvarcheck_ML_RTTOV12'
497 integer :: i
498 integer :: Iter_ML ! M-L iteration count
499 real(kind_real) :: JOut(3) ! J, Jb, Jo
500 real(kind_real) :: JCost ! Cost function,
501 logical :: OutOfRange
502 real(kind_real) :: HTR(nprofelements, nChans) ! Scratch vector
503 real(kind_real) :: U(nprofelements, nprofelements) ! U = H.B.H^T + R
504 real(kind_real) :: V(nprofelements) ! V = (y-y(x_n))-H^T(xb-x_n)
505 real(kind_real) :: USave(nprofelements, nprofelements) ! U = H.B.H^T + R
506 real(kind_real) :: VSave(nprofelements) ! V = (y-y(x_n))-H^T(xb-x_n)
507 real(kind_real) :: New_DeltaProfile(nprofelements)
508 real(kind_real) :: Tau_Surf(nchans) ! Transmittance from surface
509 real(kind_real) :: BriTemp(nchans) ! Forward modelled brightness temperatures
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
516 
517 status = statusok
518 
519 !---------------------------------------------------------------------------
520 ! 1. Calculate HTR-1 for the three allowed forms of R matrix. if required, the
521 ! matrix is tested to determine whether it is stored as an inverse and
522 ! inverted if not.
523 !---------------------------------------------------------------------------
524 
525 !HTR(-1) = matmul(H_matrix_T, R_inverse)
526 call r_matrix % multiply_inverse_matrix(h_matrix_t, htr)
527 
528 !---------------------------------------------------------------------------
529 ! 2. Calculate U and V
530 !---------------------------------------------------------------------------
531 
532 u = matmul(htr, h_matrix)
533 v = matmul(htr, deltabt)
534 v = v + matmul(u, deltaprofile)
535 
536 !---------------------------------------------------------------------------
537 ! 3. Add on inverse of B-matrix to U.
538 !---------------------------------------------------------------------------
539 
540 u = u + b_inv
541 
542 !---------------------------------------------------------------------------
543 ! 5. Start Marquardt-Levenberg loop.
544 ! Search for a value of gamma that reduces the cost function.
545 !---------------------------------------------------------------------------
546 
547 jcost = 1.0e10_kind_real
548 gamma = gamma / ten
549 usave = u
550 vsave = v
551 iter_ml = 0
552 
553 descentloop : do while (jcost > jold .and. &
554  iter_ml < self % MaxMLIterations .and. &
555  gamma <= 1.0e25_kind_real)
556 
557  iter_ml = iter_ml + 1
558 
559  !------------------------------------------------------------------------
560  ! 5.1 Add on Marquardt-Levenberg terms to U and V.
561  !------------------------------------------------------------------------
562 
563  gamma = gamma * ten
564 
565  do i = 1, nprofelements
566  u(i,i) = usave(i,i) + gamma
567  end do
568  v = vsave + gamma * deltaprofile
569 
570  !------------------------------------------------------------------------
571  ! 5.2 Calculate new profile increment.
572  !------------------------------------------------------------------------
573 
574  call ops_cholesky (u, &
575  v, &
576  nprofelements, &
577  new_deltaprofile, &
578  status)
579  if (status /= 0) then
580  write(*,*) 'Error in Cholesky decomposition'
581  end if
582 
583  !------------------------------------------------------------------------
584  ! 5.3. Calculate the radiances for the new profile.
585  !------------------------------------------------------------------------
586 
587  guessprofile(:) = backprofile(:) + new_deltaprofile(:)
588 
589  call ufo_rttovonedvarcheck_checkiteration (self, & ! in
590  geovals, & ! in
591  profile_index, & ! in
592  guessprofile(:), & ! inout
593  outofrange) ! out
594 
595  if (.not. outofrange) then
596  call ufo_rttovonedvarcheck_profvec2geovals(geovals, profile_index, ob, &
597  guessprofile, self % UseQtSplitRain)
598 
599  !Emiss(1:nchans) = RTprof_Guess % Emissivity(Channels(1:nchans))
600  !CalcEmiss(1:nchans) = RTprof_Guess % CalcEmiss(Channels(1:nchans))
601 
602  ! Get Jabobian and new hofx
603  call ufo_rttovonedvarcheck_get_jacobian(self, geovals, ob, ob % channels_used, &
604  profile_index, guessprofile(:), &
605  hofxdiags, rttov_simobs, britemp(:), h_matrix_tmp)
606 
607  !------------------------------------------------------------------------
608  ! 5.6. Calculate the new cost function.
609  !------------------------------------------------------------------------
610 
611  if (rtstatus > 0) then
612 
613  ! In case of RT error, set cost to large value and
614  ! continue with next iteration
615 
616  jcost = 1.0e10_kind_real
617  else
618  deltaprofile(:) = guessprofile(:) - backprofile(:)
619  ydiff(:) = ob % yobs(:) - britemp(:)
620  call ufo_rttovonedvarcheck_costfunction(deltaprofile, b_inv, ydiff, r_matrix, jout)
621  jcost = jout(1)
622  if (status /= statusok) goto 9999
623  end if
624 
625  else
626 
627  ! if profile out of range, set cost to large value and
628  ! continue with next iteration
629 
630  jcost = 1.0e10_kind_real
631 
632  end if
633 
634 end do descentloop
635 
636 deltaprofile = new_deltaprofile
637 gamma = gamma / ten
638 jold = jcost
639 
640 9999 continue
641 
643 
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.