10 use oops_variables_mod
12 use missing_values_mod
23 type(oops_variables),
public :: obsvars
24 type(oops_variables),
public :: geovars
25 integer :: nlayers_kernel
26 real(kind_real),
allocatable,
dimension(:) :: ak_kernel, bk_kernel
27 character(kind=c_char,len=:),
allocatable :: obskernelvar, tracervars(:)
28 logical :: troposphere, totalcolumn
29 real(kind_real) :: convert_factor_model, convert_factor_hofx
40 use fckit_configuration_module,
only: fckit_configuration
44 type(fckit_configuration),
intent(in) :: f_conf
45 type(fckit_configuration) :: f_confOpts
47 integer :: ivar, nvars
48 character(len=max_string) :: err_msg
49 character(len=:),
allocatable :: str_array(:)
52 call f_conf%get_or_die(
"obs options",f_confopts)
54 call f_confopts%get_or_die(
"nlayers_kernel", self%nlayers_kernel)
55 nlevs_yaml = f_confopts%get_size(
"ak")
56 if (nlevs_yaml /= self%nlayers_kernel+1)
then
57 write(err_msg, *)
"ufo_avgkernel_setup error: YAML nlayers_kernel != size of ak array"
58 call abor1_ftn(err_msg)
60 nlevs_yaml = f_confopts%get_size(
"bk")
61 if (nlevs_yaml /= self%nlayers_kernel+1)
then
62 write(err_msg, *)
"ufo_avgkernel_setup error: YAML nlayers_kernel != size of bk array"
63 call abor1_ftn(err_msg)
67 allocate(self%ak_kernel(nlevs_yaml))
68 allocate(self%bk_kernel(nlevs_yaml))
69 call f_confopts%get_or_die(
"ak", self%ak_kernel)
70 call f_confopts%get_or_die(
"bk", self%bk_kernel)
73 if (.not. f_confopts%get(
"AvgKernelVar", self%obskernelvar))
then
74 self%obskernelvar =
"averaging_kernel"
78 nvars = self%obsvars%nvars()
79 call f_confopts%get_or_die(
"tracer variables", str_array)
80 self%tracervars = str_array
83 if (.not. f_confopts%get(
"tropospheric column", self%troposphere)) self%troposphere = .false.
84 if (.not. f_confopts%get(
"total column", self%totalcolumn)) self%totalcolumn = .false.
87 if (self%troposphere .and. self%totalcolumn)
then
88 write(err_msg, *)
"ufo_avgkernel_setup error: both tropospheric and total column set to TRUE, only one can be TRUE"
89 call abor1_ftn(err_msg)
93 if (.not. f_confopts%get(
"model units coeff", self%convert_factor_model)) self%convert_factor_model =
one
94 if (.not. f_confopts%get(
"hofx units coeff", self%convert_factor_hofx)) self%convert_factor_hofx =
one
99 call self%geovars%push_back(self%tracervars(ivar))
102 call self%geovars%push_back(
var_ps)
104 call self%geovars%push_back(
var_prs)
105 call self%geovars%push_back(
var_prsi)
107 call self%geovars%push_back(
var_ts)
109 call self%geovars%push_back(
var_zi)
132 integer,
intent(in) :: nvars, nlocs
134 real(c_double),
intent(inout) :: hofx(nvars, nlocs)
135 type(c_ptr),
value,
intent(in) :: obss
138 type(
ufo_geoval),
pointer :: prsi, prsl, psfc, temp, phii, tracer
139 integer :: ivar, iobs, ilev
140 character(len=MAXVARLEN) :: geovar, varstring
141 character(len=4) :: levstr
142 real(kind_real),
allocatable,
dimension(:,:) :: avgkernel_obs, prsl_obs, prsi_obs
143 real(kind_real),
allocatable,
dimension(:) :: airmass_tot, airmass_trop
144 integer,
allocatable,
dimension(:) :: troplev_obs
145 real(kind_real) :: hofx_tmp
147 real(c_double) :: missing
149 missing = missing_value(missing)
163 allocate(avgkernel_obs(self%nlayers_kernel, nlocs))
164 do ilev = 1, self%nlayers_kernel
165 write(levstr, fmt =
"(I3)") ilev
166 levstr = adjustl(levstr)
167 varstring = trim(self%obskernelvar)//
"_"//trim(levstr)
168 call obsspace_get_db(obss,
"MetaData", trim(varstring), avgkernel_obs(ilev, :))
172 allocate(prsl_obs(self%nlayers_kernel, nlocs))
173 allocate(prsi_obs(self%nlayers_kernel+1, nlocs))
175 do ilev = 1, self%nlayers_kernel+1
176 prsi_obs(ilev,:) = self%ak_kernel(ilev) + self%bk_kernel(ilev) * psfc%vals(1,:)
179 do ilev = 1, self%nlayers_kernel
180 prsl_obs(ilev,:) = (prsi_obs(ilev,:) + prsi_obs(ilev+1,:)) *
half
183 if (self%troposphere)
then
184 allocate(troplev_obs(nlocs))
185 allocate(airmass_trop(nlocs))
186 allocate(airmass_tot(nlocs))
187 call obsspace_get_db(obss,
"MetaData",
"troposphere_layer_index", troplev_obs)
188 call obsspace_get_db(obss,
"MetaData",
"air_mass_factor_troposphere", airmass_trop)
189 call obsspace_get_db(obss,
"MetaData",
"air_mass_factor_total", airmass_tot)
194 geovar = self%tracervars(ivar)
197 if (avgkernel_obs(1,iobs) /= missing)
then
198 if (self%troposphere)
then
200 prsi_obs(:,iobs), prsi%vals(:,iobs), &
201 prsl_obs(:,iobs), prsl%vals(:,iobs), temp%vals(:,iobs),&
202 phii%vals(:,iobs), tracer%vals(:,iobs)*self%convert_factor_model, &
203 hofx_tmp, troplev_obs(iobs), airmass_tot(iobs), airmass_trop(iobs))
204 hofx(ivar,iobs) = hofx_tmp * self%convert_factor_hofx
205 else if (self%totalcolumn)
then
207 prsi_obs(:,iobs), prsi%vals(:,iobs), &
208 prsl_obs(:,iobs), prsl%vals(:,iobs), temp%vals(:,iobs),&
209 phii%vals(:,iobs), tracer%vals(:,iobs)*self%convert_factor_model, &
211 hofx(ivar,iobs) = hofx_tmp * self%convert_factor_hofx
214 hofx(ivar,iobs) = missing
subroutine simulate_column_ob(nlayers_obs, nlayers_model, avgkernel_obs, prsi_obs, prsi_model, prsl_obs, prsl_model, temp_model, zi_model, profile_model, hofx, troplev_obs, airmass_tot, airmass_trop)
Fortran module for averaging kernel observation operator.
subroutine destructor(self)
subroutine ufo_avgkernel_simobs(self, geovals_in, obss, nvars, nlocs, hofx)
integer, parameter max_string
subroutine ufo_avgkernel_setup(self, f_conf)
real(kind_real), parameter, public one
real(kind_real), parameter, public half
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_get_var(self, varname, geoval)
character(len=maxvarlen), parameter, public var_prsi
character(len=maxvarlen), parameter, public var_prs
character(len=maxvarlen), parameter, public var_zi
character(len=maxvarlen), parameter, public var_ts
character(len=maxvarlen), parameter, public var_ps
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