UFO
ufo_atmvertinterp_tlad_mod.F90
Go to the documentation of this file.
1 ! (C) Copyright 2017-2019 UCAR
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 oops_variables_mod
9  use ufo_vars_mod
10  use ufo_geovals_mod
11  use vert_interp_mod
12  use missing_values_mod
13 
14 
15 ! ------------------------------------------------------------------------------
16 
17  type, public :: ufo_atmvertinterp_tlad
18  private
19  type(oops_variables), public :: obsvars
20  type(oops_variables), public :: geovars
21  integer :: nval, nlocs
22  real(kind_real), allocatable :: wf(:)
23  integer, allocatable :: wi(:)
24  character(len=MAXVARLEN), public :: v_coord ! GeoVaL to use to interpolate in vertical
25  logical, public :: use_ln ! if T, use ln(v_coord) not v_coord
26  contains
27  procedure :: setup => atmvertinterp_tlad_setup_
28  procedure :: cleanup => atmvertinterp_tlad_cleanup_
29  procedure :: settraj => atmvertinterp_tlad_settraj_
30  procedure :: simobs_tl => atmvertinterp_simobs_tl_
31  procedure :: simobs_ad => atmvertinterp_simobs_ad_
32  final :: destructor
33  end type ufo_atmvertinterp_tlad
34 
35 ! ------------------------------------------------------------------------------
36 contains
37 ! ------------------------------------------------------------------------------
38 
39 subroutine atmvertinterp_tlad_setup_(self, grid_conf)
40  use fckit_configuration_module, only: fckit_configuration
41  implicit none
42  class(ufo_atmvertinterp_tlad), intent(inout) :: self
43  type(fckit_configuration), intent(in) :: grid_conf
44 
45  character(kind=c_char,len=:), allocatable :: coord_name
46  integer :: ivar, nvars
47 
48  !> Fill in variables requested from the model
49  nvars = self%obsvars%nvars()
50  do ivar = 1, nvars
51  call self%geovars%push_back(self%obsvars%variable(ivar))
52  enddo
53  !> grab what vertical coordinate/variable to use from the config
54  self%use_ln = .false.
55 
56  if( grid_conf%has("vertical coordinate") ) then
57  call grid_conf%get_or_die("vertical coordinate",coord_name)
58  self%v_coord = coord_name
59  if( trim(self%v_coord) .eq. var_prs ) self%use_ln = .true.
60  else ! default
61  self%v_coord = var_prs
62  self%use_ln = .true.
63  endif
64 
65 end subroutine atmvertinterp_tlad_setup_
66 
67 ! ------------------------------------------------------------------------------
68 
69 subroutine atmvertinterp_tlad_settraj_(self, geovals, obss)
70  use obsspace_mod
71  implicit none
72  class(ufo_atmvertinterp_tlad), intent(inout) :: self
73  type(ufo_geovals), intent(in) :: geovals
74  type(c_ptr), value, intent(in) :: obss
75 
76  real(kind_real), allocatable :: obsvcoord(:)
77  type(ufo_geoval), pointer :: vcoordprofile
78  integer :: iobs
79  real(kind_real), allocatable :: tmp(:)
80  real(kind_real) :: tmp2
81 
82  ! Make sure nothing already allocated
83  call self%cleanup()
84 
85  ! Get pressure profiles from geovals
86  call ufo_geovals_get_var(geovals, self%v_coord, vcoordprofile)
87  self%nval = vcoordprofile%nval
88 
89  ! Get the observation vertical coordinates
90  self%nlocs = obsspace_get_nlocs(obss)
91  allocate(obsvcoord(self%nlocs))
92  call obsspace_get_db(obss, "MetaData", self%v_coord, obsvcoord)
93 
94  ! Allocate arrays for interpolation weights
95  allocate(self%wi(self%nlocs))
96  allocate(self%wf(self%nlocs))
97 
98  ! Calculate the interpolation weights
99  allocate(tmp(vcoordprofile%nval))
100  do iobs = 1, self%nlocs
101  if (self%use_ln) then
102  tmp = log(vcoordprofile%vals(:,iobs))
103  tmp2 = log(obsvcoord(iobs))
104  else
105  tmp = vcoordprofile%vals(:,iobs)
106  tmp2 = obsvcoord(iobs)
107  end if
108  call vert_interp_weights(vcoordprofile%nval, tmp2, tmp, self%wi(iobs), self%wf(iobs))
109  enddo
110 
111  ! Cleanup memory
112  deallocate(obsvcoord)
113  deallocate(tmp)
114 
115 end subroutine atmvertinterp_tlad_settraj_
116 
117 ! ------------------------------------------------------------------------------
118 
119 subroutine atmvertinterp_simobs_tl_(self, geovals, obss, nvars, nlocs, hofx)
120  implicit none
121  class(ufo_atmvertinterp_tlad), intent(in) :: self
122  type(ufo_geovals), intent(in) :: geovals
123  integer, intent(in) :: nvars, nlocs
124  real(c_double), intent(inout) :: hofx(nvars, nlocs)
125  type(c_ptr), value, intent(in) :: obss
126 
127  integer :: iobs, ivar
128  type(ufo_geoval), pointer :: profile
129  character(len=MAXVARLEN) :: geovar
130 
131  do ivar = 1, nvars
132  ! Get the name of input variable in geovals
133  geovar = self%geovars%variable(ivar)
134 
135  ! Get profile for this variable from geovals
136  call ufo_geovals_get_var(geovals, geovar, profile)
137 
138  ! Interpolate from geovals to observational location into hofx
139  do iobs = 1, nlocs
140  call vert_interp_apply_tl(profile%nval, profile%vals(:,iobs), &
141  & hofx(ivar,iobs), self%wi(iobs), self%wf(iobs))
142  enddo
143  enddo
144 end subroutine atmvertinterp_simobs_tl_
145 
146 ! ------------------------------------------------------------------------------
147 
148 subroutine atmvertinterp_simobs_ad_(self, geovals, obss, nvars, nlocs, hofx)
149  implicit none
150  class(ufo_atmvertinterp_tlad), intent(in) :: self
151  type(ufo_geovals), intent(inout) :: geovals
152  integer, intent(in) :: nvars, nlocs
153  real(c_double), intent(in) :: hofx(nvars, nlocs)
154  type(c_ptr), value, intent(in) :: obss
155 
156  integer :: iobs, ivar
157  type(ufo_geoval), pointer :: profile
158  character(len=MAXVARLEN) :: geovar
159  real(c_double) :: missing
160 
161  missing = missing_value(missing)
162 
163  do ivar = 1, nvars
164  ! Get the name of input variable in geovals
165  geovar = self%geovars%variable(ivar)
166 
167  ! Get pointer to profile for this variable in geovals
168  call ufo_geovals_get_var(geovals, geovar, profile)
169 
170  ! Allocate geovals profile if not yet allocated
171  if (.not. allocated(profile%vals)) then
172  profile%nlocs = self%nlocs
173  profile%nval = self%nval
174  allocate(profile%vals(profile%nval, profile%nlocs))
175  profile%vals(:,:) = 0.0_kind_real
176  endif
177  if (.not. geovals%linit ) geovals%linit=.true.
178 
179  ! Adjoint of interpolate, from hofx into geovals
180  do iobs = 1, self%nlocs
181  if (hofx(ivar,iobs) /= missing) then
182  call vert_interp_apply_ad(profile%nval, profile%vals(:,iobs), &
183  & hofx(ivar,iobs), self%wi(iobs), self%wf(iobs))
184  endif
185  enddo
186  enddo
187 end subroutine atmvertinterp_simobs_ad_
188 
189 ! ------------------------------------------------------------------------------
190 
192  implicit none
193  class(ufo_atmvertinterp_tlad), intent(inout) :: self
194  self%nval = 0
195  self%nlocs = 0
196  if (allocated(self%wi)) deallocate(self%wi)
197  if (allocated(self%wf)) deallocate(self%wf)
198 end subroutine atmvertinterp_tlad_cleanup_
199 
200 ! ------------------------------------------------------------------------------
201 
202 subroutine destructor(self)
203  type(ufo_atmvertinterp_tlad), intent(inout) :: self
204 
205  call self%cleanup()
206 
207 end subroutine destructor
208 
209 ! ------------------------------------------------------------------------------
210 
ufo_atmvertinterp_tlad_mod::atmvertinterp_tlad_cleanup_
subroutine atmvertinterp_tlad_cleanup_(self)
Definition: ufo_atmvertinterp_tlad_mod.F90:192
ufo_atmvertinterp_tlad_mod::atmvertinterp_tlad_settraj_
subroutine atmvertinterp_tlad_settraj_(self, geovals, obss)
Definition: ufo_atmvertinterp_tlad_mod.F90:70
vert_interp_mod::vert_interp_apply_tl
subroutine vert_interp_apply_tl(nlev, fvec_tl, f_tl, wi, wf)
Definition: vert_interp.F90:92
ufo_atmvertinterp_tlad_mod::destructor
subroutine destructor(self)
Definition: ufo_atmvertinterp_tlad_mod.F90:203
ufo_atmvertinterp_tlad_mod::ufo_atmvertinterp_tlad
Definition: ufo_atmvertinterp_tlad_mod.F90:17
ufo_atmvertinterp_tlad_mod::atmvertinterp_simobs_ad_
subroutine atmvertinterp_simobs_ad_(self, geovals, obss, nvars, nlocs, hofx)
Definition: ufo_atmvertinterp_tlad_mod.F90:149
vert_interp_mod
Fortran module to perform linear interpolation.
Definition: vert_interp.F90:8
ufo_atmvertinterp_tlad_mod::atmvertinterp_simobs_tl_
subroutine atmvertinterp_simobs_tl_(self, geovals, obss, nvars, nlocs, hofx)
Definition: ufo_atmvertinterp_tlad_mod.F90:120
vert_interp_mod::vert_interp_weights
subroutine vert_interp_weights(nlev, obl, vec, wi, wf)
Definition: vert_interp.F90:22
ufo_geovals_mod
Definition: ufo_geovals_mod.F90:7
vert_interp_mod::vert_interp_apply_ad
subroutine vert_interp_apply_ad(nlev, fvec_ad, f_ad, wi, wf)
Definition: vert_interp.F90:111
ufo_vars_mod
Definition: ufo_variables_mod.F90:8
ufo_geovals_mod::ufo_geovals_get_var
subroutine, public ufo_geovals_get_var(self, varname, geoval)
Definition: ufo_geovals_mod.F90:128
ufo_geovals_mod::ufo_geovals
type to hold interpolated fields required by the obs operators
Definition: ufo_geovals_mod.F90:47
ufo_geovals_mod::ufo_geoval
type to hold interpolated field for one variable, one observation
Definition: ufo_geovals_mod.F90:40
ufo_atmvertinterp_tlad_mod::atmvertinterp_tlad_setup_
subroutine atmvertinterp_tlad_setup_(self, grid_conf)
Definition: ufo_atmvertinterp_tlad_mod.F90:40
ufo_atmvertinterp_tlad_mod
Definition: ufo_atmvertinterp_tlad_mod.F90:6
ufo_vars_mod::var_prs
character(len=maxvarlen), parameter, public var_prs
Definition: ufo_variables_mod.F90:25