UFO
ufo_rttovonedvarcheck_rsubmatrix_mod.f90
Go to the documentation of this file.
1 ! (C) British Crown Copyright 2017-2018 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 derived type to hold data for the observation covariance
7 
9 
10 use kinds
13 
14 implicit none
15 private
16 
18 
19  integer :: nchans !< number of channels used in current r matrix
20  real(kind_real), allocatable :: matrix(:,:) !< full matrix
21  real(kind_real), allocatable :: inv_matrix(:,:) !< inverse full matrix
22  real(kind_real), allocatable :: diagonal(:) !< diagonal matrix
23  logical :: diagonal_flag !< flag to use diagonal r-matrix
24  logical :: full_flag !< flag to use full r-matrix
25 
26 contains
27  procedure :: setup => rsubmatrix_setup
28  procedure :: delete => rsubmatrix_delete
29  procedure :: info => rsubmatrix_print
30  procedure :: multiply_vector => rsubmatrix_multiply
31  procedure :: multiply_matrix => rsubmatrix_multiply_matrix
32  procedure :: multiply_inverse_vector => rsubmatrix_inv_multiply
33  procedure :: multiply_inverse_matrix => rsubmatrix_multiply_inv_matrix
34  procedure :: add_to_matrix => rsubmatrix_add_to_u
35  procedure :: multiply_factor_by_stdev => rsubmatrix_multiply_factor_by_stdev
36 
38 
39 ! ------------------------------------------------------------------------------
40 contains
41 ! ------------------------------------------------------------------------------
42 !> Setup for the r sub-matrix
43 !!
44 !! \author Met Office
45 !!
46 !! \date 09/06/2020: Created
47 !!
48 subroutine rsubmatrix_setup(self, nchans, channels, full_rmatrix)
49 
50 implicit none
51 class(ufo_rttovonedvarcheck_rsubmatrix), intent(inout) :: self
52 integer, intent(in) :: nchans
53 integer, intent(in) :: channels(:)
54 type(ufo_metoffice_rmatrixradiance), intent(in) :: full_rmatrix
55 
56 character(len=*), parameter :: &
57  routinename = "rsubmatrix_setup"
58 character(len=max_string) :: err_msg
59 integer :: ii, ff, ss
60 character(len=max_string) :: mat_type
61 
62 self % nchans = nchans
63 self % full_flag = .false.
64 self % diagonal_flag = .false.
65 
66 ! Get r matrix type from full matrix
67 if (full_rmatrix % rtype == 1) then
68  mat_type = "full"
69 else if (full_rmatrix % rtype == 2) then
70  mat_type = "diagonal"
71 else
72  call abor1_ftn('Unknown r matrix type')
73 end if
74 
75 ! Setup correct r matrix
76 select case (trim(mat_type))
77  case ("full")
78  ! full rmatrix not setup yet but in principle this is
79  ! a start as to how it would be initialised.
80  !allocate(self % matrix(nchans,nchans))
81  !allocate(self % inv_matrix(nchans,nchans))
82  !self % matrix(:,:) = 0.0_kind_real
83  !self % inv_matrix(:,:) = 0.0_kind_real
84  !self % full_flag = .true.
85  !do ii=1,nchans
86  ! self % matrix(ii,ii) = obs_error(ii) * obs_error(ii)
87  ! self % inv_matrix(ii,ii) = 1.0_kind_real / &
88  ! (obs_error(ii) * obs_error(ii))
89  !end do
90  call abor1_ftn('full r matrix under development - use a diagonal')
91  case ("diagonal")
92  allocate(self % diagonal(nchans))
93  self % diagonal(:) = 0.0_kind_real
94  self % diagonal_flag = .true.
95 
96  do ff=1,full_rmatrix % nchans
97  do ss=1,self % nchans
98  if (full_rmatrix % channels(ff) == channels(ss)) then
99  self % diagonal(ss) = full_rmatrix % errors(ff) * full_rmatrix % errors(ff)
100  end if
101  end do
102  end do
103  case default
104  call abor1_ftn('Unknown r matrix type')
105 end select
106 
107 end subroutine rsubmatrix_setup
108 
109 ! ------------------------------------------------------------------------------
110 !> Delete method for the r_matrix
111 !!
112 !! \author Met Office
113 !!
114 !! \date 09/06/2020: Created
115 !!
116 subroutine rsubmatrix_delete(self)
117 
118 implicit none
119 class(ufo_rttovonedvarcheck_rsubmatrix), intent(inout) :: self !< R mtrix structure
120 
121 if (allocated(self % matrix)) deallocate(self % matrix)
122 if (allocated(self % inv_matrix)) deallocate(self % inv_matrix)
123 if (allocated(self % diagonal)) deallocate(self % diagonal)
124 
125 end subroutine rsubmatrix_delete
126 
127 ! ------------------------------------------------------------------------------
128 !> Multiply a vector by the r-matrix
129 !!
130 !! \author Met Office
131 !!
132 !! \date 09/06/2020: Created
133 !!
134 subroutine rsubmatrix_multiply(self,xin,xout)
135 
136 implicit none
137 class(ufo_rttovonedvarcheck_rsubmatrix), intent(in) :: self
138 real(kind_real), intent(in) :: xin(:)
139 real(kind_real), intent(inout) :: xout(:)
140 
141 if (size(xout) /= self % nchans) then
142  call abor1_ftn("rsubmatrix_multiply: arrays incompatible sizes")
143 end if
144 
145 ! Full R matrix
146 if (self % full_flag) xout(:) = matmul(xin(:), self % matrix(:,:))
147 
148 ! Diagonal R matrix
149 if (self % diagonal_flag) xout(:) = xin(:) * self % diagonal(:)
150 
151 end subroutine rsubmatrix_multiply
152 
153 ! ------------------------------------------------------------------------------
154 !> Multiply a matrix by the r-matrix
155 !!
156 !! \author Met Office
157 !!
158 !! \date 09/06/2020: Created
159 !!
160 subroutine rsubmatrix_multiply_matrix(self,xin,xout)
161 
162 implicit none
163 class(ufo_rttovonedvarcheck_rsubmatrix), intent(in) :: self
164 real(kind_real), intent(in) :: xin(:,:)
165 real(kind_real), intent(inout) :: xout(:,:)
166 
167 integer :: ii
168 
169 if (size(xout, 2) /= self % nchans) then
170  call abor1_ftn("rsubmatrix_multiply_matrix: arrays incompatible sizes")
171 end if
172 
173 ! Full R matrix
174 if (self % full_flag) xout = matmul(xin, self % matrix(:,:))
175 
176 ! Diagonal R matrix
177 if (self % diagonal_flag) then
178  do ii=1, self % nchans
179  xout(:,ii) = xin(:,ii) * self % diagonal(ii)
180  end do
181 end if
182 
183 end subroutine rsubmatrix_multiply_matrix
184 
185 ! ------------------------------------------------------------------------------
186 !> Multiply a vector by the inverse of the r-matrix
187 !!
188 !! \author Met Office
189 !!
190 !! \date 09/06/2020: Created
191 !!
192 subroutine rsubmatrix_inv_multiply(self,xin,xout)
193 
194 implicit none
195 class(ufo_rttovonedvarcheck_rsubmatrix), intent(in) :: self
196 real(kind_real), intent(in) :: xin(:)
197 real(kind_real), intent(inout) :: xout(:)
198 
199 if (size(xout) /= self % nchans) then
200  call abor1_ftn("rsubmatrix_inv_multiply: arrays incompatible sizes")
201 end if
202 
203 ! Full R matrix
204 if (self % full_flag) xout(:) = matmul(xin(:), self % inv_matrix(:,:))
205 
206 ! Diagonal R matrix
207 if (self % diagonal_flag) xout(:) = xin(:) / self % diagonal(:)
208 
209 end subroutine rsubmatrix_inv_multiply
210 
211 ! ------------------------------------------------------------------------------
212 !> Multiply a matrix by the inverse of the r-matrix
213 !!
214 !! \author Met Office
215 !!
216 !! \date 09/06/2020: Created
217 !!
218 subroutine rsubmatrix_multiply_inv_matrix(self,xin,xout)
219 
220 implicit none
221 class(ufo_rttovonedvarcheck_rsubmatrix), intent(in) :: self
222 real(kind_real), intent(in) :: xin(:,:)
223 real(kind_real), intent(out) :: xout(:,:)
224 
225 integer :: ii
226 
227 if (size(xout, 2) /= self % nchans) then
228  call abor1_ftn("rsubmatrix_multiply_inv_matrix: arrays incompatible sizes")
229 end if
230 
231 ! Full R matrix
232 if (self % full_flag) xout = matmul(xin, self % inv_matrix(:,:))
233 
234 ! Diagonal R matrix
235 if (self % diagonal_flag) then
236  do ii=1, self % nchans
237  xout(:,ii) = xin(:,ii) / self % diagonal(ii)
238  end do
239 end if
240 
241 end subroutine rsubmatrix_multiply_inv_matrix
242 
243 ! ------------------------------------------------------------------------------
244 !> Add a matrix to the r-matrix
245 !!
246 !! \author Met Office
247 !!
248 !! \date 09/06/2020: Created
249 !!
250 subroutine rsubmatrix_add_to_u(self,uin,uout)
251 
252 implicit none
253 class(ufo_rttovonedvarcheck_rsubmatrix), intent(in) :: self
254 real(kind_real), intent(in) :: uin(:,:)
255 real(kind_real), intent(inout) :: uout(:,:)
256 
257 integer :: ii
258 
259 if (size(uout) /= self % nchans * self % nchans) then
260  call abor1_ftn("rsubmatrix_add_to_u: arrays incompatible sizes")
261 end if
262 
263 ! Full R matrix
264 if (self % full_flag) uout = uin + self % matrix
265 
266 ! Diagonal R matrix
267 if (self % diagonal_flag) then
268  do ii=1, self % nchans
269  uout(ii,ii) = uin(ii,ii) + self % diagonal(ii)
270  end do
271 end if
272 
273 end subroutine rsubmatrix_add_to_u
274 
275 ! ------------------------------------------------------------------------------
276 !> Multiply a vector by the r-matrix diagonal standard deviation
277 !!
278 !! \author Met Office
279 !!
280 !! \date 16/06/2021: Created
281 !!
282 subroutine rsubmatrix_multiply_factor_by_stdev(self,factor,xout)
283 
284 implicit none
285 class(ufo_rttovonedvarcheck_rsubmatrix), intent(in) :: self
286 real(kind_real), intent(in) :: factor
287 real(kind_real), intent(inout) :: xout(:)
288 
289 integer :: ii
290 
291 if (size(xout) /= self % nchans) then
292  call abor1_ftn("rsubmatrix_multiply_factor_by_stdev: arrays incompatible sizes")
293 end if
294 
295 ! Full R matrix
296 if (self % full_flag) then
297  do ii=1, self % nchans
298  xout(ii) = factor * sqrt(self % matrix(ii,ii))
299  end do
300 end if
301 
302 ! Diagonal R matrix
303 if (self % diagonal_flag) xout(:) = factor * sqrt(self % diagonal(:))
304 
306 
307 ! ------------------------------------------------------------------------------
308 !> Print the contents of the r-matrix
309 !!
310 !! \author Met Office
311 !!
312 !! \date 09/06/2020: Created
313 !!
314 subroutine rsubmatrix_print(self)
315 
316 implicit none
317 class(ufo_rttovonedvarcheck_rsubmatrix), intent(in) :: self
318 
319 integer :: ii
320 
321 if (self % full_flag) then
322 
323  write(*,*) "Full R matrix used printing diagonal"
324  write(*,*) "nchans = ",self % nchans
325  write(*,*) "Matrix diagonal elements = "
326  do ii = 1, self % nchans
327  write(*,*) self % matrix(ii,ii)
328  end do
329  write(*,*) "Inverse Matrix diagonal elements = "
330  do ii = 1, self % nchans
331  write(*,*) self % inv_matrix(ii,ii)
332  end do
333 
334 end if
335 
336 if (self % diagonal_flag) then
337 
338  write(*,*) "Diagonal R matrix used"
339  write(*,*) "nchans = ",self % nchans
340  write(*,*) "Diagonal = ",self % diagonal(:)
341 
342 end if
343 
344 end subroutine rsubmatrix_print
345 
Fortran derived type to hold data for the observation covariance.
Fortran module constants used throughout the rttovonedvarcheck filter.
integer, parameter, public max_string
maximum string length
Fortran derived type to hold data for the observation covariance.
subroutine rsubmatrix_inv_multiply(self, xin, xout)
Multiply a vector by the inverse of the r-matrix.
subroutine rsubmatrix_multiply_factor_by_stdev(self, factor, xout)
Multiply a vector by the r-matrix diagonal standard deviation.
subroutine rsubmatrix_multiply(self, xin, xout)
Multiply a vector by the r-matrix.
subroutine rsubmatrix_multiply_inv_matrix(self, xin, xout)
Multiply a matrix by the inverse of the r-matrix.
subroutine rsubmatrix_delete(self)
Delete method for the r_matrix.
subroutine rsubmatrix_setup(self, nchans, channels, full_rmatrix)
Setup for the r sub-matrix.
subroutine rsubmatrix_multiply_matrix(self, xin, xout)
Multiply a matrix by the r-matrix.
subroutine rsubmatrix_print(self)
Print the contents of the r-matrix.
subroutine rsubmatrix_add_to_u(self, uin, uout)
Add a matrix to the r-matrix.