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
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 ! ------------------------------------------------------------------------------
84 subroutine ufo_atmvertinterplay_simobs(self, geovals_in, obss, nvars, nlocs, hofx)
88 use obsspace_mod
89 implicit none
90 class(ufo_atmvertinterplay), intent(in) :: self
91 integer, intent(in) :: nvars, nlocs
92 type(ufo_geovals), intent(in) :: geovals_in
93 real(c_double), intent(inout) :: hofx(nvars, nlocs)
94 type(c_ptr), value, intent(in) :: obss
95 
96 ! Local variables
97 integer :: iobs, ivar
98 integer :: nsig, nlevs
99 real(kind_real), dimension(:), allocatable :: toppressure,botpressure,airpressure
100 type(ufo_geovals) :: geovals
101 type(ufo_geoval), pointer :: modelpressures, modelozone
102 character(len=MAXVARLEN) :: geovar
103 character(len=MAXVARLEN) :: var_zdir
104 real :: pob,delp4,delz,dz1
105 real(kind_real) :: layer_oz
106 
107  ! Notes:
108  ! (1) Set desired vertical coordinate direction (top2bottom or bottom2top) based
109  ! on vertical coodinate variable and reload geoavls according to the set
110  ! direction
111  ! (2) This is done because this observation operator assums pressure levels
112  ! are from bottom to top (bottom2top) with morelpressure(1) for surface and
113  ! modelpressure(nsig+1) for model top
114 
115  call ufo_geovals_copy(geovals_in, geovals) ! dont want to change geovals_in
116  var_zdir = var_prsi ! vertical coordinate variable
117  call ufo_geovals_reorderzdir(geovals, var_zdir, "bottom2top")
118 
119  ! Get pressure profiles from geovals [Pa]
120  call ufo_geovals_get_var(geovals, var_prsi, modelpressures)
121  nsig = modelpressures%nval - 1
122  ! Allocate pressure limits and get air_pressure metadata from obs
123  allocate(toppressure(nlocs))
124  allocate(botpressure(nlocs))
125  allocate(airpressure(nlocs))
126  call obsspace_get_db(obss, "MetaData", "air_pressure", airpressure)
127 
128  do ivar = 1, nvars
129  write(6,*) 'ufo_atmvertinterplay_simobs: self%nlevels = ', self%nlevels
130  nlevs = self%nlevels(ivar)
131  call get_integral_limits(airpressure, botpressure, toppressure, modelpressures%vals(:,:), nlevs, nlocs, nsig)
132 
133  !Get the name of input variable in geovals
134  geovar = self%geovars%variable(ivar)
135 
136  !Get model output
137  call ufo_geovals_get_var(geovals, geovar, modelozone)
138 
139  do iobs = 1, nlocs
140  call apply_layer_integral(self%coefficients(ivar), modelozone%vals(:,iobs), modelpressures%vals(:,iobs), botpressure(iobs), toppressure(iobs), nsig, layer_oz )
141  hofx(ivar,iobs) = layer_oz
142  enddo
143  enddo
144  deallocate(toppressure)
145  deallocate(botpressure)
146  call ufo_geovals_delete(geovals)
147 end subroutine ufo_atmvertinterplay_simobs
148 
149 
150 ! ------------------------------------------------------------------------------
151 
152 end module ufo_atmvertinterplay_mod
Fortran module for atmvertinterplay observation operator.
subroutine ufo_atmvertinterplay_setup(self, conf)
subroutine ufo_atmvertinterplay_simobs(self, geovals_in, obss, nvars, nlocs, hofx)
subroutine, public ufo_geovals_reorderzdir(self, varname, zdir)
subroutine, public ufo_geovals_copy(self, other)
Copy one GeoVaLs object into another.
subroutine, public ufo_geovals_delete(self)
subroutine, public ufo_geovals_get_var(self, varname, geoval)
character(len=maxvarlen), parameter, public var_prsi
Fortran module to perform linear interpolation.
subroutine apply_layer_integral(coefficient, modelozone, modelpressure, botpressure, toppressure, nsig, layer_oz)
subroutine get_integral_limits(airpressure, botpressure, toppressure, modelpressure, nlevs, nlocs, nsig)
Fortran derived type for the observation type.
type to hold interpolated field for one variable, one observation
type to hold interpolated fields required by the obs operators