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 fv3_mieobs_mod, ONLY: get_fv3_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 :: wavelenghts(:)
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%wavelenghts(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%wavelenghts)) DEALLOCATE(self%wavelenghts)
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 :: wavelenghts_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(wavelenghts_all)) DEALLOCATE(wavelenghts_all)
164 
165  ALLOCATE(wavelenghts_all(self%n_channels), stat = alloc_stat)
166 
167  wavelenghts_all=1.e7/sc(chinfo(n)%sensor_index)%wavenumber(:)
168 
169  self%wavelenghts=wavelenghts_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_fv3_aod(self%n_layers, self%n_profiles, nvars, &
179  &self%n_aerosols, self%conf%rcfile, &
180  &self%wavelenghts, var_aerosols, aero_layers, rh, &
181  &ext=self%bext, rc = rc)
182 
183  IF (rc /= 0) THEN
184  message = 'error on exit from get_fv3_aod'
185  CALL display_message( program_name, message, failure )
186  stop
187  END IF
188 
189  DEALLOCATE(rh)
190  DEALLOCATE(aero_layers)
191  DEALLOCATE(wavelenghts_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  IF (.NOT. ALLOCATED(var_p%vals)) THEN
316  var_p%nlocs = self%n_profiles
317  var_p%nval = self%n_layers
318  ALLOCATE(var_p%vals(var_p%nval,var_p%nlocs))
319  var_p%vals = 0.0_kind_real
320  ENDIF
321 
322  qm_ad(jaero,:,:) = qm_ad(jaero,:,:) * self%layer_factors
323  var_p%vals=qm_ad(jaero,:,:)
324 
325  ENDDO
326 
327  NULLIFY(var_p)
328 
329  DEALLOCATE(qm_ad)
330  DEALLOCATE(var_aerosols)
331 
332  IF (.NOT. geovals%linit ) geovals%linit=.true.
333 
334  END SUBROUTINE ufo_aodluts_simobs_ad
335 
336 ! ------------------------------------------------------------------------------
337 
338 END MODULE ufo_aodluts_tlad_mod
ufo_avgkernel_mod::max_string
integer, parameter max_string
Definition: ufo_avgkernel_mod.F90:17
ufo_crtm_utils_mod::assign_aerosol_names
subroutine, public assign_aerosol_names(aerosol_option, var_aerosols)
Definition: ufo_crtm_utils_mod.F90:1008
ufo_luts_utils_mod::calculate_aero_layers
subroutine, public calculate_aero_layers(aerosol_option, n_aerosols, n_profiles, n_layers, geovals, aero_layers, rh, layer_factors)
Definition: ufo_luts_utils_mod.F90:93
ufo_luts_utils_mod
fortran module to provide code shared between nonlinear and tlm/adm radiance calculations
Definition: ufo_luts_utils_mod.F90:8
ufo_aodluts_tlad_mod::ufo_aodluts_tlad_settraj
subroutine ufo_aodluts_tlad_settraj(self, geovals, obss)
Definition: ufo_aodluts_tlad_mod.F90:110
ufo_aodluts_tlad_mod::ufo_aodluts_tlad_setup
subroutine ufo_aodluts_tlad_setup(self, f_confoper, channels)
Definition: ufo_aodluts_tlad_mod.F90:57
ufo_crtm_utils_mod
Fortran module to provide code shared between nonlinear and tlm/adm radiance calculations.
Definition: ufo_crtm_utils_mod.F90:8
ufo_geovals_mod
Definition: ufo_geovals_mod.F90:7
ufo_aodluts_tlad_mod
fortran module to handle tl/ad for aod observations
Definition: ufo_aodluts_tlad_mod.F90:8
ufo_aodluts_tlad_mod::ufo_aodluts_tlad_delete
subroutine ufo_aodluts_tlad_delete(self)
Definition: ufo_aodluts_tlad_mod.F90:90
ufo_luts_utils_mod::luts_conf_delete
subroutine, public luts_conf_delete(conf)
Definition: ufo_luts_utils_mod.F90:80
ufo_aodluts_tlad_mod::ufo_aodluts_simobs_tl
subroutine ufo_aodluts_simobs_tl(self, geovals, obss, nvars, nlocs, hofx)
Definition: ufo_aodluts_tlad_mod.F90:212
ufo_vars_mod
Definition: ufo_variables_mod.F90:8
ufo_aodluts_tlad_mod::ufo_aodluts_tlad
fortran derived type for aod trajectory
Definition: ufo_aodluts_tlad_mod.F90:31
ufo_geovals_mod::ufo_geovals_get_var
subroutine, public ufo_geovals_get_var(self, varname, geoval)
Definition: ufo_geovals_mod.F90:128
ufo_luts_utils_mod::luts_conf
Definition: ufo_luts_utils_mod.F90:37
ufo_aodluts_tlad_mod::ufo_aodluts_simobs_ad
subroutine ufo_aodluts_simobs_ad(self, geovals, obss, nvars, nlocs, hofx)
Definition: ufo_aodluts_tlad_mod.F90:273
ufo_geovals_mod::ufo_geovals
type to hold interpolated fields required by the obs operators
Definition: ufo_geovals_mod.F90:47
ufo_geovals_mod::ufo_geoval
type to hold interpolated field for one variable, one observation
Definition: ufo_geovals_mod.F90:40
conf
Definition: conf.py:1
ufo_luts_utils_mod::luts_conf_setup
subroutine, public luts_conf_setup(conf, f_confopts, f_confoper)
Definition: ufo_luts_utils_mod.F90:51