11 use missing_values_mod
12 use oops_variables_mod
20 type(oops_variables),
public :: obsvars
21 type(oops_variables),
public :: geovars
22 real(kind_real),
allocatable :: airdens(:,:)
23 real(kind_real),
allocatable :: delp(:,:)
24 real(kind_real),
allocatable :: ext(:,:,:)
25 real(kind_real),
allocatable :: obss_wavelength(:)
26 real(kind_real),
public,
allocatable :: wavelength(:)
27 integer :: nlayers, nprofiles
44 integer function b_channel( bracket, nprofiles, bkg_wavelengths, obs_wavelength )
46 integer,
intent(in) :: bracket
47 integer,
intent(in) :: nprofiles
48 real(kind_real),
dimension(nprofiles) :: bkg_wavelengths
49 real(kind_real) :: obs_wavelength
51 character(len=maxvarlen) :: err_msg
54 do while(j < nprofiles)
55 if(obs_wavelength .GE. bkg_wavelengths(j) .and.&
56 obs_wavelength .LT. bkg_wavelengths(j+1))
then
57 if (bracket == 1)
then
59 else if (bracket == 2)
then
62 write(err_msg,*)
"ufo_aodext_mod: function b_channel: bracket index should be 1 (lower) or 2 (upper)"
63 call abor1_ftn(err_msg)
66 else if(obs_wavelength .GT. bkg_wavelengths(j) .and.&
67 obs_wavelength .LE. bkg_wavelengths(j+1))
then
68 if (bracket == 1)
then
70 else if (bracket == 2)
then
73 write(err_msg,*)
"ufo_aodext_mod: function b_channel: bracket index should be 1 (lower) or 2 (upper)"
74 call abor1_ftn(err_msg)
84 use fckit_configuration_module,
only: fckit_configuration
87 type(fckit_configuration),
intent(in) :: f_conf
91 character(len=maxvarlen) :: err_msg
94 call f_conf%get_or_die(
"nprofiles", self%nprofiles)
96 if (self%nprofiles < 2 .or. self%nprofiles > 3)
then
97 write(err_msg,*)
'ufo_aodext_tlad_setup: number of extinction profiles must be 2 or 3'
98 call abor1_ftn(err_msg)
101 do n = 1, self%nprofiles
106 allocate(self%wavelength(self%nprofiles))
107 call f_conf%get_or_die(
"bkg_wavelengths", self%wavelength)
110 do while (n < self%nprofiles)
111 if(self%wavelength(n) > self%wavelength(n+1))
then
112 write(err_msg,*)
' ufo_aodext_tlad_setup: bkg wavelengths should be in an ascending order'
113 call abor1_ftn(err_msg)
124 if (
allocated(self%airdens))
deallocate(self%airdens)
125 if (
allocated(self%delp))
deallocate(self%delp)
126 if (
allocated(self%ext))
deallocate(self%ext)
127 if (
allocated(self%obss_wavelength))
deallocate(self%obss_wavelength)
128 if (
allocated(self%wavelength))
deallocate(self%wavelength)
140 type(c_ptr),
value,
intent(in) :: obss
143 character(len=MAXVARLEN) :: geovar
144 integer :: nch, nvars, nlocs
151 nlocs = obsspace_get_nlocs(obss)
154 nvars = self%obsvars%nvars()
158 self%nlayers = delp_profile%nval
160 allocate(self%delp(self%nlayers,nlocs))
161 self%delp = delp_profile%vals
164 allocate(self%airdens(self%nlayers,nlocs))
165 self%airdens = airdens_profile%vals
167 allocate(self%ext(self%nlayers, nlocs, self%nprofiles))
168 do nch = 1, self%nprofiles
169 geovar = self%geovars%variable(nch)
171 self%ext(:,:,nch) = ext_profile%vals
176 allocate(self%obss_wavelength(nvars))
177 call obsspace_get_db(obss,
"VarMetaData",
"obs_wavelength", self%obss_wavelength)
193 integer,
intent(in) :: nvars, nlocs
194 real(c_double),
intent(inout) :: hofx(nvars, nlocs)
195 type(c_ptr),
value,
intent(in) :: obss
198 real(kind_real),
dimension(:,:,:),
allocatable :: ext_tl
199 real(kind_real),
dimension(:,:),
allocatable :: aod_bkg
200 real(kind_real),
dimension(:,:),
allocatable :: aod_bkg_tl
201 real(kind_real),
dimension(:,:),
allocatable :: angstrom
202 real(kind_real),
dimension(:,:),
allocatable :: angstrom_tl
203 real(kind_real),
dimension(:,:),
allocatable :: logm
205 real(kind_real) :: arg1, arg1_tl, tmp, coef, coef_tl
207 integer :: nch, nobs, ic, i, j, km
210 character(len=MAXVARLEN) :: geovar
211 real(c_double) :: missing
214 allocate(ext_tl(self%nlayers, nlocs, self%nprofiles))
216 do nch = 1, self%nprofiles
217 geovar = self%geovars%variable(nch)
219 ext_tl(:,:,nch) = ext_profile%vals
222 allocate(aod_bkg(nlocs, self%nprofiles))
223 allocate(aod_bkg_tl(nlocs, self%nprofiles))
227 do nch = 1, self%nprofiles
229 do km = 1, self%nlayers
231 aod_bkg(nobs,nch) = aod_bkg(nobs, nch) + (self%ext(km,nobs,nch) * self%delp(km,nobs)&
232 * 1./(self%airdens(km,nobs) *
grav*1000.0_kind_real))
233 aod_bkg_tl(nobs,nch) = aod_bkg_tl(nobs, nch) + (ext_tl(km,nobs,nch) * self%delp(km,nobs)&
234 * 1./(self%airdens(km,nobs) *
grav*1000.0_kind_real))
240 allocate(angstrom_tl(nvars,nlocs))
241 allocate(angstrom(nvars,nlocs))
242 allocate(logm(nvars,nlocs))
244 missing =missing_value(missing)
251 if(self%obss_wavelength(ic) < self%wavelength(1) .or.&
252 self%obss_wavelength(ic) > self%wavelength(self%nprofiles))
then
253 hofx(ic, nobs) = missing
255 i =
b_channel(1, self%nprofiles, self%wavelength, self%obss_wavelength(ic))
256 j =
b_channel(2, self%nprofiles, self%wavelength, self%obss_wavelength(ic))
258 logm(ic, nobs) = log(self%wavelength(i)/self%wavelength(j))
259 tmp = aod_bkg(nobs, i) / aod_bkg(nobs, j)
260 arg1_tl = (aod_bkg_tl(nobs, i)-tmp*aod_bkg_tl(nobs,j))/aod_bkg(nobs,j)
263 angstrom_tl(ic, nobs) = arg1_tl/(logm(ic, nobs) * arg1)
264 angstrom(ic, nobs) = log(arg1)/logm(ic,nobs)
266 coef = (self%wavelength(i)/self%wavelength(j))**angstrom(ic, nobs)
267 coef_tl = coef * log(self%wavelength(i)/self%wavelength(j))*angstrom_tl(ic,nobs)
268 hofx(ic, nobs) = coef * aod_bkg_tl(nobs, i) + aod_bkg(nobs, i)* coef_tl
272 deallocate( angstrom_tl, angstrom, aod_bkg, aod_bkg_tl, ext_tl, logm)
287 integer,
intent(in) :: nvars, nlocs
288 real(c_double),
intent(in) :: hofx(nvars, nlocs)
289 type(c_ptr),
value,
intent(in) :: obss
292 real(kind_real),
dimension(:,:,:),
allocatable :: ext_ad
293 real(kind_real),
dimension(:,:),
allocatable :: aod_bkg
294 real(kind_real),
dimension(:,:),
allocatable :: aod_bkg_ad
295 real(kind_real),
dimension(:,:),
allocatable :: angstrom
296 real(kind_real),
dimension(:,:),
allocatable :: angstrom_ad
297 real(kind_real),
dimension(:,:),
allocatable :: logm
299 real(kind_real) :: arg1, arg1_ad, tmp, tmp_ad, coef, coef_ad
301 integer :: nch, nobs, km, ic, i, j
303 character(len=MAXVARLEN) :: geovar
305 real(c_double) :: missing
307 allocate(aod_bkg(nlocs, self%nprofiles))
310 do nch = 1, self%nprofiles
312 do km = 1, self%nlayers
314 aod_bkg(nobs,nch) = aod_bkg(nobs, nch) + (self%ext(km,nobs,nch) * self%delp(km,nobs) &
315 * 1./(self%airdens(km,nobs)*
grav*1000.0_kind_real))
321 missing = missing_value(missing)
322 allocate(angstrom(nvars,nlocs))
323 allocate(logm(nvars,nlocs))
327 if(self%obss_wavelength(ic) < self%wavelength(1) .or.&
328 self%obss_wavelength(ic) > self%wavelength(self%nprofiles))
then
329 angstrom(ic, nobs) = missing
332 i =
b_channel(1, self%nprofiles, self%wavelength, self%obss_wavelength(ic))
333 j =
b_channel(2, self%nprofiles, self%wavelength, self%obss_wavelength(ic))
335 logm(ic, nobs) = log(self%wavelength(i)/self%wavelength(j))
337 angstrom(ic, nobs) = log(aod_bkg(nobs,i)/aod_bkg(nobs,j))/logm(ic, nobs)
342 allocate(aod_bkg_ad(nlocs, self%nprofiles))
343 allocate(angstrom_ad(nvars,nlocs))
347 do nobs = nlocs, 1, -1
350 if( hofx(ic,nobs)/=missing.and.angstrom(ic,nobs)/=missing )
then
352 i =
b_channel(1, self%nprofiles, self%wavelength, self%obss_wavelength(ic))
353 j =
b_channel(2, self%nprofiles, self%wavelength, self%obss_wavelength(ic))
355 coef = (self%wavelength(i)/self%wavelength(j))**angstrom(ic, nobs)
356 aod_bkg_ad(nobs, i) = aod_bkg_ad(nobs, i) + coef * hofx(ic, nobs)
358 angstrom_ad(ic, nobs) = angstrom_ad(ic,nobs) + coef * log(self%wavelength(i)/self%wavelength(j)) &
359 * aod_bkg(nobs, i) * hofx(ic, nobs)
361 j =
b_channel(2, self%nprofiles, self%wavelength, self%obss_wavelength(ic))
363 tmp = aod_bkg(nobs, i) / aod_bkg(nobs, j)
364 tmp_ad = angstrom_ad(ic, nobs)/(aod_bkg(nobs,j)*tmp*logm(ic, nobs))
366 aod_bkg_ad(nobs, i) = aod_bkg_ad(nobs,i) + tmp_ad
367 aod_bkg_ad(nobs, j) = aod_bkg_ad(nobs,j) - tmp * tmp_ad
372 allocate(ext_ad(self%nlayers, nlocs, self%nprofiles))
375 do nch = self%nprofiles, 1, -1
376 do nobs = nlocs, 1, -1
377 do km = self%nlayers, 1, -1
378 ext_ad(km, nobs, nch) = ext_ad(km, nobs, nch) + self%delp(km, nobs) &
379 * aod_bkg_ad(nobs, nch) * 1./(self%airdens(km, nobs) *
grav * 1000.)
385 do nch = self%nprofiles, 1, -1
387 geovar = self%geovars%variable(nch)
389 ext_profile%vals(:,:) = ext_ad(:,:,nch)
392 deallocate(angstrom_ad, angstrom, aod_bkg_ad, aod_bkg, ext_ad)
Fortran module for aodext tl/ad observation operator.
character(len=maxvarlen), dimension(3), parameter extdefault
Default variables required from model.
integer function b_channel(bracket, nprofiles, bkg_wavelengths, obs_wavelength)
subroutine ufo_aodext_simobs_ad(self, geovals, obss, nvars, nlocs, hofx)
subroutine destructor(self)
subroutine ufo_aodext_tlad_settraj(self, geovals, obss)
subroutine ufo_aodext_tlad_setup(self, f_conf)
subroutine ufo_aodext_simobs_tl(self, geovals, obss, nvars, nlocs, hofx)
real(kind_real), parameter, public grav
real(kind_real), parameter, public zero
subroutine, public ufo_geovals_get_var(self, varname, geoval)
character(len=maxvarlen), parameter, public var_ext2
character(len=maxvarlen), parameter, public var_airdens
character(len=maxvarlen), parameter, public var_ext3
character(len=maxvarlen), parameter, public var_delp
character(len=maxvarlen), parameter, public var_ext1
type to hold interpolated field for one variable, one observation
type to hold interpolated fields required by the obs operators