UFO
ufo_gnssro_bndropp2d_mod.F90
Go to the documentation of this file.
1 ! (C) Copyright 2017-2018 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 module for gnssro bending angle ropp2d forward operator
7 !> following the ROPP (2018 Aug) implementation
8 
10 
11 use fckit_configuration_module, only: fckit_configuration
12 !use iso_c_binding
13 use kinds
14 use ufo_vars_mod
17 use ufo_basis_mod, only: ufo_basis
20 use obsspace_mod
21 use missing_values_mod
24 
26 use fckit_log_module, only : fckit_log
27 
28 implicit none
29 public :: ufo_gnssro_bndropp2d
30 private
31  !> Fortran derived type for gnssro trajectory
33  type(gnssro_conf) :: roconf
34  real(kind_real), allocatable :: obslon2d(:), obslat2d(:) !2d location
35  contains
36 
37  procedure :: setup => ufo_gnssro_bndropp2d_setup
38  procedure :: simobs => ufo_gnssro_bndropp2d_simobs
39 end type ufo_gnssro_bndropp2d
40 
41 contains
42 
43 ! ------------------------------------------------------------------------------
44 subroutine ufo_gnssro_bndropp2d_setup(self, f_conf, c_size)
45  implicit none
46  class(ufo_gnssro_bndropp2d), intent(inout) :: self
47  type(fckit_configuration), intent(in) :: f_conf
48  integer, intent(in) :: c_size ! 1d obsspace vector length
49 
50  call gnssro_conf_setup(self%roconf,f_conf)
51 
52  allocate(self%obsLon2d(c_size*self%roconf%n_horiz))
53  allocate(self%obsLat2d(c_size*self%roconf%n_horiz))
54 
55  self%obsLon2d = 0.0
56  self%obsLat2d = 0.0
57 
58 end subroutine ufo_gnssro_bndropp2d_setup
59 
60 ! ------------------------------------------------------------------------------
61 subroutine ufo_gnssro_bndropp2d_simobs(self, geovals, hofx, obss)
62  use ropp_fm_types, only: state2dfm, state1dfm
63  use ropp_fm_types, only: obs1dbangle
64  use typesizes, only: wp => eightbytereal
65  use datetimetypes, only: dp
66 
67  implicit none
68  class(ufo_gnssro_bndropp2d), intent(in) :: self
69  type(ufo_geovals), intent(in) :: geovals
70  real(kind_real), intent(inout) :: hofx(:)
71  type(c_ptr), value, intent(in) :: obss
72  real(c_double) :: missing
73 
74  type(state2dfm) :: x
75  type(state1dfm) :: x1d
76  type(obs1dbangle) :: y
77 
78  character(len=*), parameter :: myname_="ufo_gnssro_bndropp2d_simobs"
79  integer, parameter :: max_string = 800
80  character(max_string) :: err_msg
81  integer :: nlev, nlocs, iobs, nvprof
82  integer :: iflip
83  type(ufo_geoval), pointer :: t, q, prs, gph, gph_sfc
84  real(kind_real), allocatable :: obsImpP(:),obsLocR(:),obsGeoid(:),obsAzim(:) !nlocs
85  real(kind_real), allocatable :: obsLat(:),obsLon(:) !nlocs
86  real(kind_real), allocatable :: obsLonnh(:),obsLatnh(:) !n_horiz
87  integer :: n_horiz
88  real(kind_real) :: dtheta
89  real(kind_real) :: ob_time
90  integer, allocatable, dimension(:) :: ichk
91 
92  n_horiz = self%roconf%n_horiz
93  dtheta = self%roconf%dtheta
94 
95  write(err_msg,*) "TRACE: ufo_gnssro_bndropp2d_simobs: begin"
96  call fckit_log%info(err_msg)
97 ! check if nlocs is consistent in geovals & hofx
98  if (geovals%nlocs /= size(hofx)*n_horiz) then
99  write(err_msg,*) myname_, ' error: 2d nlocs inconsistent! geovals%nlocs, size(hofx), &
100  and n_horiz are', geovals%nlocs, size(hofx), n_horiz
101  call abor1_ftn(err_msg)
102  endif
103 
104 ! get variables from geovals
105  call ufo_geovals_get_var(geovals, var_ts, t) ! temperature
106  call ufo_geovals_get_var(geovals, var_q, q) ! specific humidity
107  call ufo_geovals_get_var(geovals, var_prs, prs) ! pressure
108  call ufo_geovals_get_var(geovals, var_z, gph) ! geopotential height
109  call ufo_geovals_get_var(geovals, var_sfc_geomz, gph_sfc) ! surface geopotential height
110 
111  missing = missing_value(missing)
112  nlev = t%nval ! number of model levels
113  nlocs = obsspace_get_nlocs(obss)
114 
115  iflip = 0
116  if (prs%vals(1,1) .lt. prs%vals(prs%nval,1) ) then
117  iflip = 1
118  write(err_msg,'(a)') ' ufo_gnssro_bndropp2d_simobs:'//new_line('a')// &
119  ' Model vertical height profile is in descending order,'//new_line('a')// &
120  ' but ROPP requires it to be ascending order, need flip'
121  call fckit_log%info(err_msg)
122  end if
123 
124 ! set obs space struture
125  allocate(obslon(nlocs))
126  allocate(obslat(nlocs))
127  allocate(obsimpp(nlocs))
128  allocate(obslocr(nlocs))
129  allocate(obsgeoid(nlocs))
130  allocate(obsazim(nlocs))
131  allocate(obslatnh(n_horiz))
132  allocate(obslonnh(n_horiz))
133 
134  call obsspace_get_db(obss, "MetaData", "longitude", obslon)
135  call obsspace_get_db(obss, "MetaData", "latitude", obslat)
136  call obsspace_get_db(obss, "MetaData", "impact_parameter", obsimpp)
137  call obsspace_get_db(obss, "MetaData", "earth_radius_of_curvature", obslocr)
138  call obsspace_get_db(obss, "MetaData", "geoid_height_above_reference_ellipsoid", obsgeoid)
139  call obsspace_get_db(obss, "MetaData", "sensor_azimuth_angle", obsazim)
140 
141  nvprof = 1 ! no. of bending angles in profile
142  ob_time = 0.0
143  allocate(ichk(nvprof))
144  ichk(:) = 0
145  write(err_msg,*) "TRACE: ufo_gnssro_bndropp2d_simobs: begin observation loop, nlocs = ", nlocs
146  call fckit_log%info(err_msg)
147 
148 ! loop through the obs
149  obs_loop: do iobs = 1, nlocs
150 
151  if ( ( obsimpp(iobs)-obslocr(iobs)-obsgeoid(iobs) ) <= self%roconf%top_2d .and. &
152  obsazim(iobs) /= missing ) then
153 
154  obslatnh = self%obsLat2d( (iobs-1)*n_horiz+1:iobs*n_horiz )
155  obslonnh = self%obsLon2d( (iobs-1)*n_horiz+1:iobs*n_horiz )
156  call init_ropp_2d_statevec(obslonnh, obslatnh, &
157  t%vals(:,(iobs-1)*n_horiz+1:iobs*n_horiz), &
158  q%vals(:,(iobs-1)*n_horiz+1:iobs*n_horiz), &
159  prs%vals(:,(iobs-1)*n_horiz+1:iobs*n_horiz), &
160  gph%vals(:,(iobs-1)*n_horiz+1:iobs*n_horiz), &
161  nlev,x,n_horiz,dtheta,iflip)
162 
163  call init_ropp_2d_obvec(nvprof, &
164  obsimpp(iobs), &
165  obslat(iobs), &
166  obslon(iobs), &
167  obslocr(iobs), &
168  obsgeoid(iobs), &
169  y)
170 
171  call ropp_fm_bangle_2d(x,y)
172 
173  else ! apply ropp1d above top_2d
174 
175  call init_ropp_1d_statevec(ob_time, &
176  obslon(iobs), &
177  obslat(iobs), &
178  t%vals(:,(iobs-1)*n_horiz+1+(n_horiz-1)/2), &
179  q%vals(:,(iobs-1)*n_horiz+1+(n_horiz-1)/2), &
180  prs%vals(:,(iobs-1)*n_horiz+1+(n_horiz-1)/2), &
181  gph%vals(:,(iobs-1)*n_horiz+1+(n_horiz-1)/2), &
182  nlev, &
183  gph_sfc%vals(1,(iobs-1)*n_horiz+1+(n_horiz-1)/2), &
184  x1d, iflip)
185 
186  call init_ropp_1d_obvec(nvprof, &
187  obsimpp(iobs), &
188  ichk, ob_time, &
189  obslat(iobs), &
190  obslon(iobs), &
191  obslocr(iobs), &
192  obsgeoid(iobs), &
193  y)
194 
195  call ropp_fm_bangle_1d(x1d,y)
196 
197  end if
198 
199 ! hack -- handling ropp missing value
200  if (y%bangle(nvprof) .lt. -900.0_wp ) then
201  hofx(iobs) = missing
202  y%bangle(nvprof) = missing
203  else
204  hofx(iobs) = y%bangle(nvprof) ! nvprof is just one point
205  end if
206 ! hack -- handling ropp missing value
207 
208 ! deallocate ropp structures
209  if ( ( obsimpp(iobs)-obslocr(iobs)-obsgeoid(iobs) ) <= self%roconf%top_2d ) then
210  call ropp_tidy_up_2d(x,y)
211  else
212  call ropp_tidy_up_1d(x1d,y)
213  end if
214 
215  end do obs_loop
216 
217  deallocate(obslat)
218  deallocate(obslon)
219  deallocate(obsimpp)
220  deallocate(obslocr)
221  deallocate(obsgeoid)
222  deallocate(obsazim)
223  deallocate(obslatnh)
224  deallocate(obslonnh)
225  deallocate(ichk)
226 
227  write(err_msg,*) "TRACE: ufo_gnssro_bndropp2d_simobs: completed"
228  call fckit_log%info(err_msg)
229 
230  return
231 
232 end subroutine ufo_gnssro_bndropp2d_simobs
233 ! ------------------------------------------------------------------------------
234 
235 end module ufo_gnssro_bndropp2d_mod
subroutine, public gnssro_conf_setup(roconf, f_conf)
Fortran module to prepare for Lagrange polynomial interpolation. based on GSI: lagmod....
Definition: lag_interp.F90:4
subroutine, public lag_interp_const(q, x, n)
Definition: lag_interp.F90:24
subroutine, public lag_interp_smthweights(x, xt, aq, bq, w, dw, n)
Definition: lag_interp.F90:174
type(registry_t), public ufo_geovals_registry
Linked list interface - defines registry_t type.
subroutine, public ufo_geovals_get_var(self, varname, geoval)
Fortran module for gnssro bending angle ropp2d forward operator following the ROPP (2018 Aug) impleme...
subroutine ufo_gnssro_bndropp2d_setup(self, f_conf, c_size)
subroutine ufo_gnssro_bndropp2d_simobs(self, geovals, hofx, obss)
Fortran module to handle gnssro bending angle observations following the ROPP (2018 Aug) implementati...
subroutine, public init_ropp_1d_statevec(step_time, rlon, rlat, temp, shum, pres, phi, lm, phi_sfc, x, iflip)
subroutine, public init_ropp_1d_obvec(nvprof, obs_impact, ichk, ob_time, rlat, rlon, roc, undulat, y)
Fortran module to handle gnssro bending angle observations following the ROPP (2018 Aug) implementati...
subroutine, public init_ropp_2d_statevec(rlon, rlat, temp, shum, pres, phi, lm, x, n_horiz, dtheta, iflip)
subroutine, public init_ropp_2d_obvec(nvprof, obs_impact, rlat, rlon, roc, undulat, y)
character(len=maxvarlen), parameter, public var_prs
character(len=maxvarlen), parameter, public var_q
character(len=maxvarlen), parameter, public var_sfc_geomz
character(len=maxvarlen), parameter, public var_z
character(len=maxvarlen), parameter, public var_ts
Fortran module to perform linear interpolation.
Definition: vert_interp.F90:8
type to hold interpolated field for one variable, one observation
type to hold interpolated fields required by the obs operators
Fortran derived type for gnssro trajectory.