UFO
ufo_marinevertinterp_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 
6 !> Fortran marinevertinterp module for tl/ad observation operator
7 
9 
10  use oops_variables_mod
11  use kinds
13  use ufo_vars_mod
14 
15  implicit none
16  private
17 
18  integer, parameter :: max_string=800
19 
20  !> Fortran derived type for the tl/ad observation operator
21  type, public :: ufo_marinevertinterp_tlad
22  private
23  type(oops_variables), public :: geovars
24  type(oops_variables), public :: obsvars
25  logical, public :: ltraj = .false. !< trajectory set?
26  integer :: nlocs !< Number of observations
27  integer :: nval !< Number of level in model's profiles
28  type(ufo_geoval) :: var !< traj
29  type(ufo_geoval) :: h !< Layer thickness (traj) ] obs locations
30  real (kind=kind_real), allocatable :: depth(:,:) !< Depth [nval x nlocs]
31  real (kind=kind_real), allocatable :: deptho(:) !< Observation location
32  real(kind_real), allocatable :: wf(:) !< Vertical interpolation weights
33  integer, allocatable :: wi(:) !< Vertical interpolation indices
34  contains
35  procedure :: setup => ufo_marinevertinterp_tlad_setup
36  procedure :: delete => ufo_marinevertinterp_tlad_delete
37  procedure :: settraj => ufo_marinevertinterp_tlad_settraj
38  procedure :: simobs_tl => ufo_marinevertinterp_simobs_tl
39  procedure :: simobs_ad => ufo_marinevertinterp_simobs_ad
41 
42 contains
43 
44 ! ------------------------------------------------------------------------------
46 implicit none
47 class(ufo_marinevertinterp_tlad), intent(inout) :: self
48 
49 integer :: ivar, nvars
50 
51 nvars = self%obsvars%nvars()
52 do ivar = 1, nvars
53  call self%geovars%push_back(self%obsvars%variable(ivar))
54 enddo
55 
57 
58 ! ------------------------------------------------------------------------------
60 implicit none
61 class(ufo_marinevertinterp_tlad), intent(inout) :: self
62 
63  if (allocated(self%wi)) deallocate(self%wi)
64  if (allocated(self%wf)) deallocate(self%wf)
65  if (allocated(self%deptho)) deallocate(self%deptho)
66  if (allocated(self%depth)) deallocate(self%depth)
67  if (allocated(self%var%vals)) deallocate(self%var%vals)
68  if (allocated(self%h%vals)) deallocate(self%h%vals)
69  self%ltraj = .false.
70 
72 
73 ! ------------------------------------------------------------------------------
74 subroutine ufo_marinevertinterp_tlad_settraj(self, geovals, obss)
75  use vert_interp_mod
76  use ufo_tpsp2ti_mod
77  use obsspace_mod
78  use iso_c_binding
79  implicit none
80  class(ufo_marinevertinterp_tlad), intent(inout) :: self !< Complete trajectory needed by the operator
81  type(ufo_geovals), intent(in) :: geovals !< Model background
82  type(c_ptr), value, intent(in) :: obss !<
83 
84  character(len=*), parameter :: myname_="ufo_marinevertinterp_tlad_settraj"
85  character(max_string) :: err_msg
86 
87  type(ufo_geoval), pointer :: var, h
88  integer :: nlocs, nlev, iobs, ilev
89 
90  real(kind_real), allocatable :: obs_depth(:)
91  integer :: obss_nlocs
92 
93  ! Associate geovals pointers
94  call ufo_geovals_get_var(geovals, self%geovars%variable(1), var)
95  call ufo_geovals_get_var(geovals, var_ocn_lay_thick, h)
96 
98 
99  nlocs = h%nlocs
100  nlev = h%nval
101 
102  self%nlocs = nlocs
103  self%nval = nlev
104 
105  self%var = var
106  self%h = h
107 
108  allocate(self%deptho(nlocs))
109 
110  obss_nlocs = obsspace_get_nlocs(obss)
111  allocate(obs_depth(obss_nlocs))
112  call obsspace_get_db(obss, "MetaData", "depth", obs_depth)
113 
114  self%deptho = obs_depth
115 
116  !< Depth from layer thickness
117  allocate(self%depth(nlev,nlocs))
118  do iobs = 1, nlocs
119  self%depth(1,iobs)=0.5*self%h%vals(1,iobs)
120  do ilev = 2, nlev
121  self%depth(ilev,iobs)=sum(self%h%vals(1:ilev-1,iobs))+0.5*self%h%vals(ilev,iobs)
122  end do
123  end do
124 
125  !< Interpolation weight
126  allocate(self%wi(nlocs),self%wf(nlocs))
127  do iobs = 1, nlocs
128  call vert_interp_weights(nlev,self%deptho(iobs),self%depth(:,iobs),self%wi(iobs),self%wf(iobs))
129  end do
130  self%ltraj = .true.
131 
132  deallocate(obs_depth)
133 
135 
136 ! ------------------------------------------------------------------------------
137 subroutine ufo_marinevertinterp_simobs_tl(self, geovals, hofx, obss)
138  use ufo_tpsp2ti_mod
140  use vert_interp_mod
141  use obsspace_mod
142  use missing_values_mod
143  use iso_c_binding
144  implicit none
145  class(ufo_marinevertinterp_tlad), intent(in) :: self
146  type(ufo_geovals), intent(in) :: geovals
147  real(c_double), intent(inout) :: hofx(:)
148  type(c_ptr), value, intent(in) :: obss
149 
150  character(len=*), parameter :: myname_="ufo_marinevertinterp_simobs_tl"
151  character(max_string) :: err_msg
152  integer :: iobs, ilev, nlev, nlocs
153  type(ufo_geoval), pointer :: var_d !< Increments from geoval
154 
155  ! check if trajectory was set
156  if (.not. self%ltraj) then
157  write(err_msg,*) myname_, ' trajectory wasnt set!'
158  call abor1_ftn(err_msg)
159  endif
160 
161  ! check if nlocs is consistent in geovals & hofx
162  if (geovals%nlocs /= size(hofx,1)) then
163  write(err_msg,*) myname_, ' error: nlocs inconsistent!'
164  call abor1_ftn(err_msg)
165  endif
166 
167  ! Associate geovals
168  call ufo_geovals_get_var(geovals, self%geovars%variable(1), var_d)
169 
170  nlev = var_d%nval
171  nlocs = var_d%nlocs
172 
173  ! linear vertical interp
174  hofx = 0.0
175  do iobs = 1,nlocs
176  call vert_interp_apply(nlev, var_d%vals(:,iobs), hofx(iobs), self%wi(iobs), self%wf(iobs))
177  enddo
178 
179 end subroutine ufo_marinevertinterp_simobs_tl
180 
181 ! ------------------------------------------------------------------------------
182 subroutine ufo_marinevertinterp_simobs_ad(self, geovals, hofx, obss)
183  use ufo_tpsp2ti_mod
185  use vert_interp_mod
186  use obsspace_mod
187  use missing_values_mod
188  use iso_c_binding
189  implicit none
190  class(ufo_marinevertinterp_tlad), intent(in) :: self
191  type(ufo_geovals), intent(inout) :: geovals
192  real(c_double), intent(in) :: hofx(:)
193  type(c_ptr), value, intent(in) :: obss
194 
195  character(len=*), parameter :: myname_="ufo_marinevertinterp_simobs_ad"
196  character(max_string) :: err_msg
197 
198  real (kind=kind_real) :: deptho !< Observation location
199 
200  integer :: iobs, nlocs, ilev, nlev
201  type(ufo_geoval), pointer :: dvar
202  real(c_double) :: missing
203 
204  !> Set missing value
205  missing = missing_value(missing)
206 
207  ! check if trajectory was set
208  if (.not. self%ltraj) then
209  write(err_msg,*) myname_, ' trajectory wasnt set!'
210  call abor1_ftn(err_msg)
211  endif
212 
213  ! check if nlocs is consistent in geovals & hofx
214  if (geovals%nlocs /= size(hofx,1)) then
215  write(err_msg,*) myname_, ' error: nlocs inconsistent!'
216  call abor1_ftn(err_msg)
217  endif
218 
219  if (.not. geovals%linit ) geovals%linit=.true.
220 
221  ! Associate geovals
222  call ufo_geovals_get_var(geovals, var_ocn_salt, dvar)
223 
224  nlev = self%nval
225  nlocs = self%nlocs
226 
227  ! backward vertical interp
228  do iobs = 1, size(hofx,1)
229  if (hofx(iobs) /= missing) then
230  deptho = self%deptho(iobs)
231 
232  ! Adjoint obs operator
233  call vert_interp_apply_ad(nlev, dvar%vals(:,iobs), hofx(iobs), self%wi(iobs), self%wf(iobs))
234  end if
235  enddo
236 
237 end subroutine ufo_marinevertinterp_simobs_ad
238 
subroutine, public ufo_geovals_get_var(self, varname, geoval)
Fortran marinevertinterp module for tl/ad observation operator.
subroutine ufo_marinevertinterp_simobs_tl(self, geovals, hofx, obss)
subroutine ufo_marinevertinterp_tlad_settraj(self, geovals, obss)
subroutine ufo_marinevertinterp_simobs_ad(self, geovals, hofx, obss)
character(len=maxvarlen), public var_ocn_salt
character(len=maxvarlen), public var_ocn_lay_thick
Fortran module to perform linear interpolation.
Definition: vert_interp.F90:8
subroutine vert_interp_apply_ad(nlev, fvec_ad, f_ad, wi, wf)
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
Fortran derived type for the tl/ad observation operator.