UFO
ufo_backgrounderrorvertinterp_mod.F90
Go to the documentation of this file.
1 ! (C) Copyright 2021 Met Office UK
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 
7 
8 use iso_c_binding, only: c_ptr
9 use oops_variables_mod, only: oops_variables
11 
12 contains
13 
14 !> For each obs diagnostic called <var>_background_error, where <var> belongs to the set of variable
15 !> names @p obsvars, fill this diagnostic with estimates of the background error of variable <var>
16 !> at observation locations.
17 subroutine ufo_backgrounderrorvertinterp_fillobsdiags(obs_vcoord_name, vcoord_name, &
18  geovals, obsspace, nlocs, obsvars, obsdiags)
19  use kinds, only: kind_real
20  use obsspace_mod, only: obsspace_get_db
24  implicit none
25 
26  ! Name of the variable with vertical coordinates of observations
27  character(len=*), intent(in) :: obs_vcoord_name
28  ! Name of the GeoVaL with the vertical coordinate levels to use for
29  ! interpolation of background errors
30  character(len=*), intent(in) :: vcoord_name
31  type(ufo_geovals), intent(in) :: geovals
32  type(c_ptr), value, intent(in) :: obsspace
33  integer, intent(in) :: nlocs
34  type(oops_variables), intent(in) :: obsvars
35  type(ufo_geovals), intent(inout) :: obsdiags
36 
37  logical :: use_ln
38  integer :: iobs, ivar
39  real(kind_real) :: obs_vcoord(nlocs)
40  type(ufo_geoval), pointer :: vcoord_profile, background_error_profile
41  real(kind_real) :: wf(nlocs)
42  integer :: wi(nlocs)
43  character(len=MAXVARLEN) :: varstr
44  integer :: lenvarstr
45  real(kind_real), allocatable :: interp_nodes(:)
46  real(kind_real) :: interp_point
47 
48  character(len=*), parameter :: suffix = "_background_error"
49 
50  ! Get vertical coordinate profiles from geovals
51  call ufo_geovals_get_var(geovals, vcoord_name, vcoord_profile)
52 
53  ! Get the observation vertical coordinates
54  call obsspace_get_db(obsspace, "MetaData", obs_vcoord_name, obs_vcoord)
55 
56  ! Use logarithmic interpolation if the vertical coordinate is air_pressure
57  ! or air_pressure_levels
58  use_ln = (obs_vcoord_name .eq. var_prs) .or. (obs_vcoord_name .eq. var_prsi)
59 
60  ! Calculate the interpolation weights
61  allocate(interp_nodes(vcoord_profile%nval))
62  do iobs = 1, nlocs
63  if (use_ln) then
64  interp_nodes = log(vcoord_profile%vals(:,iobs))
65  interp_point = log(obs_vcoord(iobs))
66  else
67  interp_nodes = vcoord_profile%vals(:,iobs)
68  interp_point = obs_vcoord(iobs)
69  end if
70  call vert_interp_weights(vcoord_profile%nval, interp_point, interp_nodes, &
71  wi(iobs), wf(iobs))
72  enddo
73 
74  do ivar = 1, obsdiags%nvar
75  varstr = obsdiags%variables(ivar)
76  lenvarstr = len_trim(varstr)
77 
78  ! We need to fill this diagnostic if:
79  ! (a) its name is long enough to be of the form `<var>_background_error`;
80  if (lenvarstr <= len(suffix)) cycle
81  ! (b) its name actually *is* of the form `<var>_background_error`;
82  if (varstr(lenvarstr - len(suffix)+1:lenvarstr) /= suffix) cycle
83  ! (c) <var> belongs to the list obsvars.
84  if (.not. obsvars%has(varstr(:lenvarstr - len(suffix)))) cycle
85 
86  ! All tests passed -- fill the diagnostic.
87 
88  ! Get background error profile from geovals
89  call ufo_geovals_get_var(geovals, varstr, background_error_profile)
90 
91  ! Allocate the background error diagnostic.
92  if (allocated(obsdiags%geovals(ivar)%vals)) deallocate(obsdiags%geovals(ivar)%vals)
93  obsdiags%geovals(ivar)%nval = 1
94  allocate(obsdiags%geovals(ivar)%vals(obsdiags%geovals(ivar)%nval, nlocs))
95 
96  ! Interpolate the profile at observation location into the obsdiag
97  do iobs = 1, nlocs
98  call vert_interp_apply(background_error_profile%nval, &
99  background_error_profile%vals(:,iobs), &
100  obsdiags%geovals(ivar)%vals(1,iobs), &
101  wi(iobs), wf(iobs))
102  enddo
103  enddo
104 
105  ! Free memory
106  deallocate(interp_nodes)
108 
subroutine ufo_backgrounderrorvertinterp_fillobsdiags(obs_vcoord_name, vcoord_name, geovals, obsspace, nlocs, obsvars, obsdiags)
For each obs diagnostic called _background_error, where belongs to the set of variable names obsvars...
subroutine, public ufo_geovals_get_var(self, varname, geoval)
character(len=maxvarlen), parameter, public var_prsi
character(len=maxvarlen), parameter, public var_prs
integer, parameter, public maxvarlen
Fortran module to perform linear interpolation.
Definition: vert_interp.F90:8
subroutine vert_interp_weights(nlev, obl, vec, wi, wf)
Definition: vert_interp.F90:22
subroutine vert_interp_apply(nlev, fvec, f, wi, wf)
Definition: vert_interp.F90:73
type to hold interpolated field for one variable, one observation
type to hold interpolated fields required by the obs operators