UFO
ufo_metoffice_bmatrixstatic_mod.f90
Go to the documentation of this file.
1 ! (C) British Crown Copyright 2020 Met Office
2 !
3 ! This software is licensed under the terms of the Apache Licence Version 2.0
4 ! which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
5 
6 !> Fortran module containing the full b-matrix data type and methods for the 1D-Var.
7 
9 
10 use fckit_log_module, only : fckit_log
11 use kinds
12 use ufo_constants_mod, only: zero, one
14 use ufo_vars_mod
15 
16 implicit none
17 private
18 
20  logical :: status !< status indicator
21  integer :: nbands !< number of latitude bands
22  integer :: nsurf !< number of surface type variations
23  integer :: nfields !< number of fields
24  integer, pointer :: fields(:,:) !< fieldtypes and no. elements in each
25  real(kind=kind_real), pointer :: store(:,:,:) !< original b-matrices read from the file
26  real(kind=kind_real), pointer :: inverse(:,:,:) !< inverse of above
27  real(kind=kind_real), pointer :: sigma(:,:) !< diagonal elements
28  real(kind=kind_real), pointer :: proxy(:,:) !< copy of original for manipulation
29  real(kind=kind_real), pointer :: inv_proxy(:,:) !< copy of inverse
30  real(kind=kind_real), pointer :: sigma_proxy(:,:) !< copy of diagonal
31  real(kind=kind_real), pointer :: south(:) !< s limit of each latitude band
32  real(kind=kind_real), pointer :: north(:) !< n limit of each latitude band
33 contains
34  procedure :: setup => ufo_metoffice_bmatrixstatic_setup
35  procedure :: delete => ufo_metoffice_bmatrixstatic_delete
36  procedure :: reset => ufo_metoffice_bmatrixstatic_reset
38 
39 character(len=200) :: message
40 
41 !-----------------------------------------------------------------------------
42 ! 1. 1d-var profile elements
43 !-----------------------------------------------------------------------------
44 
45 ! define id codes for 1d-var retrieval fields.
46 ! a list of these fieldtype codes is always present in the header of the bmatrix
47 ! file and it's that list which decides the form of the retrieval vector.
48 !
49 ! new definitions should be made in conjunction with the profileinfo_type
50 ! structure found in ufo_rttovonedvarcheck_profindex_mod.F90.
51 
52 integer, parameter, public :: nfieldtypes_ukmo = 19 !< number of fieldtypes
53 integer, parameter, public :: &
54  ufo_metoffice_fieldtype_t = 1, & !< temperature
55  ufo_metoffice_fieldtype_q = 2, & !< specific humidity profile
56  ufo_metoffice_fieldtype_t2 = 3, & !< surface air temperature
57  ufo_metoffice_fieldtype_q2 = 4, & !< surface spec humidity
58  ufo_metoffice_fieldtype_tstar = 5, & !< surface skin temperature
59  ufo_metoffice_fieldtype_pstar = 6, & !< surface pressure
60  ufo_metoffice_fieldtype_o3total = 7, & !< total column ozone - not currently setup
61  ufo_metoffice_fieldtype_not_used = 8, & !< not currently in use - not currently setup
62  ufo_metoffice_fieldtype_ql = 9, & !< liquid water profile - not currently setup
63  ufo_metoffice_fieldtype_qt = 10, & !< total water profile
64  ufo_metoffice_fieldtype_windspeed = 11, & !< surface wind speed
65  ufo_metoffice_fieldtype_o3profile = 12, & !< ozone - not currently setup
66  ufo_metoffice_fieldtype_lwp = 13, & !< liquid water path - not currently setup
67  ufo_metoffice_fieldtype_mwemiss = 14, & !< microwave emissivity - not currently setup
68  ufo_metoffice_fieldtype_qi = 15, & !< ice profile - not currently setup
69  ufo_metoffice_fieldtype_cloudtopp = 16, & !< single-level cloud top pressure
70  ufo_metoffice_fieldtype_cloudfrac = 17, & !< effective cloud fraction
71  ufo_metoffice_fieldtype_emisspc = 18, & !< emissivity prinipal components - not currently setup
72  ufo_metoffice_fieldtype_cf = 19 !< cloud fraction profile - not currently setup
73 
74 character(len=*), parameter, public :: ufo_metoffice_fieldtype_text(nfieldtypes_ukmo) = &
75  (/ var_ts, &
76  var_q, &
77  var_sfc_t2m, &
78  var_sfc_q2m, &
79  var_sfc_tskin, &
80  var_sfc_p2m, &
81  'ozone (total column)', &
82  '[unused field type] ', &
83  var_clw, &
84  'q total ', &
86  'ozone (profile) ', &
87  'liquid water path ', &
88  var_sfc_emiss, &
89  var_cli, &
90  'cloud top pressure ', &
91  'cloud fraction ', &
92  'emissivity pcs ', &
93  var_cldfrac /)
94 
95 contains
96 
97 ! ------------------------------------------------------------------------------------------------
98 !> Routine to read and setup the 1D-Var B-matrix
99 !!
100 !! \author Met Office
101 !!
102 !! \date 09/06/2020: Created
103 !!
104 subroutine ufo_metoffice_bmatrixstatic_setup(self, variables, filepath, qtotal_flag)
105 
106 implicit none
107 class(ufo_metoffice_bmatrixstatic), intent(inout) :: self !< B-matrix Covariance
108 character(len=*), intent(in) :: variables(:) !< Model variables in B matrix
109 character(len=*), intent(in) :: filepath !< Path to B matrix file
110 logical, intent(in) :: qtotal_flag !< Flag for qtotal
111 
112 logical :: file_exists ! Check if a file exists logical
113 integer :: fileunit ! Unit number for reading in files
114 integer, allocatable :: fields_in(:) ! Fields_in used to subset b-matrix for testing.
115 real(kind=kind_real) :: t1,t2 ! Time values for logging
116 character(len=:), allocatable :: str
117 logical :: testing = .false.
118 integer :: ii, jj
119 logical :: match
120 
121 call fckit_log % info("ufo_metoffice_bmatrixstatic_setup start")
122 
123 call cpu_time(t1)
124 
125 ! Open file and read in b-matrix
126 inquire(file=trim(filepath), exist=file_exists)
127 if (file_exists) then
128  fileunit = ufo_utils_iogetfreeunit()
129  open(unit = fileunit, file = trim(filepath))
131  call rttovonedvarcheck_create_fields_in(fields_in, variables, qtotal_flag)
132  if (testing) then
133  call rttovonedvarcheck_covariance_getbmatrix(self, fileunit, fieldlist=fields_in)
134  else
135  call rttovonedvarcheck_covariance_getbmatrix(self, fileunit)
136  end if
137  close(unit = fileunit)
138  call fckit_log % info("rttovonedvarcheck bmatrix file exists and read in")
139 else
140  call abor1_ftn("rttovonedvarcheck bmatrix file not found")
141 end if
142 
143 call cpu_time(t2)
144 
145 ! Check the yaml input contains all required b-matrix elements
146 do ii = 1, size(self % fields(:,1)) ! loop over b-matrix elements
147  match = .false.
148  do jj = 1, size(fields_in) ! loop over array generated from yaml
149  if (self % fields(ii,1) == fields_in(jj)) match = .true.
150  end do
151  if (.not. match) then
152  write(*,*) "input model variables do not have ",ufo_metoffice_fieldtype_text(self % fields(ii,1))
153  call abor1_ftn("rttovonedvarcheck not all the model data is available for the b-matrix")
154  end if
155 end do
156 
157 write(message,*) "ufo_metoffice_bmatrixstatic_setup cpu time = ",(t2-t1)
158 call fckit_log % info(message)
159 
161 
162 ! ------------------------------------------------------------------------------------------------
163 !> Routine to delete and squash the 1D-Var B-matrix
164 !!
165 !! \details Met Office OPS Heritage: Ops_SatRad_SquashBmatrix.f90
166 !!
167 !! \author Met Office
168 !!
169 !! \date 09/06/2020: Created
170 !!
172 
173 implicit none
174 class(ufo_metoffice_bmatrixstatic), intent(inout) :: self !< B-matrix Covariance
175 
176 character(len=*), parameter :: RoutineName = "ufo_metoffice_bmatrixstatic_delete"
177 
178 self % status = .false.
179 self % nbands = 0
180 self % nsurf = 0
181 if ( associated(self % fields) ) deallocate( self % fields )
182 if ( associated(self % store) ) deallocate( self % store )
183 if ( associated(self % inverse) ) deallocate( self % inverse )
184 if ( associated(self % sigma) ) deallocate( self % sigma )
185 if ( associated(self % proxy) ) deallocate( self % proxy )
186 if ( associated(self % inv_proxy) ) deallocate( self % inv_proxy )
187 if ( associated(self % sigma_proxy) ) deallocate( self % sigma_proxy )
188 if ( associated(self % south) ) deallocate( self % south )
189 if ( associated(self % north) ) deallocate( self % north )
190 
192 
193 ! ------------------------------------------------------------------------------------------------
194 !> \brief Routine to initialize the 1D-Var B-matrix
195 !!
196 !! \details Met Office OPS Heritage: Ops_SatRad_InitBmatrix.f90
197 !!
198 !! \author Met Office
199 !!
200 !! \date 09/06/2020: Created
201 !!
203 
204 implicit none
205 
206 ! subroutine arguments:
207 type(ufo_metoffice_bmatrixstatic), intent(out) :: self !< B-matrix Covariance
208 
209 character(len=*), parameter :: routinename = "rttovonedvarcheck_covariance_InitBmatrix"
210 
211 self % status = .false.
212 self % nbands = 0
213 self % nsurf = 0
214 nullify( self % fields )
215 nullify( self % store )
216 nullify( self % inverse )
217 nullify( self % sigma )
218 nullify( self % proxy )
219 nullify( self % inv_proxy )
220 nullify( self % sigma_proxy )
221 nullify( self % south )
222 nullify( self % north )
223 
225 
226 ! ------------------------------------------------------------------------------------------------
227 !> Routine to initialize the 1D-Var B-matrix
228 !!
229 !! \details Met Office OPS Heritage: Ops_SatRad_GetBmatrix.f90
230 !!
231 !! read the input file and allocate and fill in all the components of the bmatrix
232 !! structure, with the exception of proxy variables.
233 !!
234 !! notes:
235 !!
236 !! it is assumed a valid bmatrix file is available and has been opened ready for
237 !! reading, accessed via the input unit number.
238 !!
239 !! two optional arguments are provided to allow a submatrix to be formed from the
240 !! original file, either depending on a list of fields to be used for retrieval,
241 !! or a list of specific element numbers to be retained.
242 !!
243 !! the file header may begin with any number of comment lines, which are defined
244 !! as those using either # or ! as the first non-blank character.
245 !!
246 !! immediately following any comments, the header should then contain information
247 !! on the size of the matrix to be read in, and a description of each matrix
248 !! element. memory will be allocated depending on these matrix specifications.
249 !!
250 !! each matrix should then have a one line header containing the latitude bounds
251 !! and a latitude band id. band id numbers should be sequential in latitude. i.e.
252 !! band 1 will begin at -90.0, band 2 from -60.0 ... (or however wide we choose
253 !! the bands).
254 !!
255 !! we also calculate an inverse of each b matrix, used in the current 1d-var for
256 !! cost function monitoring only but it may be required for other minimization
257 !! methods at some point.
258 !!
259 !! standard deviations are also stored in a separate vector.
260 !!
261 !! proxy variables are provided to allow manipulation of the chosen matrix during
262 !! processing without affecting the original. we might wish to do this, for
263 !! example, to take account of the different surface temperature errors for land
264 !! and sea. this routine makes no assumption about the use of these variables,
265 !! hence no space is allocated. nullification of unused pointers should take
266 !! place outside (use the ops_satrad_initbmatrix routine).
267 !!
268 !! \author Met Office
269 !!
270 !! \date 09/06/2020: Created
271 !!
273  fileunit, &
274  b_elementsused, &
275  fieldlist)
276 
277 implicit none
278 
279 ! subroutine arguments:
280 type (ufo_metoffice_bmatrixstatic), intent(inout) :: self !< B-matrix covariance
281 integer, intent(in) :: fileunit !< free file unit number
282 integer, optional, intent(in) :: b_elementsused(:) !< optional: list of elements used
283 integer, optional, intent(inout) :: fieldlist(:) !< optional: list of fields used
284 
285 ! local declarations:
286 character(len=*), parameter :: routinename = "rttovonedvarcheck_covariance_GetBmatrix"
287 integer :: i
288 integer :: j
289 integer :: k
290 integer :: readstatus
291 integer :: status
292 integer :: nbands
293 integer :: matrixsize
294 integer :: band
295 integer :: nmatrix
296 integer :: nbfields
297 integer :: nelements
298 integer :: nelements_total
299 real(kind=kind_real) :: southlimit
300 real(kind=kind_real) :: northlimit
301 character(len=80) :: line
302 character(len=3) :: fieldtype
303 real(kind=kind_real), allocatable :: bfromfile(:,:)
304 logical, allocatable :: list(:)
305 integer, allocatable :: bfields(:,:)
306 integer, allocatable :: elementsused(:)
307 
308 !--------------------------
309 ! 1. read header information
310 !--------------------------
311 
312 !----
313 ! 1.1) header comments
314 !----
315 
316 ! read individual lines until one is found where the first non-blank character
317 ! is not # or !
318 
319 do
320  read (fileunit, '(a)') line
321  line = adjustl(line)
322  if (verify(line, '#!') == 1) then
323  backspace(fileunit)
324  exit
325  end if
326 end do
327 
328 !----
329 ! 1.2) matrix information
330 !----
331 
332 nmatrix = 0
333 nbfields = 0
334 read (fileunit, *) matrixsize, nbands, nbfields ! matrix size, no. of latitude
335 if (nbfields > 0) then ! bands, no. of fields
336  allocate (bfields(nbfields,2))
337  do i = 1, nbfields
338  read (fileunit, *) bfields(i,1), bfields(i,2) ! field id, number of elements
339  end do
340 end if
341 
342 !----
343 ! 1.3) output initial messages
344 !----
345 
346 call fckit_log % debug('reading b matrix file:')
347 write (message, '(a,i0)') 'number of latitude bands = ', nbands
348 call fckit_log % debug(message)
349 write (message, '(a,i0)') 'matrix size = ', matrixsize
350 call fckit_log % debug(message)
351 if (nbfields > 0) then
352  call fckit_log % debug('order of fields and number of elements in each:')
353  do i = 1, nbfields
354  write (message, '(i0,a)') bfields(i,2), ' x ' // ufo_metoffice_fieldtype_text(bfields(i,1))
355  call fckit_log % debug(message)
356  end do
357 end if
358 
359 !-------------------------------------------------------
360 ! 2. read matrix field mappings and generate element list
361 !-------------------------------------------------------
362 
363 ! each field in the bmatrix has a designated id number (defined in
364 ! opsmod_satrad_info) that is included in the file header. under certain
365 ! circumstances there may be a requirement to exclude some of the fields from
366 ! the matrix and this can be achieved by including the fieldlist argument which
367 ! should contain the required id values.
368 ! this section checks the fields in fieldlist against those in the file and makes
369 ! up a final list of those common to both. subsequently, this is translated to
370 ! the exact element numbers that we wish to keep. note that an alternative to
371 ! this method is to provide the element numbers explicitly in the argument
372 ! b_elementsused.
373 
374 allocate (self % fields(nfieldtypes_ukmo,2))
375 self % fields(:,:) = 0
376 self % status = .true.
377 nelements = 0
378 nelements_total = 0
379 self % nfields = 0
380 
381 if (present (fieldlist)) then
382 
383  !----
384  ! 2.1) use retrieval field list if optional argument fieldlist present
385  !----
386 
387  allocate (elementsused(matrixsize))
388  blist: do j = 1, nbfields
389  do i = 1, size (fieldlist)
390  if (fieldlist(i) == 0) cycle
391  if (bfields(j,1) == fieldlist(i)) then
392  do k = 1, bfields(j,2)
393  elementsused(nelements + k) = nelements_total + k
394  end do
395  nelements_total = nelements_total + bfields(j,2)
396  nelements = nelements + bfields(j,2)
397  fieldlist(i) = 0 ! store only fields that are not used in here
398  cycle blist
399  end if
400  end do
401  bfields(j,1) = 0 ! store only fields that are used in here
402  nelements_total = nelements_total + bfields(j,2)
403  end do blist
404 
405  nbfields = count(bfields(:,1) /= 0)
406  bfields(1:nbfields,2) = pack(bfields(:,2), bfields(:,1) /= 0)
407  bfields(1:nbfields,1) = pack(bfields(:,1), bfields(:,1) /= 0)
408 
409  ! 2.1.1) write messages
410 
411  if (any(fieldlist /= 0)) then
412  call fckit_log % debug('the following requested retrieval fields are not in the b matrix:')
413  do i = 1, size (fieldlist)
414  if (fieldlist(i) /= 0) then
415  write (fieldtype, '(i0)') fieldlist(i)
416  if (fieldlist(i) > 0 .and. fieldlist(i) <= nfieldtypes_ukmo) then
417  write (message, '(a)') trim(ufo_metoffice_fieldtype_text(fieldlist(i))) // &
418  ' (fieldtype ' // trim(adjustl(fieldtype)) // ')'
419  call fckit_log % debug(message)
420  else
421  write (message, '(a)') 'fieldtype ' // trim(adjustl(fieldtype)) // &
422  ' which is invalid'
423  call fckit_log % debug(message)
424  end if
425  end if
426  end do
427  end if
428 
429  call fckit_log % debug('b matrix fields used to define the retrieval profile vector:')
430  do i = 1, nbfields
431  write (message, '(a)') ufo_metoffice_fieldtype_text(bfields(i,1))
432  call fckit_log % debug(message)
433  end do
434 
435  ! 2.1.2) reset fieldlist so that only used fields are now stored
436 
437  fieldlist(1:nbfields) = bfields(1:nbfields,1)
438  if (nbfields < size (fieldlist)) fieldlist(nbfields + 1:) = 0
439 
440 else if (present (b_elementsused)) then
441 
442  !----
443  ! 2.2) or use exact element numbers if optional argument b_elementsused present
444  !----
445 
446  allocate (elementsused(size (b_elementsused)))
447  if (any(b_elementsused < 0 .and. b_elementsused > matrixsize)) then
448  write(*,*) routinename // ' : invalid b matrix elements present in input list'
449  end if
450  nelements = count(b_elementsused > 0 .and. b_elementsused <= matrixsize)
451  elementsused(1:nelements) = pack(b_elementsused, b_elementsused > 0 .and. b_elementsused <= matrixsize)
452 
453 else
454 
455  !----
456  ! 2.3) or use everything by default
457  !----
458 
459  nelements = matrixsize
460 
461 end if
462 
463 !---------------------------------------------------------
464 ! 3. read the file and store in bmatrix structure variables
465 !---------------------------------------------------------
466 
467 ! set field list in structure variable
468 
469 if (nbfields > 0) self % fields(1:nbfields,:) = bfields(1:nbfields,:)
470 self % nfields = nbfields
471 
472 ! initialize the rest
473 
474 self % nbands = nbands
475 allocate (self % store(nelements,nelements,nbands))
476 allocate (self % south(nbands))
477 allocate (self % north(nbands))
478 self % store(:,:,:) = zero
479 
480 ! allocate dummy variables for file input
481 
482 allocate (list(nbands))
483 allocate (bfromfile(matrixsize,matrixsize))
484 list(:) = .false.
485 
486 readallb : do
487 
488  !----
489  ! 3.1) read matrix
490  !----
491 
492  ! latitude band information
493 
494  read (fileunit, '(i3,2f8.2)', iostat = readstatus) band, southlimit, northlimit
495  if (readstatus < 0) exit
496 
497  ! matrix data
498 
499  do j = 1, matrixsize
500  read (fileunit, '(5e16.8)' ) (bfromfile(i,j), i = 1, matrixsize)
501  end do
502 
503  write (message, '(a,i0,a,2f8.2)') &
504  'band no.', band, ' has southern and northern latitude limits of', &
505  southlimit, northlimit
506  call fckit_log % debug(message)
507 
508  !----
509  ! 3.2) transfer into 1d-var arrays
510  !----
511 
512  if (band > 0 .and. band <= nbands) then
513  list(band) = .true.
514  nmatrix = nmatrix + 1
515  if (nelements < matrixsize) then
516  self % store(:,:,band) = &
517  bfromfile(elementsused(1:nelements),elementsused(1:nelements))
518  else
519  self % store(:,:,band) = bfromfile(:,:)
520  end if
521  self % south(band) = southlimit
522  self % north(band) = northlimit
523  else
524  write (message, '(a,i0)') 'skipped matrix with band number ', band
525  call fckit_log % debug(message)
526  end if
527 
528 end do readallb
529 
530 !---------------------
531 ! 4. store error vector
532 !---------------------
533 
534 allocate (self % sigma(nelements,nbands))
535 do i = 1, nelements
536  self % sigma(i,:) = sqrt(self % store(i,i,:))
537 end do
538 
539 !----------------
540 ! 5. invert matrix
541 !----------------
542 
543 allocate (self % inverse(nelements,nelements,nbands))
544 self % inverse(:,:,:) = self % store(:,:,:)
545 
546 do k = 1, nbands
547  call invertmatrix (nelements, & ! in
548  nelements, & ! in
549  self % inverse(:,:,k), & ! inout
550  status) ! out
551  if (status /= 0) then
552  call abor1_ftn("rttovonedvarcheck: bmatrix is not invertible")
553  end if
554 end do
555 
556 !----------
557 ! 6. tidy up
558 !----------
559 
560 if (nmatrix < nbands) then
561  call abor1_ftn("rttovonedvarcheck: too few b matrices found in input file")
562 end if
563 
565 
566 ! ------------------------------------------------------------------------------------------------
567 !> Routine to create error covariances for a single observation
568 !!
569 !! \details Met Office OPS Heritage: Ops_SatRad_ResetCovariances.f90
570 !!
571 !! \author Met Office
572 !!
573 !! \date 08/09/2020: Created
574 !!
575 subroutine ufo_metoffice_bmatrixstatic_reset(self, latitude, & ! in
576  b_matrix, b_inverse, b_sigma ) ! out
577 
578 implicit none
579 
580 ! Subroutine arguments
581 class(ufo_metoffice_bmatrixstatic), intent(in) :: self !< B-matrix covariance
582 real(kind_real), intent(in) :: latitude
583 real(kind_real), intent(out) :: b_matrix(:,:)
584 real(kind_real), intent(out) :: b_inverse(:,:)
585 real(kind_real), intent(out) :: b_sigma(:)
586 
587 ! Local Variables
588 integer :: band, i
589 
590 ! select appropriate b matrix for latitude of observation
591 b_matrix(:,:) = zero
592 b_inverse(:,:) = zero
593 b_sigma(:) = zero
594 do band = 1, self % nbands
595  if (latitude < self % north(band)) exit
596 end do
597 b_matrix(:,:) = self % store(:,:,band)
598 b_inverse(:,:) = self % inverse(:,:,band)
599 b_sigma(:) = self % sigma(:,band)
600 
601 ! This has been left in for future development
602 !! Use errors associated with microwave emissivity atlas
603 !if (profindex % mwemiss(1) > 0) then
604 !
605 ! ! Atlas uncertainty stored in Ob % MwEmErrAtlas, use this to scale each
606 ! ! row/column of the B matrix block.
607 ! ! The default B matrix, see e.g. file ATOVS_Bmatrix_43, contains error
608 ! ! covariances representing a global average. Here, those elements are scaled
609 ! ! by a factor MwEmissError/SQRT(diag(B_matrix)) for each channel.
610 !
611 ! do i = profindex % mwemiss(1), profindex % mwemiss(2)
612 ! MwEmissError = Ob % MwEmErrAtlas(i - profindex % mwemiss(1) + 1)
613 ! if (MwEmissError > 1.0E-4 .and. MwEmissError < 1.0) then
614 ! bscale = MwEmissError / sqrt (B_matrix(i,i))
615 ! B_matrix(:,i) = B_matrix(:,i) * bscale
616 ! B_matrix(i,:) = B_matrix(i,:) * bscale
617 ! B_inverse(:,i) = B_inverse(:,i) / bscale
618 ! B_inverse(i,:) = B_inverse(i,:) / bscale
619 ! B_sigma(i) = B_sigma(i) * bscale
620 ! end if
621 ! end do
622 !
623 !end if
624 !
625 !! Scale the background skin temperature error covariances over land
626 !if (Ob % Surface == RTland .and. SkinTempErrorLand >= 0.0) then
627 !
628 ! bscale = SkinTempErrorLand / sqrt (B_matrix(profindex % tstar,profindex % tstar))
629 ! B_matrix(:,profindex % tstar) = B_matrix(:,profindex % tstar) * bscale
630 ! B_matrix(profindex % tstar,:) = B_matrix(profindex % tstar,:) * bscale
631 ! B_inverse(:,profindex % tstar) = B_inverse(:,profindex % tstar) / bscale
632 ! B_inverse(profindex % tstar,:) = B_inverse(profindex % tstar,:) / bscale
633 ! B_sigma(profindex % tstar) = B_sigma(profindex % tstar) * bscale
634 !
635 !end if
636 
638 
639 ! ------------------------------------------------------------------------------------------------
640 !> Create a subset of the b-matrix. Used for testing.
641 !!
642 !! \author Met Office
643 !!
644 !! \date 09/06/2020: Created
645 !!
646 subroutine rttovonedvarcheck_create_fields_in(fields_in, variables, qtotal_flag)
647 
648 implicit none
649 
650 integer, allocatable, intent(inout) :: fields_in(:) !< Array to specify fields used
651 character(len=*), intent(in) :: variables(:) !< Model variables in B matrix
652 logical, intent(in) :: qtotal_flag !< Flag for qtotal
653 
654 character(len=MAXVARLEN) :: varname
655 integer :: jvar
656 integer :: nmvars, counter
657 character(len=200) :: message
658 logical :: clw_present = .false.
659 logical :: ciw_present = .false.
660 
661 call fckit_log % info("rttovonedvarcheck_create_fields_in: starting")
662 
663 ! Which fields are being used from b matrix file - temporary until rttov can handle all fields
664 nmvars = size(variables)
665 allocate(fields_in(nmvars))
666 fields_in(:) = 0
667 
668 counter = 0
669 do jvar = 1, nmvars
670 
671  counter = counter + 1
672  varname = variables(jvar)
673 
674  select case (trim(varname))
675 
676  case (var_ts)
677  fields_in(counter) = 1 ! air_temperature
678 
679  case (var_q)
680  if (qtotal_flag) then
681  fields_in(counter) = 10 ! total water profile
682  else
683  fields_in(counter) = 2 ! water profile
684  end if
685 
686  case(var_sfc_t2m)
687  fields_in(counter) = 3 ! 2m air_temperature
688 
689  case(var_sfc_q2m)
690  fields_in(counter) = 4 ! 2m specific_humidity
691 
692  case(var_sfc_tskin)
693  fields_in(counter) = 5 ! surface skin temperature
694 
695  case(var_sfc_p2m)
696  fields_in(counter) = 6 ! surface air pressure
697 
698  ! 7 - o3total is not implmented yet
699  ! 8 - not used is not implmented yet
700 
701  case (var_clw)
702  clw_present = .true.
703  if (.NOT. qtotal_flag) then
704  call abor1_ftn("rttovonedvarcheck not setup for independent clw yet")
705  end if
706 
707  case (var_sfc_u10, var_sfc_v10)
708  fields_in(counter) = 11 ! surface wind speed
709 
710  ! 12 - o3profile is not implmented yet
711  ! 13 - lwp (liquid water path) is not implmented yet
712 
713  case ("surface_emissivity") ! microwave emissivity
714  call abor1_ftn("rttovonedvarcheck not setup for surface surface_emissivity yet")
715 
716  case (var_cli)
717  ciw_present = .true.
718  if (.NOT. qtotal_flag) then
719  call abor1_ftn("rttovonedvarcheck not setup for independent ciw yet")
720  end if
721 
722  case ("cloud_top_pressure")
723  call abor1_ftn("rttovonedvarcheck not setup for cloud retrievals yet")
724 
725  case ("effective_cloud_fraction") ! effective cloud fraction
726  call abor1_ftn("rttovonedvarcheck not setup for cloud retrievals yet")
727 
728  case ("emissivity_pc") ! emissivity prinipal components
729  call abor1_ftn("rttovonedvarcheck not setup for pc emissivity yet")
730 
731  ! 19 cloud fraction profile - not currently used
732 
733  case default
734  write(message,*) trim(varname)," not implemented yet in rttovonedvarcheck Covariance"
735  call abor1_ftn(message)
736 
737  end select
738 
739 end do
740 
741 ! Check clw and ciw are both in the list of required variables
742 if (qtotal_flag .and. ((.not. clw_present) .or. (.not. ciw_present))) then
743  call abor1_ftn("rttovonedvarcheck using qtotal but clw or ciw not in variables")
744 end if
745 
747 
748 ! ------------------------------------------------------------------------------------------------
749 
real(kind_real), parameter, public one
real(kind_real), parameter, public zero
Fortran module containing the full b-matrix data type and methods for the 1D-Var.
integer, parameter, public ufo_metoffice_fieldtype_cloudtopp
single-level cloud top pressure
integer, parameter, public ufo_metoffice_fieldtype_q
specific humidity profile
integer, parameter, public ufo_metoffice_fieldtype_lwp
liquid water path - not currently setup
integer, parameter, public ufo_metoffice_fieldtype_q2
surface spec humidity
integer, parameter, public ufo_metoffice_fieldtype_qi
ice profile - not currently setup
subroutine ufo_metoffice_bmatrixstatic_reset(self, latitude, b_matrix, b_inverse, b_sigma)
Routine to create error covariances for a single observation.
integer, parameter, public ufo_metoffice_fieldtype_t
temperature
subroutine rttovonedvarcheck_covariance_getbmatrix(self, fileunit, b_elementsused, fieldlist)
Routine to initialize the 1D-Var B-matrix.
subroutine ufo_metoffice_bmatrixstatic_delete(self)
Routine to delete and squash the 1D-Var B-matrix.
subroutine ufo_metoffice_bmatrixstatic_setup(self, variables, filepath, qtotal_flag)
Routine to read and setup the 1D-Var B-matrix.
integer, parameter, public ufo_metoffice_fieldtype_t2
surface air temperature
subroutine rttovonedvarcheck_create_fields_in(fields_in, variables, qtotal_flag)
Create a subset of the b-matrix. Used for testing.
integer, parameter, public ufo_metoffice_fieldtype_emisspc
emissivity prinipal components - not currently setup
integer, parameter, public ufo_metoffice_fieldtype_qt
total water profile
integer, parameter, public ufo_metoffice_fieldtype_ql
liquid water profile - not currently setup
character(len= *), dimension(nfieldtypes_ukmo), parameter, public ufo_metoffice_fieldtype_text
integer, parameter, public ufo_metoffice_fieldtype_not_used
not currently in use - not currently setup
integer, parameter, public ufo_metoffice_fieldtype_windspeed
surface wind speed
integer, parameter, public nfieldtypes_ukmo
number of fieldtypes
subroutine rttovonedvarcheck_covariance_initbmatrix(self)
Routine to initialize the 1D-Var B-matrix.
integer, parameter, public ufo_metoffice_fieldtype_cf
cloud fraction profile - not currently setup
integer, parameter, public ufo_metoffice_fieldtype_o3profile
ozone - not currently setup
integer, parameter, public ufo_metoffice_fieldtype_mwemiss
microwave emissivity - not currently setup
integer, parameter, public ufo_metoffice_fieldtype_o3total
total column ozone - not currently setup
integer, parameter, public ufo_metoffice_fieldtype_cloudfrac
effective cloud fraction
integer, parameter, public ufo_metoffice_fieldtype_pstar
surface pressure
integer, parameter, public ufo_metoffice_fieldtype_tstar
surface skin temperature
Fortran module with various useful routines.
integer function, public ufo_utils_iogetfreeunit()
Find a free file unit.
subroutine, public invertmatrix(n, m, a, status, matrix)
character(len=maxvarlen), parameter, public var_sfc_emiss
character(len=maxvarlen), parameter, public var_cldfrac
character(len=maxvarlen), parameter, public var_clw
character(len=maxvarlen), parameter, public var_sfc_v10
character(len=maxvarlen), parameter, public var_q
character(len=maxvarlen), parameter, public var_sfc_u10
character(len=maxvarlen), parameter, public var_sfc_q2m
character(len=maxvarlen), parameter, public var_sfc_tskin
character(len=maxvarlen), parameter, public var_sfc_p2m
character(len=maxvarlen), parameter, public var_ts
character(len=maxvarlen), parameter, public var_cli
character(len=maxvarlen), parameter, public var_sfc_wspeed
character(len=maxvarlen), parameter, public var_sfc_t2m