UFO
ufo_groundgnss_ropp_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 ground-based gnss refractivity ropp forward operator
7 !> following the ROPP (2018 Aug) implementation
8 
10 
11 use iso_c_binding
12 use kinds
13 use ufo_vars_mod
16 use ufo_basis_mod, only: ufo_basis
17 use obsspace_mod
18 use missing_values_mod
20 use fckit_log_module, only : fckit_log
21 
22 implicit none
23 public :: ufo_groundgnss_ropp
24 private
25 
26  !> Fortran derived type for ground based gnss trajectory
27 type, extends(ufo_basis) :: ufo_groundgnss_ropp
28  contains
29  procedure :: simobs => ufo_groundgnss_ropp_simobs
30 end type ufo_groundgnss_ropp
31 
32 contains
33 
34 ! ------------------------------------------------------------------------------
35 ! Description:
36 ! simulate the zenith total delay point observation
37 ! this is done by integrating refractivities
38 ! computed by the ROPP forward operator
39 !
40 ! Inputs:
41 ! obsLat latitude
42 ! obsLon longitude
43 ! obsHeight station height
44 !
45 ! t temperature
46 ! q specific humidity
47 ! prs pressure
48 ! gph geopotential height
49 ! z_sfc surface geometric height
50 !
51 ! Outputs:
52 ! model_ztd simulated zenith total delay (put into HofX)
53 !
54 ! ------------------------------------------------------------------------------
55 subroutine ufo_groundgnss_ropp_simobs(self, geovals, hofx, obss)
56  use ropp_fm_types, only: state1dfm
57  use ropp_fm_types, only: obs1drefrac
58  use typesizes, only: wp => eightbytereal
59  use datetimetypes, only: dp
60 
61  implicit none
62  class(ufo_groundgnss_ropp), intent(in) :: self
63  type(ufo_geovals), intent(in) :: geovals
64  real(kind_real), intent(inout) :: hofx(:)
65  type(c_ptr), value, intent(in) :: obss
66  real(c_double) :: missingDouble
67 
68  type(state1dfm) :: x ! ROPP 1d state vector data type
69  type(obs1drefrac) :: y ! ROPP 1d Refractivity "observations" vector data type
70 
71  character(len=*), parameter :: myname_="ufo_groundgnss_ropp_simobs"
72  real(kind=dp) :: ob_time
73  integer, parameter :: max_string = 800
74 
75  character(max_string) :: err_msg ! error message
76  integer :: nlev, nobs, iobs ! number of model level, observations, and counter
77  integer, allocatable, dimension(:) :: ichk ! quality indicator for observation
78  type(ufo_geoval), pointer :: t, q, prs, gph, z_sfc ! model state variables
79  real(kind_real), allocatable :: obsLat(:), obsLon(:) ! observation latitude and longitude
80  real(kind_real), allocatable :: obsHeight(:), obsValue(:) ! observation station height and value
81  real(kind_real), allocatable :: model_z(:) ! model geometric height
82  real(kind_real) :: station_phi ! observation geopotential height
83  real(kind_real) :: model_ztd ! simulated observation (zenith total delay)
84  integer :: iflip ! monotonic increasing height
85  logical :: l_linear ! indicator of refractivity interpolation method
86  write(err_msg,*) "TRACE: ufo_groundgnss_ropp_simobs: begin"
87  call fckit_log%info(err_msg)
88 
89 ! check if nlocs is consistent in geovals & hofx
90  if (geovals%nlocs /= size(hofx)) then
91  write(err_msg,*) myname_, ' error: nlocs inconsistent!'
92  call abor1_ftn(err_msg)
93  endif
94 
95 ! get variables from geovals
96  call ufo_geovals_get_var(geovals, var_ts, t) ! temperature
97  call ufo_geovals_get_var(geovals, var_q, q) ! specific humidity
98  call ufo_geovals_get_var(geovals, var_prs, prs) ! pressure
99  call ufo_geovals_get_var(geovals, var_z, gph) ! geopotential height
100  call ufo_geovals_get_var(geovals, var_sfc_geomz, z_sfc) ! surface geometric height
101 
102  missingdouble = missing_value(missingdouble)
103 
104  nlev = t%nval ! number of model levels
105  nobs = obsspace_get_nlocs(obss)
106 
107  if (nobs > 0) then
108  iflip = 0
109  if (prs%vals(1,1) .lt. prs%vals(prs%nval,1) ) then
110  iflip = 1
111  write(err_msg,'(a)') ' ufo_groundgnss_ropp_simobs:'//new_line('a')// &
112  ' Model vertical height profile is in descending order,'//new_line('a')// &
113  ' but ROPP requires it to be ascending order, need flip'
114  call fckit_log%info(err_msg)
115  end if
116 
117  ! set obs space struture
118  allocate(obslon(nobs))
119  allocate(obslat(nobs))
120  allocate(obsheight(nobs))
121  allocate(obsvalue(nobs))
122 
123  ! create array for model geometric heights
124  allocate(model_z(nlev))
125  model_z(:) = 0.0
126 
127  call obsspace_get_db(obss, "MetaData", "longitude", obslon)
128  call obsspace_get_db(obss, "MetaData", "latitude", obslat)
129  call obsspace_get_db(obss, "MetaData", "station_height", obsheight)
130  call obsspace_get_db(obss, "ObsValue", "ZTD", obsvalue)
131 ! obsValue = 0.0
132 
133  allocate(ichk(nlev))
134  ichk(:) = 0 ! this will hold QC values for observation from QC flags
135 
136  write(err_msg,*) "TRACE: ufo_groundgnss_ropp_simobs: begin observation loop, nobs = ", nobs
137  call fckit_log%info(err_msg) ! always print
138 
139  obs_loop: do iobs = 1, nobs
140 
141  ob_time = 0.0
142  l_linear = .false.
143  call init_ropp_1d_statevec(ob_time, &
144  obslon(iobs), &
145  obslat(iobs), &
146  t%vals(:,iobs), &
147  q%vals(:,iobs), &
148  prs%vals(:,iobs), &
149  gph%vals(:,iobs), &
150  nlev, &
151  z_sfc%vals(1,iobs), &
152  x, iflip)
153 
154  call calc_station_phi(obslat(iobs), obsheight(iobs), station_phi)
155  call init_ropp_1d_obvec(nlev, &
156  ichk, ob_time, &
157  obslat(iobs), &
158  obslon(iobs), &
159  station_phi, &
160  x, y)
161 
162  call ropp_fm_refrac_1d(x,y)
163 
164  call calc_model_z(nlev, obslat(iobs), y%geop, model_z)
165  ! note the scaling of the refractivity by 1.e-6 is done in subroutine after integral
166  call gnss_ztd_integral(nlev, y%refrac, model_z, obsheight(iobs), model_ztd, l_linear)
167  ! add error trap ! model_ztd initialized to 0 in integral if 0 is returned something very wrong
168  if ( model_ztd == 0.0 ) then
169  model_ztd = missingdouble
170  end if
171 
172  ! matching a print format used in initialization of obvec
173  if ( iobs == 1 ) then
174  write(err_msg,'(a9,2a11,2a16,2a15)') 'ROPPsim: ', 'lat', 'lon', &
175  'ob', 'bk', 'station_hgt', 'model_terr'
176  call fckit_log%debug(err_msg) ! print when MAIN_DEBUG=1
177  end if
178  write(err_msg,'(9x,2f11.3,2f16.6,2f15.3)') &
179  obslat(iobs), &
180  obslon(iobs), &
181  obsvalue(iobs), &
182  model_ztd, &
183  obsheight(iobs), &
184  model_z(1)
185  call fckit_log%debug(err_msg) ! print when MAIN_DEBUG=1
186 
187  hofx(iobs) = model_ztd
188 
189  ! hack -- handling ropp missing value
190  call ropp_tidy_up_1d(x,y)
191 
192  end do obs_loop
193 
194  deallocate(ichk)
195  deallocate(obslat)
196  deallocate(obslon)
197  deallocate(obsheight)
198  deallocate(obsvalue)
199  end if ! nobs > 0
200 
201  write(err_msg,*) "TRACE: ufo_groundgnss_ropp_simobs: completed"
202  call fckit_log%info(err_msg)
203 
204 end subroutine ufo_groundgnss_ropp_simobs
205 ! ------------------------------------------------------------------------------
206 
207 end module ufo_groundgnss_ropp_mod
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 ground-based gnss refractivity ropp forward operator following the ROPP (2018 Aug)...
subroutine ufo_groundgnss_ropp_simobs(self, geovals, hofx, obss)
Fortran module to handle ground-based gnss observations following the ROPP (2018 Aug) implementation.
subroutine, public calc_model_z(nlev, rlat, model_phi, model_z)
subroutine, public init_ropp_1d_obvec(nlev, ichk, ob_time, rlat, rlon, station_phi, x, y)
subroutine, public gnss_ztd_integral(lm, model_refrac, model_z, ob_terr, model_ztd, l_linear)
subroutine, public calc_station_phi(rlat, station_height, station_phi)
subroutine, public init_ropp_1d_statevec(step_time, rlon, rlat, temp, shum, pres, phi, lm, z_sfc, x, iflip)
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
type to hold interpolated field for one variable, one observation
type to hold interpolated fields required by the obs operators
Fortran derived type for ground based gnss trajectory.