UFO
ufo_groundgnss_metoffice_mod.F90
Go to the documentation of this file.
1 !-------------------------------------------------------------------------------
2 ! (C) British Crown Copyright 2020 Met Office
3 !
4 ! This software is licensed under the terms of the Apache Licence Version 2.0
5 ! which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6 !-------------------------------------------------------------------------------
7 
8 !> Fortran module for ground based gnss Met Office forward operator
9 
11 
12 use iso_c_binding
13 use kinds
14 use ufo_vars_mod
17 use ufo_basis_mod, only: ufo_basis
18 use obsspace_mod
19 use missing_values_mod
21 use fckit_log_module, only : fckit_log
23 
24 implicit none
26 private
27 
28  !> Fortran derived type for groundgnss trajectory
30  logical :: vert_interp_ops
31  logical :: pseudo_ops
32  real(kind_real) :: min_temp_grad
33  contains
34  procedure :: setup => ufo_groundgnss_metoffice_setup
35  procedure :: simobs => ufo_groundgnss_metoffice_simobs
37 
38 contains
39 
40 ! ------------------------------------------------------------------------------
41 ! Get the optional settings for the forward model, and save them in the object
42 ! so that they can be used in the code.
43 ! ------------------------------------------------------------------------------
44 subroutine ufo_groundgnss_metoffice_setup(self, f_conf)
45 
46 use fckit_configuration_module, only: fckit_configuration
47 implicit none
48 class(ufo_groundgnss_metoffice), intent(inout) :: self
49 type(fckit_configuration), intent(in) :: f_conf
50 call f_conf%get_or_die("min_temp_grad", self % min_temp_grad)
51 
52 end subroutine ufo_groundgnss_metoffice_setup
53 
54 
55 ! ------------------------------------------------------------------------------
56 ! Ground GNSS forward operator for the Met Office system
57 ! ------------------------------------------------------------------------------
58 subroutine ufo_groundgnss_metoffice_simobs(self, geovals, hofx, obss)
59 
60  implicit none
61 
62  ! Arguments to this routine
63  class(ufo_groundgnss_metoffice), intent(in) :: self ! The object in which this operator is contained
64  type(ufo_geovals), intent(in) :: geovals ! The model values, interpolated to the obsevation locations
65  real(kind_real), intent(inout) :: hofx(:) ! The model forecast of the observations
66  type(c_ptr), value, intent(in) :: obss ! The observations, and meta-data for those observations
67 
68  character(len=*), parameter :: myname_ = "ufo_groundgnss_metoffice_simobs"
69  integer, parameter :: max_string = 800
70 
71  character(max_string) :: err_msg ! Error message for output
72  character(max_string) :: message ! General message for output
73  integer :: nobs ! Number of observations
74  integer :: iobs ! Loop variable, observation number
75  type(ufo_geoval), pointer :: q ! Model background values of specific humidity
76  type(ufo_geoval), pointer :: prs ! Model background values of air pressure
77  type(ufo_geoval), pointer :: theta_heights ! Model heights of levels containing specific humidity
78  type(ufo_geoval), pointer :: rho_heights ! Model heights of levels containing air pressure
79 
80  real(kind_real), allocatable :: zStation(:)
81 
82  ! Local variables
83  INTEGER :: ilev, nlevp, nlevq, iflip
84  REAL(kind_real), allocatable :: pressure(:) ! Model background values of air pressure (monotonic order)
85  REAL(kind_real), allocatable :: humidity(:) ! Model background specific humidity (in pressure monotonic order)
86  REAL(kind_real), allocatable :: za(:) ! Model heights of rho levs (in pressure monotonic order)
87  REAL(kind_real), allocatable :: zb(:) ! Model heights of theta levs (in pressure monotonic order)
88 
89 
90  write(err_msg,*) "TRACE: ufo_groundgnss_metoffice_simobs: begin"
91  call fckit_log%info(err_msg)
92 
93 ! check if nlocs is consistent in geovals & hofx
94  IF (geovals%nlocs /= size(hofx)) THEN
95  write(err_msg,*) myname_, ' error: nlocs inconsistent!'
96  call abor1_ftn(err_msg)
97  END IF
98 
99 ! get variables from geovals
100  call ufo_geovals_get_var(geovals, var_q, q) ! specific humidity
101  call ufo_geovals_get_var(geovals, var_prsi, prs) ! pressure
102  call ufo_geovals_get_var(geovals, var_z, theta_heights) ! Geopotential height of the normal model levels
103  call ufo_geovals_get_var(geovals, var_zi, rho_heights) ! Geopotential height of the pressure levels
104 
105  nlevp = prs % nval
106  nlevq = q % nval
107 
108  iflip = 0
109  IF (prs % vals(1,1)-prs % vals(nlevp,1) < 0.0) THEN
110  iflip = 1
111  WRITE(message, *) "Pressure is in ascending order. Reorder the variables in vertical direction"
112  CALL fckit_log % warning(message)
113  END IF
114 
115  nobs = obsspace_get_nlocs(obss)
116  allocate(zstation(nobs))
117 
118  call obsspace_get_db(obss, "MetaData", "station_height", zstation)
119 
120  write(err_msg,*) "TRACE: ufo_groundgnss_metoffice_simobs: begin observation loop, nobs = ", nobs
121  call fckit_log%info(err_msg)
122 
123  hofx(:) = 0
124 
125  allocate(pressure(1:nlevp))
126  allocate(humidity(1:nlevq))
127  allocate(za(1:nlevp))
128  allocate(zb(1:nlevq))
129 
130  obs_loop: do iobs = 1, nobs
131 
132  IF (iflip == 1) THEN
133  do ilev = 1, nlevp
134  pressure(ilev) = prs % vals(nlevp-ilev+1,iobs)
135  za(ilev) = rho_heights % vals(nlevp-ilev+1,iobs)
136  end do
137  do ilev = 1, nlevq
138  humidity(ilev) = q % vals(nlevq-ilev+1,iobs)
139  zb(ilev) = theta_heights % vals(nlevq-ilev+1,iobs)
140  end do
141  ELSE
142  pressure = prs % vals(:,iobs)
143  humidity = q % vals(:,iobs)
144  za = rho_heights % vals(:,iobs)
145  zb = theta_heights % vals(:,iobs)
146  END IF
147 
148  call ops_groundgnss_forwardmodel(nlevp, &
149  nlevq, &
150  za(1:nlevp), &
151  zb(1:nlevq), &
152  pressure(1:nlevp), &
153  humidity(1:nlevq), &
154  self % min_temp_grad, &
155  1, &
156  zstation(iobs), &
157  hofx(iobs))
158 
159  write(message,'(A,10I6)') "Size of hofx = ", shape(hofx)
160  call fckit_log%debug(message)
161  write(message,'(A,F12.4)') "hofx(iobs) = ", hofx(iobs)
162  call fckit_log%debug(message)
163 
164  end do obs_loop
165 
166  write(err_msg,*) "TRACE: ufo_groundgnss_metoffice_simobs: completed"
167  call fckit_log%info(err_msg)
168 
169  deallocate(pressure)
170  deallocate(humidity)
171  deallocate(za)
172  deallocate(zb)
173 
174 end subroutine ufo_groundgnss_metoffice_simobs
175 ! ------------------------------------------------------------------------------
176 
177 
178 SUBROUTINE ops_groundgnss_forwardmodel(nlevp, &
179  nlevq, &
180  za, &
181  zb, &
182  pressure, &
183  humidity, &
184  gbgnss_min_temp_grad, &
185  nobs, &
186  zStation, &
187  Model_ZTD)
188 
189 INTEGER, INTENT(IN) :: nlevp ! no. of p levels in state vec.
190 INTEGER, INTENT(IN) :: nlevq ! no. of theta levels
191 REAL(kind_real), INTENT(IN) :: za(1:nlevp) ! heights of rho levs
192 REAL(kind_real), INTENT(IN) :: zb(1:nlevq) ! heights of theta levs
193 REAL(kind_real), INTENT(IN) :: pressure(1:nlevp) ! Model background pressure
194 REAL(kind_real), INTENT(IN) :: humidity(1:nlevq) ! Model background specific humidity
195 REAL(kind_real), INTENT(IN) :: gbgnss_min_temp_grad ! The minimum temperature gradient which is used
196 INTEGER, INTENT(IN) :: nobs ! Number of observations
197 
198 REAL(kind_real), INTENT(IN) :: zStation ! Station heights
199 REAL(kind_real), INTENT(INOUT) :: Model_ZTD ! Model forecast of the observations
200 
201 !
202 ! Things that may need to be output, as they are used by the TL/AD calculation
203 !
204 
205 REAL(kind_real) :: pN(nlevq) ! Presure on theta levels
206 REAL(kind_real), ALLOCATABLE :: refrac(:) ! Model refractivity
207 LOGICAL :: refracerr ! Refraction error
208 INTEGER :: nRefLevels ! Number of levels in refractivity calculation
209 REAL(kind_real) :: TopCorrection ! Zenith Total Delay Top of atmos correction
210 !
211 ! Local parameters
212 !
213 integer, parameter :: max_string = 800 ! Length of strings
214 character(len=*), parameter :: myname_ = "Ops_Groundgnss_ForwardModel"
215 !
216 ! Local variables
217 !
218 INTEGER :: nstate ! no. of levels in state vec.
219 REAL(kind_real) :: x(1:nlevp+nlevq) ! state vector
220 character(max_string) :: err_msg ! Error message to be output
221 character(max_string) :: message ! General message for output
222 
223 REAL(kind_real), ALLOCATABLE :: model_heights(:) ! Geopotential heights of the refractivity levels (not needed for this oper)
224 
225 ! The model data must be on a staggered grid, with nlevp = nlevq+1
226 IF (nlevp /= nlevq + 1) THEN
227  write(err_msg,*) myname_ // ':' // ' Data must be on a staggered grid nlevp, nlevq = ', nlevp, nlevq
228  call fckit_log % warning(err_msg)
229  write(err_msg,*) myname_ // ':' // ' error: number of levels inconsistent!'
230  call abor1_ftn(err_msg)
231 END IF
232 
233 CALL ufo_calculate_refractivity(nlevp, &
234  nlevq, &
235  za, &
236  zb, &
237  pressure, &
238  humidity, &
239  .true., & ! vert_interp_ops
240  .false., & ! pseudo_ops
241  gbgnss_min_temp_grad, &
242  refracerr, &
243  nreflevels, &
244  refrac, &
245  model_heights)
246 
247 CALL ops_groundgnss_topcorrection(pressure, &
248  nlevq, &
249  za, &
250  zb, &
251  topcorrection)
252 
253 
254 CALL ops_groundgnss_ztd (nlevq, &
255  refrac, &
256  zb, &
257  zstation, &
258  model_ztd)
259 
260 model_ztd = model_ztd + topcorrection
261 
262 write(message,'(A,F16.14)') "Model_ZTD = ", model_ztd
263 call fckit_log%debug(message)
264 
265 
266 END SUBROUTINE ops_groundgnss_forwardmodel
267 
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 Met Office forward operator.
subroutine ufo_groundgnss_metoffice_setup(self, f_conf)
subroutine ops_groundgnss_forwardmodel(nlevp, nlevq, za, zb, pressure, humidity, gbgnss_min_temp_grad, nobs, zStation, Model_ZTD)
subroutine ufo_groundgnss_metoffice_simobs(self, geovals, hofx, obss)
subroutine, public ops_groundgnss_topcorrection(P, nlevq, za, zb, TopCorrection)
subroutine, public ops_groundgnss_ztd(nlevq, refrac, zb, zStation, Model_ZTD)
Module for containing a general refractivity forward operator and its K-matrix.
subroutine, public ufo_calculate_refractivity(nlevP, nlevq, za, zb, P, q, vert_interp_ops, pseudo_ops, min_temp_grad, refracerr, nRefLevels, refractivity, model_heights, temperature, interp_pressure)
Calculation of the refractivity from the pressure and specific humidity.
character(len=maxvarlen), parameter, public var_prsi
character(len=maxvarlen), parameter, public var_q
character(len=maxvarlen), parameter, public var_zi
character(len=maxvarlen), parameter, public var_z
type to hold interpolated field for one variable, one observation
type to hold interpolated fields required by the obs operators