14 use fckit_log_module,
only: fckit_log
16 use missing_values_mod
24 INTEGER :: origctr = 0
28 INTEGER :: num_heights
31 REAL,
POINTER :: height(:)
32 REAL,
POINTER :: frac_err(:)
42 filename, & ! The name of the file to be read in
43 Rmatrix, & ! The R matrices read from the files
49 INTEGER,
INTENT(IN) :: max_mats
50 CHARACTER(LEN=*),
INTENT(IN) :: filename
51 TYPE (
rmatrix_type),
ALLOCATABLE,
INTENT(OUT) :: rmatrix(:)
52 INTEGER,
INTENT(OUT) :: r_num_mats
55 CHARACTER(len=*),
PARAMETER :: routinename =
"ufo_roobserror_getrmatrix"
59 CHARACTER(len=200) :: errormessage
60 INTEGER :: return_code
69 OPEN(unit=fileunit, file=filename, action=
'READ', status=
'OLD', iostat=return_code)
70 if (return_code /= 0)
then
71 WRITE(errormessage,
'(3A,I0)')
"Error opening ", trim(filename), &
72 ", return code = ", return_code
73 call abor1_ftn(errormessage)
82 IF (r_num_mats >= max_mats)
THEN
83 WRITE (errormessage,
'(A,I0,A,I0)') &
84 "Trying to read too many R-matrices ", &
85 r_num_mats,
" out of ", max_mats
86 CALL abor1_ftn(errormessage)
90 temp_rmat(r_num_mats + 1), &
92 IF (return_code < 0)
THEN
95 ELSE IF (return_code > 0)
THEN
96 WRITE(errormessage,
'(A,I0)') &
97 "Trouble reading R-matrix namelist, error number ", &
99 CALL abor1_ftn(errormessage)
101 r_num_mats = r_num_mats + 1
109 ALLOCATE (rmatrix(r_num_mats))
122 IF (rmatrix(i) % max_height /= rmatrix(1) % max_height)
THEN
123 WRITE (errormessage,
'(A,I0,A,I0,A,I0)') &
124 "All the R-matrices should have the same value for max_height Rmatrix(", &
125 i,
") % max_height = ", rmatrix(i) % max_height, &
126 ", RMatrix(1) % max_height = ", rmatrix(1) % max_height
127 CALL abor1_ftn(errormessage)
142 Rmatrix, & ! The R matrices read from the files
148 INTEGER,
INTENT(IN) :: fileunit
149 TYPE (Rmatrix_type),
INTENT(OUT) :: Rmatrix
150 INTEGER,
INTENT(OUT) :: return_code
153 CHARACTER(len=*),
PARAMETER :: RoutineName =
"ufo_roobserror_read_rmatrix"
154 CHARACTER(len=200) :: ErrorMessage
156 INTEGER :: max_height
159 REAL :: obs_errors(600)
165 namelist / gpsro_ob_error / &
178 satid = missing_value(satid)
179 origc = missing_value(origc)
181 heights = missing_value(heights(1))
182 obs_errors = missing_value(obs_errors(1))
184 av_temp = missing_value(av_temp)
185 latitude = missing_value(latitude)
190 READ (fileunit, nml = gpsro_ob_error, iostat = return_code)
191 IF (return_code == 0)
THEN
193 rmatrix % num_heights = count(heights /= missing_value(heights(1)))
194 IF (count(obs_errors /= missing_value(obs_errors(1))) /= rmatrix % num_heights)
THEN
195 WRITE (errormessage,
'(A,I0,1X,I0)')
"Counts do not match ", &
196 count(obs_errors /= missing_value(obs_errors(1))), rmatrix % num_heights
197 CALL abor1_ftn(errormessage)
199 ALLOCATE (rmatrix % height(1:rmatrix % num_heights))
200 ALLOCATE (rmatrix % frac_err(1:rmatrix % num_heights))
201 rmatrix % height(:) = pack(heights, heights /= missing_value(heights(1)))
202 rmatrix % frac_err(:) = pack(obs_errors, obs_errors /= missing_value(obs_errors(1)))
203 rmatrix % frac_err(:) = rmatrix % frac_err(:)
206 rmatrix % av_temp = av_temp
207 rmatrix % max_height = max_height
208 rmatrix % latitude = latitude
209 rmatrix % satid = satid
210 rmatrix % origctr = origc
211 rmatrix % clen = clen
212 rmatrix % min_error = min_error
239 INTEGER,
INTENT(IN) :: satid
240 INTEGER,
INTENT(IN) :: origc
241 REAL,
INTENT(IN) :: av_temp
242 INTEGER,
INTENT(IN) :: R_num_sats
243 TYPE (Rmatrix_type),
INTENT(IN) :: RMatrix_list(R_num_sats)
244 TYPE (Rmatrix_type),
INTENT(OUT) :: out_matrix
247 CHARACTER(len=*),
PARAMETER :: RoutineName =
"ufo_roobserror_interpolate_rmatrix"
249 INTEGER :: lower_match
250 INTEGER :: upper_match
252 CHARACTER(len=200) :: ErrorMessage
253 REAL,
ALLOCATABLE :: interp_errors(:)
258 IF (satid == rmatrix_list(i) % satid .AND. &
259 origc == rmatrix_list(i) % origctr)
THEN
260 IF (rmatrix_list(i) % av_temp /= missing_value(rmatrix_list(i) % av_temp))
THEN
261 IF (rmatrix_list(i) % av_temp > av_temp)
THEN
262 IF (upper_match == 0)
THEN
264 ELSE IF (rmatrix_list(i) % av_temp < rmatrix_list(upper_match) % av_temp)
THEN
268 IF (lower_match == 0)
THEN
270 ELSE IF (rmatrix_list(i) % av_temp > rmatrix_list(lower_match) % av_temp)
THEN
278 IF (upper_match > 0)
THEN
279 IF (lower_match > 0)
THEN
280 WRITE (errormessage,
'(A,3F10.2)')
"Interpolating between locations.. ", &
281 rmatrix_list(lower_match) % av_temp, &
282 av_temp, rmatrix_list(upper_match) % av_temp
283 call fckit_log % debug(errormessage)
284 weight = (av_temp - rmatrix_list(lower_match) % av_temp) / &
285 (rmatrix_list(upper_match) % av_temp - rmatrix_list(lower_match) % av_temp)
287 out_matrix % num_heights = rmatrix_list(lower_match) % num_heights
288 ALLOCATE (out_matrix % height(1:out_matrix % num_heights))
289 ALLOCATE (out_matrix % frac_err(1:out_matrix % num_heights))
290 ALLOCATE (interp_errors(1:out_matrix % num_heights))
292 rmatrix_list(lower_match) % height, &
293 rmatrix_list(upper_match) % num_heights, &
294 rmatrix_list(upper_match) % height, &
295 rmatrix_list(upper_match) % frac_err, &
297 out_matrix % height(:) = rmatrix_list(lower_match) % height(:)
298 out_matrix % frac_err(:) = weight * interp_errors + &
299 (1 - weight) * rmatrix_list(lower_match) % frac_err
301 out_matrix % av_temp = av_temp
304 out_matrix % max_height = rmatrix_list(lower_match) % max_height
305 out_matrix % satid = satid
306 out_matrix % origctr = origc
307 out_matrix % clen = weight * rmatrix_list(upper_match) % clen + &
308 (1 - weight) * rmatrix_list(lower_match) % clen
309 out_matrix % min_error = weight * rmatrix_list(upper_match) % min_error + &
310 (1 - weight) * rmatrix_list(lower_match) % min_error
311 out_matrix % latitude = missing_value(out_matrix % latitude)
317 IF (lower_match > 0)
THEN
321 WRITE (errormessage,
'(A,I0,1X,I0,1X)')
"Did not match any matrices ", satid, origc
322 CALL fckit_log % warning(errormessage)
348 INTEGER,
INTENT(IN) :: target_nheights
349 REAL,
INTENT(IN) :: target_heights(1:target_nheights)
350 INTEGER,
INTENT(IN) :: source_nheights
351 REAL,
INTENT(IN) :: source_heights(1:source_nheights)
352 REAL,
INTENT(IN) :: source_values(1:source_nheights)
353 REAL,
INTENT(OUT) :: output_values(1:target_nheights)
356 CHARACTER(len=*),
PARAMETER :: RoutineName =
"ufo_roobserror_interpolate_heights"
359 LOGICAL :: MatchFound
362 DO i = 1, target_nheights
363 IF (all(target_heights(i) < source_heights))
THEN
365 output_values(i) = source_values(1)
369 DO j = 1, source_nheights - 1
370 IF (target_heights(i) >= source_heights(j) .AND. &
371 target_heights(i) < source_heights(j + 1))
THEN
379 weight = (target_heights(i) - source_heights(j)) / &
380 (source_heights(j + 1) - source_heights(j))
381 output_values(i) = weight * source_values(j + 1) + &
382 (1 - weight) * source_values(j)
386 output_values(i) = source_values(source_nheights)
407 TYPE (Rmatrix_type),
INTENT(IN) :: in_mat
408 TYPE (Rmatrix_type),
INTENT(OUT) :: out_mat
411 CHARACTER(len=*),
PARAMETER :: RoutineName =
"ufo_roobserror_copy_rmatrix"
413 out_mat % num_heights = in_mat % num_heights
414 ALLOCATE (out_mat % height(out_mat % num_heights))
415 ALLOCATE (out_mat % frac_err(out_mat % num_heights))
416 out_mat % height(:) = in_mat % height(:)
417 out_mat % frac_err(:) = in_mat % frac_err(:)
419 out_mat % av_temp = in_mat % av_temp
420 out_mat % max_height = in_mat % max_height
421 out_mat % latitude = in_mat % latitude
422 out_mat % satid = in_mat % satid
423 out_mat % origctr = in_mat % origctr
424 out_mat % clen = in_mat % clen
425 out_mat % min_error = in_mat % min_error
446 INTEGER,
INTENT(IN) :: satid
447 INTEGER,
INTENT(IN) :: origc
448 REAL(kind_real),
INTENT(IN) :: latitude
449 INTEGER,
INTENT(IN) :: R_num_sats
450 TYPE (Rmatrix_type),
INTENT(IN) :: RMatrix_list(1:R_num_sats)
451 TYPE (Rmatrix_type),
INTENT(OUT) :: out_matrix
454 CHARACTER(len=*),
PARAMETER :: RoutineName =
"ufo_roobserror_findnearest_rmatrix"
456 INTEGER :: closest_match
457 CHARACTER(len=200) :: ErrorMessage
461 IF (satid == rmatrix_list(i) % satid .AND. &
462 origc == rmatrix_list(i) % origctr)
THEN
463 IF (rmatrix_list(i) % latitude /= missing_value(rmatrix_list(i) % latitude))
THEN
464 IF (closest_match < 1)
THEN
466 ELSE IF (abs(latitude - rmatrix_list(i) % latitude) < &
467 abs(latitude - rmatrix_list(closest_match) % latitude))
THEN
474 IF (closest_match > 0)
THEN
478 WRITE (errormessage,
'(A,I0,1X,I0)')
"Did not match any matrices ", satid, origc
479 CALL fckit_log % warning(errormessage)
Fortran module for utility routines used in calculating the observation uncertainties,...
subroutine ufo_roobserror_read_rmatrix(fileunit, Rmatrix, return_code)
subroutine ufo_roobserror_copy_rmatrix(in_mat, out_mat)
subroutine, public ufo_roobserror_getrmatrix(max_mats, filename, Rmatrix, R_num_mats)
subroutine ufo_roobserror_findnearest_rmatrix(satid, origc, latitude, R_num_sats, Rmatrix_list, out_matrix)
subroutine ufo_roobserror_interpolate_rmatrix(satid, origc, av_temp, R_num_sats, Rmatrix_list, out_matrix)
subroutine ufo_roobserror_interpolate_heights(target_nheights, target_heights, source_nheights, source_heights, source_values, output_values)
Fortran module with various useful routines.
integer function, public ufo_utils_iogetfreeunit()
Find a free file unit.