UFO
ufo_SatTCWV_mod.F90
Go to the documentation of this file.
1 !
2 ! (C) Crown Copyright 2021 Met Office
3 !
4 !
5 ! This software is licensed under the terms of the Apache Licence Version 2.0
6 ! which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
7 
8 !> Fortran module for satellite precipitable water observation operator
9 
11 
12  use iso_c_binding
13  use kinds
14  use oops_variables_mod
15  use ufo_vars_mod
16  use ufo_geovals_mod
18  use ufo_basis_mod, only: ufo_basis
19  use obsspace_mod
20  use fckit_log_module, only: fckit_log
21 
22 ! Generic routines from elsewhere in jedi
23  use missing_values_mod
24  use ufo_constants_mod, only: one, zero, half, grav ! Gravitational field strength
25 
26  implicit none
27  public :: ufo_sattcwv
28  private
29 
30  !> Fortran derived type for sattcwv trajectory
31  type, extends(ufo_basis) :: ufo_sattcwv
32  contains
33  procedure :: setup => ufo_sattcwv_setup
34  procedure :: simobs => ufo_sattcwv_simobs
35  final :: destructor
36  end type ufo_sattcwv
37 
38 contains
39 
40 ! ------------------------------------------------------------------------------
41 subroutine ufo_sattcwv_setup(self, f_conf)
42 
43  use fckit_configuration_module, only: fckit_configuration
44  implicit none
45  class(ufo_sattcwv), intent(inout) :: self
46  type(fckit_configuration), intent(in) :: f_conf
47 
48 end subroutine ufo_sattcwv_setup
49 
50 ! ------------------------------------------------------------------------------
51 subroutine destructor(self)
52  implicit none
53  type(ufo_sattcwv), intent(inout) :: self
54 end subroutine destructor
55 ! ------------------------------------------------------------------------------
56 ! percipitable water observation operator
57 subroutine ufo_sattcwv_simobs(self, geovals, hofx, obss)
58  use kinds
60  use iso_c_binding
61  use obsspace_mod
62 
63  implicit none
64 
65  class(ufo_sattcwv), intent(in) :: self ! The object in which this operator is
66  type(ufo_geovals), intent(in) :: geovals ! Model vals at Obs locs
67  real(kind_real), intent(inout) :: hofx(:) ! Simulated Obs
68  type(c_ptr), value, intent(in) :: obss ! The obs and metadata
69 
70  ! Local variables
71  !
72  type(ufo_geoval), pointer :: prs ! Model background values of air pressure
73  type(ufo_geoval), pointer :: psfc ! Model background values of surface pressure
74  type(ufo_geoval), pointer :: q ! Model background values of specific humidity
75  logical :: ascend ! Flag on direction of model levels
76  integer :: iobs ! Counter
77  integer :: nlocs ! number of observations
78  integer :: ilev1 ! starting level for loop
79  integer :: ilev2 ! ending level for loop
80  integer :: inc ! increment to level loop
81  integer :: ibot ! index of second lowest level
82  integer :: isfc ! index of lowest level
83  integer, parameter :: max_string = 800
84  character(max_string) :: err_msg ! Error message for output
85  character(max_string) :: message ! General message for output
86  character(len=*), parameter :: myname_ = "ufo_sattcwv_simobs"
87 
88  ! check if nlocs is consistent in geovals & hofx
89  if (geovals%nlocs /= size(hofx)) then
90  write(err_msg,*) myname_, ' error: nlocs ',geovals%nlocs,' inconsistent with HofX size',size(hofx)
91  call abor1_ftn(err_msg)
92  endif
93 
94  ! get geovals of atmospheric pressure in (Pa) and q (kg/kg)
95  !
96  call ufo_geovals_get_var(geovals, var_ps, psfc)
97  call ufo_geovals_get_var(geovals, var_prsi, prs)
98  call ufo_geovals_get_var(geovals, var_q, q)
99 ! The model data must be on a staggered grid, with nlevp = nlevq+1
100  IF (prs % nval /= q % nval + 1) THEN
101  write(err_msg,*) myname_ // ':' // &
102  ' Data must be on a staggered grid nlevp, nlevq = ',prs%nval,q%nval
103  call fckit_log % warning(err_msg)
104  write(err_msg,*) myname_ // ':' // ' error: number of levels inconsistent!'
105  call abor1_ftn(err_msg)
106  END IF
107 !
108 ! Determine if models levels are ascending or descending and set up indices for level loop
109 ! Note assumes model levels stay same for all obs
110 !
111  ascend = .false.
112  if((prs%vals(1,1)-prs%vals(2,1)) > zero )ascend = .true.
113  if (ascend)then ! Model level starts above surface
114  ilev1 = 1
115  ilev2 = q%nval
116  inc = 1
117  ibot = 2
118  isfc = 1
119  else ! Model level starts at top of atmosphere
120  ilev1 = q%nval
121  ilev2 = 1
122  inc = -1
123  ibot = q%nval
124  isfc = q%nval
125  endif
126 
127  ! get number of observations
128  nlocs = obsspace_get_nlocs(obss)
129  !
130  obs_loop: do iobs = 1, nlocs
131  !
132  call sattcwv_forwardmodel(prs%nval, & ! Number of pressure levels
133  ilev1, & ! Starting pressure layer
134  ilev2, & ! Ending pressure layer
135  inc, & ! Layer increment
136  ibot, & ! Lowest layer inc surface
137  isfc, & ! Level next to surface
138  psfc % vals(1,iobs), & ! Surface pressure (Pa)
139  prs % vals(:,iobs), & ! Pressure levels (Pa)
140  q % vals(:,iobs), & ! Mean layer specific humidity (kg/kg)
141  hofx(iobs)) ! Simulated precipitable water (kg/sq.m)
142 !
143  end do obs_loop
144 !
145  write(err_msg,*) "TRACE: ufo_sattcwv_simobs: completed"
146  call fckit_log%info(err_msg)
147 !
148 end subroutine ufo_sattcwv_simobs
149 ! ------------------------------------------------------------------------------
150 SUBROUTINE sattcwv_forwardmodel(nlevP, &
151  ilev1, &
152  ilev2, &
153  inc, &
154  ibot, &
155  isfc, &
156  psfc, &
157  prs, &
158  q, &
159  Model_SatTCWV)
160 !-------------------------------------------------------------------------------
161 !> Compute Total column water vapour amount from geovals water vapour profile.
162 !!
163 !! \details Heritage: Var_SatTCWVOperator.f90
164 !!
165 !! \author Met Office
166 !!
167 !! \date 05/01/2021: Created
168 !!
169 INTEGER, INTENT(IN) :: nlevp ! Number of pressure levels
170 INTEGER, INTENT(IN) :: ilev1 ! Starting layer
171 INTEGER, INTENT(IN) :: ilev2 ! Ending layer
172 INTEGER, INTENT(IN) :: inc ! loop increment
173 INTEGER, INTENT(IN) :: ibot ! lowest layer including surface
174 INTEGER, INTENT(IN) :: isfc ! lowest level next to surface
175 REAL(kind_real), INTENT(IN) :: psfc ! surface pressure (Pa)
176 REAL(kind_real), INTENT(IN) :: prs(1:nlevP) ! Model background pressure (Pa) at levels
177 REAL(kind_real), INTENT(IN) :: q(1:nlevP-1) ! Model background specific humidity (kg/kg)
178 REAL(kind_real), INTENT(INOUT) :: Model_SatTCWV ! Model forecast of the observations (kg/sq.m)
179 !
180 ! Local parameters
181 !
182 integer, parameter :: max_string = 800 ! Length of strings
183 character(len=*), parameter :: myname_ = "SatTCWV_ForwardModel"
184 !
185 ! Local variables
186 !
187 character(max_string) :: err_msg ! Error message to be output
188 character(max_string) :: message ! General message for output
189 REAL(kind_real) :: PDiff ! Pressure diff across layer
190 REAL(kind_real) :: GK ! 1/gravity
191 INTEGER :: i ! level counter
192 !-------------------------------------------------------------------------------
193 !1. Initialise variables and check model levels
194 !-------------------------------------------------------------------------------
195 pdiff = zero
196 gk = one / grav
197 model_sattcwv = zero
198 !
199 !-------------------------------------------------------------------------------
200 ! Calculate model equivalent of satellite total column water vapour.
201 !-------------------------------------------------------------------------------
202 !
203 ! Now integrate through atmosphere layers
204 DO i = ilev1, ilev2, inc
205  pdiff = prs(i) - prs(i+1) ! prs is pressure on level i
206 ! Include surface layer assuming surface q is same as q 10m but could use q2m in future
207  IF (i == isfc)pdiff = psfc - prs(ibot)
208 !
209  model_sattcwv = model_sattcwv + gk * q(i) * pdiff ! Accumulate layer water vapour conc
210 END DO
211 !
212 END SUBROUTINE sattcwv_forwardmodel
213 
214 end module ufo_sattcwv_mod
real(kind_real), parameter, public one
real(kind_real), parameter, public grav
real(kind_real), parameter, public zero
real(kind_real), parameter, public half
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 satellite precipitable water observation operator.
subroutine sattcwv_forwardmodel(nlevP, ilev1, ilev2, inc, ibot, isfc, psfc, prs, q, Model_SatTCWV)
subroutine destructor(self)
subroutine ufo_sattcwv_setup(self, f_conf)
subroutine ufo_sattcwv_simobs(self, geovals, hofx, obss)
character(len=maxvarlen), parameter, public var_prsi
character(len=maxvarlen), parameter, public var_q
character(len=maxvarlen), parameter, public var_ps
type to hold interpolated field for one variable, one observation
type to hold interpolated fields required by the obs operators
Fortran derived type for sattcwv trajectory.