10 use fckit_log_module,
only : fckit_log
24 integer,
pointer :: fields(:,:)
25 real(kind=kind_real),
pointer :: store(:,:,:)
26 real(kind=kind_real),
pointer :: inverse(:,:,:)
27 real(kind=kind_real),
pointer :: sigma(:,:)
28 real(kind=kind_real),
pointer :: proxy(:,:)
29 real(kind=kind_real),
pointer :: inv_proxy(:,:)
30 real(kind=kind_real),
pointer :: sigma_proxy(:,:)
31 real(kind=kind_real),
pointer :: south(:)
32 real(kind=kind_real),
pointer :: north(:)
53 integer,
parameter,
public :: &
81 'ozone (total column)', &
82 '[unused field type] ', &
87 'liquid water path ', &
90 'cloud top pressure ', &
108 character(len=*),
intent(in) :: variables(:)
109 character(len=*),
intent(in) :: filepath
110 logical,
intent(in) :: qtotal_flag
112 logical :: file_exists
114 integer,
allocatable :: fields_in(:)
115 real(kind=kind_real) :: t1,t2
116 character(len=:),
allocatable :: str
117 logical :: testing = .false.
121 call fckit_log % info(
"ufo_metoffice_bmatrixstatic_setup start")
126 inquire(file=trim(filepath), exist=file_exists)
127 if (file_exists)
then
129 open(unit = fileunit, file = trim(filepath))
137 close(unit = fileunit)
138 call fckit_log % info(
"rttovonedvarcheck bmatrix file exists and read in")
140 call abor1_ftn(
"rttovonedvarcheck bmatrix file not found")
146 do ii = 1,
size(self % fields(:,1))
148 do jj = 1,
size(fields_in)
149 if (self % fields(ii,1) == fields_in(jj)) match = .true.
151 if (.not. match)
then
153 call abor1_ftn(
"rttovonedvarcheck not all the model data is available for the b-matrix")
157 write(
message,*)
"ufo_metoffice_bmatrixstatic_setup cpu time = ",(t2-t1)
176 character(len=*),
parameter :: RoutineName =
"ufo_metoffice_bmatrixstatic_delete"
178 self % status = .false.
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 )
209 character(len=*),
parameter :: routinename =
"rttovonedvarcheck_covariance_InitBmatrix"
211 self % status = .false.
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 )
280 type (ufo_metoffice_bmatrixstatic),
intent(inout) :: self
281 integer,
intent(in) :: fileunit
282 integer,
optional,
intent(in) :: b_elementsused(:)
283 integer,
optional,
intent(inout) :: fieldlist(:)
286 character(len=*),
parameter :: routinename =
"rttovonedvarcheck_covariance_GetBmatrix"
290 integer :: readstatus
293 integer :: matrixsize
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(:)
320 read (fileunit,
'(a)') line
322 if (verify(line,
'#!') == 1)
then
334 read (fileunit, *) matrixsize, nbands, nbfields
335 if (nbfields > 0)
then
336 allocate (bfields(nbfields,2))
338 read (fileunit, *) bfields(i,1), bfields(i,2)
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:')
355 call fckit_log % debug(
message)
375 self % fields(:,:) = 0
376 self % status = .true.
381 if (
present (fieldlist))
then
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
395 nelements_total = nelements_total + bfields(j,2)
396 nelements = nelements + bfields(j,2)
402 nelements_total = nelements_total + bfields(j,2)
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)
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)
418 ' (fieldtype ' // trim(adjustl(fieldtype)) //
')'
419 call fckit_log % debug(
message)
421 write (
message,
'(a)')
'fieldtype ' // trim(adjustl(fieldtype)) // &
423 call fckit_log % debug(
message)
429 call fckit_log % debug(
'b matrix fields used to define the retrieval profile vector:')
432 call fckit_log % debug(
message)
437 fieldlist(1:nbfields) = bfields(1:nbfields,1)
438 if (nbfields <
size (fieldlist)) fieldlist(nbfields + 1:) = 0
440 else if (
present (b_elementsused))
then
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'
450 nelements = count(b_elementsused > 0 .and. b_elementsused <= matrixsize)
451 elementsused(1:nelements) = pack(b_elementsused, b_elementsused > 0 .and. b_elementsused <= matrixsize)
459 nelements = matrixsize
469 if (nbfields > 0) self % fields(1:nbfields,:) = bfields(1:nbfields,:)
470 self % nfields = nbfields
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
482 allocate (list(nbands))
483 allocate (bfromfile(matrixsize,matrixsize))
494 read (fileunit,
'(i3,2f8.2)', iostat = readstatus) band, southlimit, northlimit
495 if (readstatus < 0)
exit
500 read (fileunit,
'(5e16.8)' ) (bfromfile(i,j), i = 1, matrixsize)
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)
512 if (band > 0 .and. band <= nbands)
then
514 nmatrix = nmatrix + 1
515 if (nelements < matrixsize)
then
516 self % store(:,:,band) = &
517 bfromfile(elementsused(1:nelements),elementsused(1:nelements))
519 self % store(:,:,band) = bfromfile(:,:)
521 self % south(band) = southlimit
522 self % north(band) = northlimit
524 write (
message,
'(a,i0)')
'skipped matrix with band number ', band
525 call fckit_log % debug(
message)
534 allocate (self % sigma(nelements,nbands))
536 self % sigma(i,:) = sqrt(self % store(i,i,:))
543 allocate (self % inverse(nelements,nelements,nbands))
544 self % inverse(:,:,:) = self % store(:,:,:)
549 self % inverse(:,:,k), &
551 if (status /= 0)
then
552 call abor1_ftn(
"rttovonedvarcheck: bmatrix is not invertible")
560 if (nmatrix < nbands)
then
561 call abor1_ftn(
"rttovonedvarcheck: too few b matrices found in input file")
576 b_matrix, b_inverse, b_sigma )
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(:)
592 b_inverse(:,:) =
zero
594 do band = 1, self % nbands
595 if (latitude < self % north(band))
exit
597 b_matrix(:,:) = self % store(:,:,band)
598 b_inverse(:,:) = self % inverse(:,:,band)
599 b_sigma(:) = self % sigma(:,band)
650 integer,
allocatable,
intent(inout) :: fields_in(:)
651 character(len=*),
intent(in) :: variables(:)
652 logical,
intent(in) :: qtotal_flag
654 character(len=MAXVARLEN) :: varname
656 integer :: nmvars, counter
657 character(len=200) :: message
658 logical :: clw_present = .false.
659 logical :: ciw_present = .false.
661 call fckit_log % info(
"rttovonedvarcheck_create_fields_in: starting")
664 nmvars =
size(variables)
665 allocate(fields_in(nmvars))
671 counter = counter + 1
672 varname = variables(jvar)
674 select case (trim(varname))
677 fields_in(counter) = 1
680 if (qtotal_flag)
then
681 fields_in(counter) = 10
683 fields_in(counter) = 2
687 fields_in(counter) = 3
690 fields_in(counter) = 4
693 fields_in(counter) = 5
696 fields_in(counter) = 6
703 if (.NOT. qtotal_flag)
then
704 call abor1_ftn(
"rttovonedvarcheck not setup for independent clw yet")
708 fields_in(counter) = 11
713 case (
"surface_emissivity")
714 call abor1_ftn(
"rttovonedvarcheck not setup for surface surface_emissivity yet")
718 if (.NOT. qtotal_flag)
then
719 call abor1_ftn(
"rttovonedvarcheck not setup for independent ciw yet")
722 case (
"cloud_top_pressure")
723 call abor1_ftn(
"rttovonedvarcheck not setup for cloud retrievals yet")
725 case (
"effective_cloud_fraction")
726 call abor1_ftn(
"rttovonedvarcheck not setup for cloud retrievals yet")
728 case (
"emissivity_pc")
729 call abor1_ftn(
"rttovonedvarcheck not setup for pc emissivity yet")
734 write(message,*) trim(varname),
" not implemented yet in rttovonedvarcheck Covariance"
735 call abor1_ftn(message)
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")
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.
character(len=200) message
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