UFO
ufo_atmvertinterplay_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 atmvertinterplay observation operator
7 
9 
10  use oops_variables_mod
11  use ufo_vars_mod
12 
13  implicit none
14  private
15 
16 !> Fortran derived type for the observation type
17  type, public :: ufo_atmvertinterplay
18  type(oops_variables), public :: obsvars
19  type(oops_variables), public :: geovars
20  integer, public, allocatable :: nlevels(:)
21  real, public, allocatable :: coefficients(:) ! unit conversion from geoval to obs
22  contains
23  procedure :: setup => ufo_atmvertinterplay_setup
24  procedure :: simobs => ufo_atmvertinterplay_simobs
25  end type ufo_atmvertinterplay
26 
27 contains
28 
29 ! ------------------------------------------------------------------------------
30 subroutine ufo_atmvertinterplay_setup(self, conf)
31 use iso_c_binding
32 use fckit_configuration_module, only: fckit_configuration
33 implicit none
34 class(ufo_atmvertinterplay), intent(inout) :: self
35 type(fckit_configuration), intent(in) :: conf
36 
37 character(kind=c_char,len=:), allocatable :: coord_name
38 character(kind=c_char,len=:), allocatable :: gvars(:)
39 real(kind=c_double), allocatable :: coefficients(:)
40 integer(kind=c_int), allocatable :: nlevels(:)
41 !Local Variables
42 integer :: ivar, nlevs=0, nvars=0, ngvars=0, ncoefs=0
43 
44 ! Check configurations
45 if (conf%has("geovals")) then
46  ngvars = conf%get_size("geovals")
47  call conf%get_or_die("geovals", gvars)
48  ! add to geovars list
49  do ivar = 1, ngvars
50  call self%geovars%push_back(gvars(ivar))
51  enddo
52 endif
53 
54 nvars = self%obsvars%nvars()
55 if (ngvars == 0 .and. nvars > 0) then
56  allocate(self%coefficients(nvars))
57  do ivar = 1, nvars
58  call self%geovars%push_back(self%obsvars%variable(ivar))
59  self%coefficients(ivar) = 1.0
60  enddo
61 endif
62 
63 if (conf%has("coefficients")) then
64  ncoefs = conf%get_size("coefficients")
65  call conf%get_or_die("coefficients", coefficients)
66  allocate(self%coefficients(ncoefs))
67  self%coefficients(1:ncoefs) = coefficients(1:ncoefs)
68 endif
69 
70 if (conf%has("nlevels")) then
71  nlevs = conf%get_size("nlevels")
72  call conf%get_or_die("nlevels", nlevels)
73  allocate(self%nlevels(nlevs))
74  self%nlevels(1:nlevs) = nlevels(1:nlevs)
75 endif
76 
77 ! Put pressure to the geovars (vars from the model) list
78 call self%geovars%push_back(var_prsi)
79 
80 end subroutine ufo_atmvertinterplay_setup
81 
82 ! ------------------------------------------------------------------------------
83 subroutine ufo_atmvertinterplay_simobs(self, geovals_in, obss, nvars, nlocs, hofx)
87 use obsspace_mod
88 implicit none
89 class(ufo_atmvertinterplay), intent(in) :: self
90 integer, intent(in) :: nvars, nlocs
91 type(ufo_geovals), intent(in) :: geovals_in
92 real(c_double), intent(inout) :: hofx(nvars, nlocs)
93 type(c_ptr), value, intent(in) :: obss
94 
95 ! Local variables
96 integer :: iobs, ivar, iprof
97 integer :: iz1, iz2, kk
98 integer :: k1, k2
99 integer :: nsig, nprof, nlev
100 real(kind_real), dimension(:), allocatable :: toppressure,botpressure,airpressure
101 type(ufo_geovals) :: geovals
102 type(ufo_geoval), pointer :: modelpressures, modelozone
103 character(len=MAXVARLEN) :: geovar
104 character(len=MAXVARLEN) :: var_zdir
105 real :: pob,delp4,delz,dz1
106 real(kind_real) :: rozcon, g
107 real(kind_real) :: topozp, botozp
108 real :: pindex
109 
110  ! Notes:
111  ! (1) Set desired vertical coordinate direction (top2bottom or bottom2top) based
112  ! on vertical coodinate variable and reload geoavls according to the set
113  ! direction
114  ! (2) This is done because this observation operator assums pressure levels
115  ! are from bottom to top (bottom2top) with morelpressure(1) for surface and
116  ! modelpressure(nsig+1) for model top
117 
118  call ufo_geovals_copy(geovals_in, geovals) ! dont want to change geovals_in
119  var_zdir = var_prsi ! vertical coordinate variable
120  call ufo_geovals_reorderzdir(geovals, var_zdir, "bottom2top")
121 
122  ! Get pressure profiles from geovals [Pa]
123  call ufo_geovals_get_var(geovals, var_prsi, modelpressures)
124  nsig = modelpressures%nval - 1
125 
126  allocate(toppressure(nlocs))
127  allocate(botpressure(nlocs))
128  allocate(airpressure(nlocs))
129 
130  do ivar = 1, nvars
131  write(6,*) 'ufo_atmvertinterplay_simobs: self%nlevels = ', self%nlevels
132  if (self%nlevels(ivar) == 1) then ! total column ozone
133  do iobs = 1, nlocs
134  toppressure(iobs) = modelpressures%vals(nsig+1, iobs)
135  botpressure(iobs) = modelpressures%vals(1, iobs)
136  enddo
137  else
138  !Obs pressures read in as Pa
139  call obsspace_get_db(obss, "MetaData", "air_pressure", airpressure)
140  nlev = self%nlevels(ivar)
141  nprof = nlocs/nlev
142  iobs = 0
143  do iprof = 1, nprof
144  do kk = 1, nlev
145  k1 = kk
146  k2 = kk - 1
147  if (k2 == 0) k2 = 1
148  if (kk == nlev) then
149  k1 = nlev - 1
150  k2 = 1
151  endif
152  iobs = iobs+1
153  toppressure(iobs) = airpressure(k2)
154  botpressure(iobs) = airpressure(k1)
155  if( kk== 1 ) then
156  toppressure(iobs) =modelpressures%vals(nsig+1, iobs)
157  botpressure(iobs) = airpressure(1)
158  else if( kk == nlev) then
159  toppressure(iobs) = modelpressures%vals(nsig+1, iobs)
160  botpressure(iobs) = modelpressures%vals(1, iobs)
161  endif
162  enddo
163  enddo
164  endif
165 
166  !Get the name of input variable in geovals
167  geovar = self%geovars%variable(ivar)
168 
169  !Get model output
170  call ufo_geovals_get_var(geovals, geovar, modelozone)
171 
172  do iobs = 1, nlocs
173  topozp = pindex(nsig+1, modelpressures%vals(1, iobs), toppressure(iobs))
174  botozp = pindex(nsig+1, modelpressures%vals(1, iobs), botpressure(iobs))
175 
176  pob = botozp
177  iz1 = topozp
178  if (iz1>nsig) iz1=nsig
179  iz2 = pob
180  !For total column ozone
181  if(iz1 .eq. nsig .and. iz2 .lt.7)iz2 = 1
182  g = 0.
183  dz1 = topozp
184  do kk=iz1,iz2,-1
185  delz = 1.
186  if(kk==iz1)delz=dz1-iz1
187  if (kk==iz2) delz=delz-pob+iz2
188  !For total column ozone
189  if(iz1 .eq. nsig .and. iz2 .eq. 1)delz = 1
190  !Interpolate in cbars
191  delp4 = (modelpressures%vals(kk,iobs)-modelpressures%vals(kk+1,iobs)) ! [Pa]
192  g = g + modelozone%vals(kk,iobs)*self%coefficients(ivar)*(delz*delp4)
193  enddo
194  hofx(ivar,iobs) = g
195  dz1 = pob
196  enddo
197  enddo
198  deallocate(toppressure)
199  deallocate(botpressure)
200  call ufo_geovals_delete(geovals)
201 
202 end subroutine ufo_atmvertinterplay_simobs
203 
204 
205 ! ------------------------------------------------------------------------------
206 
207 end module ufo_atmvertinterplay_mod
ufo_atmvertinterplay_mod::ufo_atmvertinterplay_setup
subroutine ufo_atmvertinterplay_setup(self, conf)
Definition: ufo_atmvertinterplay_mod.F90:31
ufo_atmvertinterplay_mod::ufo_atmvertinterplay
Fortran derived type for the observation type.
Definition: ufo_atmvertinterplay_mod.F90:17
ufo_geovals_mod::ufo_geovals_delete
subroutine, public ufo_geovals_delete(self)
Definition: ufo_geovals_mod.F90:107
ufo_geovals_mod
Definition: ufo_geovals_mod.F90:7
ufo_vars_mod::var_prsi
character(len=maxvarlen), parameter, public var_prsi
Definition: ufo_variables_mod.F90:26
ufo_constants_mod
Definition: ufo_constants_mod.F90:2
ufo_vars_mod
Definition: ufo_variables_mod.F90:8
ufo_atmvertinterplay_mod::ufo_atmvertinterplay_simobs
subroutine ufo_atmvertinterplay_simobs(self, geovals_in, obss, nvars, nlocs, hofx)
Definition: ufo_atmvertinterplay_mod.F90:84
ufo_geovals_mod::ufo_geovals_get_var
subroutine, public ufo_geovals_get_var(self, varname, geoval)
Definition: ufo_geovals_mod.F90:128
ufo_geovals_mod::ufo_geovals
type to hold interpolated fields required by the obs operators
Definition: ufo_geovals_mod.F90:47
ufo_geovals_mod::ufo_geoval
type to hold interpolated field for one variable, one observation
Definition: ufo_geovals_mod.F90:40
ufo_atmvertinterplay_mod
Fortran module for atmvertinterplay observation operator.
Definition: ufo_atmvertinterplay_mod.F90:8
conf
Definition: conf.py:1
ufo_geovals_mod::ufo_geovals_reorderzdir
subroutine, public ufo_geovals_reorderzdir(self, varname, zdir)
Definition: ufo_geovals_mod.F90:334
ufo_geovals_mod::ufo_geovals_copy
subroutine, public ufo_geovals_copy(self, other)
Copy one GeoVaLs object into another.
Definition: ufo_geovals_mod.F90:506