UFO
ufo_aodluts_tlad_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 to handle tl/ad for aod observations
7 
9 
10  USE fckit_configuration_module, ONLY: fckit_configuration
11  USE iso_c_binding
12  USE kinds
13  USE missing_values_mod
14 
16  USE ufo_vars_mod
20  USE crtm_module
21  USE crtm_spccoeff, ONLY: sc
22  USE obsspace_mod
23 
24  USE cf_mieobs_mod, ONLY: get_cf_aod
25  USE geos_mieobs_mod, ONLY: get_geos_aod_tl, get_geos_aod_ad
26 
27  IMPLICIT NONE
28  PRIVATE
29 
30 !> fortran derived type for aod trajectory
31  TYPE, PUBLIC :: ufo_aodluts_tlad
32  PRIVATE
33  CHARACTER(len=maxvarlen), PUBLIC, ALLOCATABLE :: varin(:) ! variablesrequested from the model
34  INTEGER, ALLOCATABLE :: channels(:)
35  REAL(kind_real), ALLOCATABLE :: wavelengths(:)
36  TYPE(luts_conf) :: conf
37  INTEGER :: n_profiles
38  INTEGER :: n_layers
39  INTEGER :: n_channels
40  INTEGER :: n_aerosols
41  REAL(kind_real), ALLOCATABLE :: bext(:,:,:,:)
42  REAL(kind_real), ALLOCATABLE :: layer_factors(:,:)
43  LOGICAL :: ltraj
44  CONTAINS
45  PROCEDURE :: setup => ufo_aodluts_tlad_setup
46  PROCEDURE :: delete => ufo_aodluts_tlad_delete
47  PROCEDURE :: settraj => ufo_aodluts_tlad_settraj
48  PROCEDURE :: simobs_tl => ufo_aodluts_simobs_tl
49  PROCEDURE :: simobs_ad => ufo_aodluts_simobs_ad
50  END TYPE ufo_aodluts_tlad
51 
52 CONTAINS
53 
54 ! ------------------------------------------------------------------------------
55 
56  SUBROUTINE ufo_aodluts_tlad_setup(self, f_confoper, channels)
57 
58  IMPLICIT NONE
59  CLASS(ufo_aodluts_tlad), INTENT(inout) :: self
60  TYPE(fckit_configuration), INTENT(in) :: f_confoper
61  INTEGER(c_int), INTENT(in) :: channels(:) !list of channels to use
62 
63  TYPE(fckit_configuration) :: f_confopts
64 
65  CHARACTER(len=maxvarlen), ALLOCATABLE :: var_aerosols(:)
66  CHARACTER(len=:), ALLOCATABLE :: str
67 
68  CALL f_confoper%get_or_die("obs options",f_confopts)
69 
70  CALL luts_conf_setup(self%conf, f_confopts, f_confoper)
71 
72  CALL assign_aerosol_names(self%conf%aerosol_option,var_aerosols)
73 
74  self%n_aerosols=SIZE(var_aerosols)
75  ALLOCATE(self%varin(self%n_aerosols))
76  self%varin(1:self%n_aerosols) = var_aerosols
77 
78  ALLOCATE(self%channels(SIZE(channels)))
79  ALLOCATE(self%wavelengths(SIZE(channels)))
80 
81  self%channels(:) = channels(:)
82 
83  DEALLOCATE(var_aerosols)
84 
85  END SUBROUTINE ufo_aodluts_tlad_setup
86 
87 ! ------------------------------------------------------------------------------
88 
89  SUBROUTINE ufo_aodluts_tlad_delete(self)
90 
91  IMPLICIT NONE
92  CLASS(ufo_aodluts_tlad), INTENT(inout) :: self
93 
94  self%ltraj = .false.
95  CALL luts_conf_delete(self%conf)
96 
97 !deallocate all arrays
98 
99  IF (ALLOCATED(self%bext)) DEALLOCATE(self%bext)
100  IF (ALLOCATED(self%layer_factors)) DEALLOCATE(self%layer_factors)
101  IF (ALLOCATED(self%varin)) DEALLOCATE(self%varin)
102  IF (ALLOCATED(self%channels)) DEALLOCATE(self%channels)
103  IF (ALLOCATED(self%wavelengths)) DEALLOCATE(self%wavelengths)
104 
105  END SUBROUTINE ufo_aodluts_tlad_delete
106 
107 ! ------------------------------------------------------------------------------
108 
109  SUBROUTINE ufo_aodluts_tlad_settraj(self, geovals, obss)
110 
111  IMPLICIT NONE
112 
113  CLASS(ufo_aodluts_tlad), INTENT(inout) :: self
114  TYPE(ufo_geovals), INTENT(in) :: geovals
115  TYPE(c_ptr), VALUE, INTENT(in) :: obss
116 
117 ! local variables
118  CHARACTER(*), PARAMETER :: program_name = 'ufo_aodluts_tlad_mod.f90'
119  CHARACTER(255) :: message, version
120  INTEGER :: err_stat, alloc_stat
121  INTEGER :: n,l,m
122  TYPE(ufo_geoval), POINTER :: temp
123 
124 ! define the "non-demoninational" arguments
125  TYPE(crtm_channelinfo_type) :: chinfo(self%conf%n_sensors)
126 
127  CHARACTER(len=maxvarlen), ALLOCATABLE :: var_aerosols(:)
128  REAL(kind_real), ALLOCATABLE :: aero_layers(:,:,:),rh(:,:)
129  REAL(kind_real), ALLOCATABLE :: wavelengths_all(:)
130 
131  INTEGER :: rc,nvars
132 
133 ! get number of profile and layers from geovals
134 
135  CALL assign_aerosol_names(self%conf%aerosol_option,var_aerosols)
136 
137  self%n_profiles = geovals%nlocs
138  CALL ufo_geovals_get_var(geovals, var_aerosols(1), temp)
139  self%n_layers = temp%nval
140  NULLIFY(temp)
141 
142  err_stat = crtm_init( self%conf%sensor_id, &
143  chinfo, &
144  file_path=trim(self%conf%coefficient_path), &
145  quiet=.true.)
146  IF ( err_stat /= success ) THEN
147  message = 'error initializing crtm (settraj)'
148  CALL display_message( program_name, message, failure )
149  stop
150  END IF
151 
152  ALLOCATE(aero_layers(self%n_aerosols,self%n_layers,self%n_profiles),&
153  &rh(self%n_layers,self%n_profiles))
154 
155  ALLOCATE(self%layer_factors(self%n_layers,self%n_profiles))
156 
157  nvars=SIZE(self%channels)
158 
159  sensor_loop:DO n = 1, self%conf%n_sensors
160 
161  self%n_channels = crtm_channelinfo_n_channels(chinfo(n))
162 
163  IF (ALLOCATED(wavelengths_all)) DEALLOCATE(wavelengths_all)
164 
165  ALLOCATE(wavelengths_all(self%n_channels), stat = alloc_stat)
166 
167  wavelengths_all=1.e7/sc(chinfo(n)%sensor_index)%wavenumber(:)
168 
169  self%wavelengths=wavelengths_all(self%channels)
170 
171  CALL calculate_aero_layers(self%conf%aerosol_option,&
172  &self%n_aerosols, self%n_profiles, self%n_layers,&
173  &geovals, aero_layers=aero_layers, rh=rh, &
174  &layer_factors=self%layer_factors)
175 
176  ALLOCATE(self%bext(self%n_layers, nvars, self%n_aerosols, self%n_profiles))
177 
178  CALL get_cf_aod(self%n_layers, self%n_profiles, nvars, &
179  &self%n_aerosols, self%conf%rcfile, &
180  &self%wavelengths, var_aerosols, aero_layers, rh, &
181  &ext=self%bext, rc = rc)
182 
183  IF (rc /= 0) THEN
184  message = 'error on exit from get_cf_aod'
185  CALL display_message( program_name, message, failure )
186  stop
187  END IF
188 
189  DEALLOCATE(rh)
190  DEALLOCATE(aero_layers)
191  DEALLOCATE(wavelengths_all)
192 
193  END DO sensor_loop
194 
195  err_stat = crtm_destroy( chinfo )
196  IF ( err_stat /= success ) THEN
197  message = 'error destroying crtm (settraj)'
198  CALL display_message( program_name, message, failure )
199  stop
200  END IF
201 
202 
203 ! set flag that the tracectory was set
204 
205  self%ltraj = .true.
206 
207  END SUBROUTINE ufo_aodluts_tlad_settraj
208 
209 ! ------------------------------------------------------------------------------
210 
211  SUBROUTINE ufo_aodluts_simobs_tl(self, geovals, obss, nvars, nlocs, hofx)
212 
213  IMPLICIT NONE
214  CLASS(ufo_aodluts_tlad), INTENT(in) :: self
215  TYPE(ufo_geovals), INTENT(in) :: geovals
216  TYPE(c_ptr), VALUE, INTENT(in) :: obss
217  INTEGER, INTENT(in) :: nvars, nlocs
218  REAL(c_double), INTENT(inout) :: hofx(nvars, nlocs)
219 
220  CHARACTER(len=*), PARAMETER :: myname_="ufo_aodluts_simobs_tl"
221  CHARACTER(max_string) :: err_msg
222  INTEGER :: jaero
223  TYPE(ufo_geoval), POINTER :: var_p
224 
225  CHARACTER(len=maxvarlen), ALLOCATABLE :: var_aerosols(:)
226 
227  REAL(kind_real), ALLOCATABLE :: aero_layers(:,:,:)
228 
229 ! initial checks
230 
231 ! check if trajectory was set
232  IF (.NOT. self%ltraj) THEN
233  WRITE(err_msg,*) myname_, ' trajectory wasnt set!'
234  CALL abor1_ftn(err_msg)
235  ENDIF
236 
237 ! check if nlocs is consistent in geovals & hofx
238  IF (geovals%nlocs /= self%n_profiles) THEN
239  WRITE(err_msg,*) myname_, ' error: nlocs inconsistent!'
240  CALL abor1_ftn(err_msg)
241  ENDIF
242 
243  CALL assign_aerosol_names(self%conf%aerosol_option,var_aerosols)
244 
245  CALL ufo_geovals_get_var(geovals, var_aerosols(1), var_p)
246 
247 ! check model levels is consistent in geovals & crtm
248  IF (var_p%nval /= self%n_layers) THEN
249  WRITE(err_msg,*) myname_, ' error: layers inconsistent!'
250  CALL abor1_ftn(err_msg)
251  ENDIF
252 
253  ALLOCATE(aero_layers(self%n_aerosols,self%n_layers,self%n_profiles))
254 
255  DO jaero=1,self%n_aerosols
256  CALL ufo_geovals_get_var(geovals, var_aerosols(jaero), var_p)
257  aero_layers(jaero,:,:)=var_p%vals*self%layer_factors
258  ENDDO
259 
260  CALL get_geos_aod_tl(self%n_layers,self%n_profiles, nvars,&
261  &self%n_aerosols, self%bext, aero_layers, aod_tot_tl=hofx)
262 
263  NULLIFY(var_p)
264 
265  DEALLOCATE(aero_layers)
266  DEALLOCATE(var_aerosols)
267 
268  END SUBROUTINE ufo_aodluts_simobs_tl
269 
270 ! ------------------------------------------------------------------------------
271 
272  SUBROUTINE ufo_aodluts_simobs_ad(self, geovals, obss, nvars, nlocs, hofx)
273 
274  IMPLICIT NONE
275  CLASS(ufo_aodluts_tlad), INTENT(in) :: self
276  TYPE(ufo_geovals), INTENT(inout) :: geovals
277  TYPE(c_ptr), VALUE, INTENT(in) :: obss
278  INTEGER, INTENT(in) :: nvars, nlocs
279  REAL(c_double), INTENT(in) :: hofx(nvars, nlocs)
280 
281  CHARACTER(len=*), PARAMETER :: myname_="ufo_aodluts_simobs_ad"
282  CHARACTER(max_string) :: err_msg
283  TYPE(ufo_geoval), POINTER :: var_p
284  INTEGER :: jaero
285 
286  REAL(kind_real), DIMENSION(:,:,:), ALLOCATABLE :: qm_ad
287  CHARACTER(len=maxvarlen), ALLOCATABLE :: var_aerosols(:)
288  REAL(kind_real), DIMENSION(:,:), ALLOCATABLE :: layer_factors
289 
290 
291 ! initial checks
292 
293 ! check if trajectory was set
294  IF (.NOT. self%ltraj) THEN
295  WRITE(err_msg,*) myname_, ' trajectory wasnt set!'
296  CALL abor1_ftn(err_msg)
297  ENDIF
298 
299 ! check if nlocs is consistent in geovals & hofx
300  IF (geovals%nlocs /= self%n_profiles) THEN
301  WRITE(err_msg,*) myname_, ' error: nlocs inconsistent!'
302  CALL abor1_ftn(err_msg)
303  ENDIF
304 
305  CALL assign_aerosol_names(self%conf%aerosol_option,var_aerosols)
306 
307  ALLOCATE(qm_ad(self%n_aerosols, self%n_layers, nlocs))
308 
309  CALL get_geos_aod_ad(self%n_layers, nlocs, nvars, self%n_aerosols, &
310  &self%bext, hofx, qm_ad)
311 
312  DO jaero=self%n_aerosols,1,-1
313 
314  CALL ufo_geovals_get_var(geovals, var_aerosols(jaero), var_p)
315 
316  qm_ad(jaero,:,:) = qm_ad(jaero,:,:) * self%layer_factors
317  var_p%vals=qm_ad(jaero,:,:)
318 
319  ENDDO
320 
321  NULLIFY(var_p)
322 
323  DEALLOCATE(qm_ad)
324  DEALLOCATE(var_aerosols)
325 
326  IF (.NOT. geovals%linit ) geovals%linit=.true.
327 
328  END SUBROUTINE ufo_aodluts_simobs_ad
329 
330 ! ------------------------------------------------------------------------------
331 
332 END MODULE ufo_aodluts_tlad_mod
fortran module to handle tl/ad for aod observations
subroutine ufo_aodluts_tlad_delete(self)
subroutine ufo_aodluts_simobs_ad(self, geovals, obss, nvars, nlocs, hofx)
subroutine ufo_aodluts_simobs_tl(self, geovals, obss, nvars, nlocs, hofx)
subroutine ufo_aodluts_tlad_settraj(self, geovals, obss)
subroutine ufo_aodluts_tlad_setup(self, f_confoper, channels)
Fortran module to provide code shared between nonlinear and tlm/adm radiance calculations.
integer, parameter, public max_string
subroutine, public assign_aerosol_names(aerosol_option, var_aerosols)
subroutine, public ufo_geovals_get_var(self, varname, geoval)
fortran module to provide code shared between nonlinear and tlm/adm radiance calculations
subroutine, public luts_conf_delete(conf)
subroutine, public calculate_aero_layers(aerosol_option, n_aerosols, n_profiles, n_layers, geovals, aero_layers, rh, layer_factors)
subroutine, public luts_conf_setup(conf, f_confopts, f_confoper)
fortran derived type for aod trajectory
type to hold interpolated field for one variable, one observation
type to hold interpolated fields required by the obs operators