12 use missing_values_mod
24 type(oops_variables),
public :: obsvars
25 type(oops_variables),
public :: geovars
26 integer :: nlayers_kernel
27 integer :: nlocs, nvars, nval
28 real(kind_real),
allocatable,
dimension(:) :: ak_kernel, bk_kernel
29 character(kind=c_char,len=:),
allocatable :: obskernelvar, tracervars(:)
30 logical :: troposphere, totalcolumn
31 real(kind_real) :: convert_factor_model, convert_factor_hofx
32 real(kind_real),
allocatable,
dimension(:,:) :: avgkernel_obs, prsl_obs, prsi_obs
33 real(kind_real),
allocatable,
dimension(:,:) :: prsl, prsi, temp, phii
34 real(kind_real),
allocatable,
dimension(:) :: airmass_tot, airmass_trop
35 integer,
allocatable,
dimension(:) :: troplev_obs
50 use fckit_configuration_module,
only: fckit_configuration
54 type(fckit_configuration),
intent(in) :: f_conf
55 type(fckit_configuration) :: f_confOpts
57 integer :: ivar, nvars
58 character(len=max_string) :: err_msg
59 character(len=:),
allocatable :: str_array(:)
62 call f_conf%get_or_die(
"obs options",f_confopts)
64 call f_confopts%get_or_die(
"nlayers_kernel", self%nlayers_kernel)
65 nlevs_yaml = f_confopts%get_size(
"ak")
66 if (nlevs_yaml /= self%nlayers_kernel+1)
then
67 write(err_msg, *)
"ufo_avgkernel_tlad_setup error: YAML nlayers_kernel != size of ak array"
68 call abor1_ftn(err_msg)
70 nlevs_yaml = f_confopts%get_size(
"bk")
71 if (nlevs_yaml /= self%nlayers_kernel+1)
then
72 write(err_msg, *)
"ufo_avgkernel_tlad_setup error: YAML nlayers_kernel != size of bk array"
73 call abor1_ftn(err_msg)
77 allocate(self%ak_kernel(nlevs_yaml))
78 allocate(self%bk_kernel(nlevs_yaml))
79 call f_confopts%get_or_die(
"ak", self%ak_kernel)
80 call f_confopts%get_or_die(
"bk", self%bk_kernel)
83 if (.not. f_confopts%get(
"AvgKernelVar", self%obskernelvar))
then
84 self%obskernelvar =
"averaging_kernel"
88 nvars = self%obsvars%nvars()
89 call f_confopts%get_or_die(
"tracer variables", str_array)
90 self%tracervars = str_array
93 if (.not. f_confopts%get(
"tropospheric column", self%troposphere)) self%troposphere = .false.
94 if (.not. f_confopts%get(
"total column", self%totalcolumn)) self%totalcolumn = .false.
97 if (self%troposphere .and. self%totalcolumn)
then
98 write(err_msg, *)
"ufo_avgkernel_tlad_setup error: both tropospheric and total column set to TRUE, only one can be TRUE"
99 call abor1_ftn(err_msg)
103 if (.not. f_confopts%get(
"model units coeff", self%convert_factor_model)) self%convert_factor_model =
one
104 if (.not. f_confopts%get(
"hofx units coeff", self%convert_factor_hofx)) self%convert_factor_hofx =
one
109 call self%geovars%push_back(self%tracervars(ivar))
132 type(c_ptr),
value,
intent(in) :: obss
136 integer :: ivar, iobs, ilev
137 character(len=MAXVARLEN) :: varstring
138 character(len=4) :: levstr
140 type(
ufo_geoval),
pointer :: prsl, temp, phii, p_temp
143 self%nlocs = obsspace_get_nlocs(obss)
144 self%nvars = obsspace_get_nvars(obss)
147 call ufo_geovals_copy(geovals_in, geovals)
149 if (p_temp%vals(1,1) < p_temp%vals(p_temp%nval,1) )
then
150 self%flip_it = .true.
152 self%flip_it = .false.
154 call ufo_geovals_reorderzdir(geovals,
var_prs,
"bottom2top")
162 self%nval = prsl%nval
164 allocate(self%prsl(self%nval, self%nlocs))
165 allocate(self%temp(self%nval, self%nlocs))
166 allocate(self%phii(self%nval+1, self%nlocs))
167 allocate(self%prsi(self%nval+1, self%nlocs))
168 do iobs = 1, self%nlocs
169 self%prsl(:,iobs) = prsl%vals(:,iobs)
170 self%prsi(:,iobs) = prsi%vals(:,iobs)
171 self%temp(:,iobs) = temp%vals(:,iobs)
172 self%phii(:,iobs) = phii%vals(:,iobs)
178 allocate(self%avgkernel_obs(self%nlayers_kernel, self%nlocs))
179 do ilev = 1, self%nlayers_kernel
180 write(levstr, fmt =
"(I3)") ilev
181 levstr = adjustl(levstr)
182 varstring = trim(self%obskernelvar)//
"_"//trim(levstr)
183 call obsspace_get_db(obss,
"MetaData", trim(varstring), self%avgkernel_obs(ilev, :))
187 allocate(self%prsl_obs(self%nlayers_kernel, self%nlocs))
188 allocate(self%prsi_obs(self%nlayers_kernel+1, self%nlocs))
190 do ilev = 1, self%nlayers_kernel+1
191 self%prsi_obs(ilev,:) = self%ak_kernel(ilev) + self%bk_kernel(ilev) * psfc%vals(1,:)
194 do ilev = 1, self%nlayers_kernel
195 self%prsl_obs(ilev,:) = (self%prsi_obs(ilev,:) + self%prsi_obs(ilev+1,:)) *
half
198 if (self%troposphere)
then
199 allocate(self%troplev_obs(self%nlocs))
200 allocate(self%airmass_trop(self%nlocs))
201 allocate(self%airmass_tot(self%nlocs))
202 call obsspace_get_db(obss,
"MetaData",
"troposphere_layer_index", self%troplev_obs)
203 call obsspace_get_db(obss,
"MetaData",
"air_mass_factor_troposphere", self%airmass_trop)
204 call obsspace_get_db(obss,
"MetaData",
"air_mass_factor_total", self%airmass_tot)
218 integer,
intent(in) :: nvars, nlocs
219 real(c_double),
intent(inout) :: hofx(nvars, nlocs)
220 type(c_ptr),
value,
intent(in) :: obss
222 integer :: ivar, iobs
223 character(len=MAXVARLEN) :: geovar
224 real(kind_real) :: hofx_tmp
226 real(c_double) :: missing
228 missing = missing_value(missing)
230 call ufo_geovals_copy(geovals_in, geovals)
234 geovar = self%tracervars(ivar)
237 if (self%avgkernel_obs(1,iobs) /= missing)
then
238 if(self%flip_it) tracer%vals(1:tracer%nval,iobs) = tracer%vals(tracer%nval:1:-1,iobs)
239 if (self%troposphere)
then
241 self%prsi_obs(:,iobs), self%prsi(:,iobs),&
242 self%prsl_obs(:,iobs), self%prsl(:,iobs), self%temp(:,iobs),&
243 self%phii(:,iobs), tracer%vals(:,iobs)*self%convert_factor_model, &
244 hofx_tmp, self%troplev_obs(iobs), self%airmass_tot(iobs), self%airmass_trop(iobs))
245 hofx(ivar,iobs) = hofx_tmp * self%convert_factor_hofx
246 else if (self%totalcolumn)
then
248 self%prsi_obs(:,iobs), self%prsi(:,iobs),&
249 self%prsl_obs(:,iobs), self%prsl(:,iobs), self%temp(:,iobs),&
250 self%phii(:,iobs), tracer%vals(:,iobs)*self%convert_factor_model, &
252 hofx(ivar,iobs) = hofx_tmp * self%convert_factor_hofx
255 hofx(ivar,iobs) = missing
259 call ufo_geovals_delete(geovals)
272 integer,
intent(in) :: nvars, nlocs
273 real(c_double),
intent(in) :: hofx(nvars, nlocs)
274 type(c_ptr),
value,
intent(in) :: obss
276 character(len=MAXVARLEN) :: geovar
278 real(kind_real) :: hofx_tmp
279 integer :: ivar, iobs
280 real(c_double) :: missing
282 missing = missing_value(missing)
284 if (.not. geovals_in%linit ) geovals_in%linit=.true.
288 geovar = self%tracervars(ivar)
292 if (hofx(ivar,iobs) /= missing)
then
293 if (self%troposphere)
then
294 hofx_tmp = hofx(ivar,iobs) * self%convert_factor_hofx
296 self%prsi_obs(:,iobs), self%prsi(:,iobs),&
297 self%prsl_obs(:,iobs), self%prsl(:,iobs), self%temp(:,iobs),&
298 self%phii(:,iobs), tracer%vals(:,iobs), &
299 hofx_tmp, self%troplev_obs(iobs), self%airmass_tot(iobs), self%airmass_trop(iobs))
300 tracer%vals(:,iobs) = tracer%vals(:,iobs) * self%convert_factor_model
301 else if (self%totalcolumn)
then
302 hofx_tmp = hofx(ivar,iobs) * self%convert_factor_hofx
304 self%prsi_obs(:,iobs), self%prsi(:,iobs),&
305 self%prsl_obs(:,iobs), self%prsl(:,iobs), self%temp(:,iobs),&
306 self%phii(:,iobs), tracer%vals(:,iobs), hofx_tmp)
307 tracer%vals(:,iobs) = tracer%vals(:,iobs) * self%convert_factor_model
310 if(self%flip_it) tracer%vals(1:tracer%nval,iobs) = tracer%vals(tracer%nval:1:-1,iobs)
324 if (
allocated(self%ak_kernel))
deallocate(self%ak_kernel)
325 if (
allocated(self%bk_kernel))
deallocate(self%bk_kernel)
326 if (
allocated(self%obskernelvar))
deallocate(self%obskernelvar)
327 if (
allocated(self%tracervars))
deallocate(self%tracervars)
328 if (
allocated(self%avgkernel_obs))
deallocate(self%avgkernel_obs)
329 if (
allocated(self%prsl_obs))
deallocate(self%prsl_obs)
330 if (
allocated(self%prsi_obs))
deallocate(self%prsi_obs)
331 if (
allocated(self%prsl))
deallocate(self%prsl)
332 if (
allocated(self%prsi))
deallocate(self%prsi)
333 if (
allocated(self%temp))
deallocate(self%temp)
334 if (
allocated(self%phii))
deallocate(self%phii)
335 if (
allocated(self%airmass_tot))
deallocate(self%airmass_tot)
336 if (
allocated(self%airmass_trop))
deallocate(self%airmass_trop)
337 if (
allocated(self%troplev_obs))
deallocate(self%troplev_obs)
subroutine simulate_column_ob_ad(nlayers_obs, nlayers_model, avgkernel_obs, prsi_obs, prsi_model, prsl_obs, prsl_model, temp_model, zi_model, profile_model_ad, hofx_ad, troplev_obs, airmass_tot, airmass_trop)
subroutine simulate_column_ob_tl(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 avgkernel tl/ad observation operator.
subroutine destructor(self)
subroutine avgkernel_simobs_ad_(self, geovals_in, obss, nvars, nlocs, hofx)
subroutine avgkernel_tlad_settraj_(self, geovals_in, obss)
integer, parameter max_string
subroutine avgkernel_simobs_tl_(self, geovals_in, obss, nvars, nlocs, hofx)
subroutine avgkernel_tlad_cleanup_(self)
subroutine avgkernel_tlad_setup_(self, f_conf)
real(kind_real), parameter, public one
real(kind_real), parameter, public half
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
type to hold interpolated field for one variable, one observation
type to hold interpolated fields required by the obs operators