UFO
ufo_aodcrtm_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 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
18  use crtm_module
19  use obsspace_mod
20 
21  implicit none
22  private
23 
24  !> Fortran derived type for aod trajectory
25  type, public :: ufo_aodcrtm
26  private
27  character(len=MAXVARLEN), public, allocatable :: varin(:) ! variablesrequested from the model
28  integer, allocatable :: channels(:)
29  type(crtm_conf) :: conf
30  contains
31  procedure :: setup => ufo_aodcrtm_setup
32  procedure :: delete => ufo_aodcrtm_delete
33  procedure :: simobs => ufo_aodcrtm_simobs
34  end type ufo_aodcrtm
35  CHARACTER(len=maxvarlen), DIMENSION(5), PARAMETER :: varin_default = (/var_ts, var_mixr, var_rh, var_prs, var_prsi/)
36 
37  CHARACTER(MAXVARLEN), PARAMETER :: varname_tmplate="aerosol_optical_depth"
38 
39 contains
40 
41 ! ------------------------------------------------------------------------------
42 
43 subroutine ufo_aodcrtm_setup(self, f_confOper, channels)
44 
45 implicit none
46 class(ufo_aodcrtm), intent(inout) :: self
47 type(fckit_configuration), intent(in) :: f_confOper
48 integer(c_int), intent(in) :: channels(:) !List of channels to use
49 
50 integer :: nvars_in
51 character(len=max_string) :: err_msg
52 type(fckit_configuration) :: f_confOpts
53 
54 CHARACTER(len=MAXVARLEN), ALLOCATABLE :: var_aerosols(:)
55 
56  call f_confoper%get_or_die("obs options",f_confopts)
57 
58  call crtm_conf_setup(self%conf, f_confopts, f_confoper)
59  if ( ufo_vars_getindex(self%conf%Absorbers, var_mixr) /= 1 ) then
60  write(err_msg,*) 'ufo_aodcrtm_setup error: H2O must be first in CRTM Absorbers for AOD'
61  call abor1_ftn(err_msg)
62  end if
63  if ( ufo_vars_getindex(self%conf%Absorbers, var_oz) < 2 ) then
64  write(err_msg,*) 'ufo_aodcrtm_setup error: O3 must be included in CRTM Absorbers'
65  call abor1_ftn(err_msg)
66  end if
67 
68  CALL assign_aerosol_names(self%conf%aerosol_option,var_aerosols)
69 
70  nvars_in = SIZE(varin_default)+SIZE(var_aerosols)
71  allocate(self%varin(nvars_in))
72  self%varin(1:size(varin_default)) = varin_default
73  self%varin(SIZE(varin_default)+1:) = var_aerosols
74 
75  ! save channels
76  allocate(self%channels(size(channels)))
77  self%channels(:) = channels(:)
78 
79 end subroutine ufo_aodcrtm_setup
80 
81 ! ------------------------------------------------------------------------------
82 
83 subroutine ufo_aodcrtm_delete(self)
84 
85 implicit none
86 class(ufo_aodcrtm), intent(inout) :: self
87 
88  call crtm_conf_delete(self%conf)
89 
90 end subroutine ufo_aodcrtm_delete
91 
92 ! ------------------------------------------------------------------------------
93 
94 SUBROUTINE ufo_aodcrtm_simobs(self, geovals, obss, nvars, nlocs, hofx)
95 
96 implicit none
97 class(ufo_aodcrtm), intent(in) :: self
98 type(ufo_geovals), intent(in) :: geovals
99 integer, intent(in) :: nvars, nlocs
100 real(c_double), intent(inout) :: hofx(nvars, nlocs)
101 type(c_ptr), value, intent(in) :: obss
102 
103 ! Local Variables
104 character(*), parameter :: PROGRAM_NAME = 'ufo_aodcrtm_mod.F90'
105 character(255) :: message, version
106 integer :: err_stat, alloc_stat
107 integer :: l, m, n, i
108 type(ufo_geoval), pointer :: temp
109 real(c_double) :: missing
110 
111 integer :: n_Profiles
112 integer :: n_Layers
113 integer :: n_Channels
114 
115 ! Define the "non-demoninational" arguments
116 type(crtm_channelinfo_type) :: chinfo(self%conf%n_Sensors)
117 type(crtm_geometry_type), allocatable :: geo(:)
118 
119 ! Define the FORWARD variables
120 type(crtm_atmosphere_type), allocatable :: atm(:)
121 type(crtm_surface_type), allocatable :: sfc(:)
122 type(crtm_rtsolution_type), allocatable :: rts(:,:)
123 
124 ! Define the K-MATRIX variables - necessary for AOD call
125 ! ---------------------------------
126 TYPE(crtm_atmosphere_type), ALLOCATABLE :: atm_K(:,:)
127 TYPE(crtm_rtsolution_type), ALLOCATABLE :: rts_K(:,:)
128 
129  ! Get number of profile and layers from geovals
130  ! ---------------------------------------------
131  n_profiles = geovals%nlocs
132  call ufo_geovals_get_var(geovals, var_ts, temp)
133  n_layers = temp%nval
134  nullify(temp)
135 
136  ! Program header
137  ! --------------
138  ! call CRTM_Version( Version )
139  ! call Program_Message( PROGRAM_NAME, &
140  ! 'Check/example program for the CRTM Forward and K-Matrix functions using '//&
141  ! trim(self%conf%ENDIAN_type)//' coefficient datafiles', &
142  ! 'CRTM Version: '//TRIM(Version) )
143 
144 
145  ! Initialise all the sensors at once
146  ! ----------------------------------
147  !** NOTE: CRTM_Init points to the various binary files needed for CRTM. See the
148  !** CRTM_Lifecycle.f90 for more details.
149 
150  ! write( *,'(/5x,"Initializing the CRTM...")' )
151  err_stat = crtm_init( self%conf%SENSOR_ID, &
152  chinfo, &
153  file_path=trim(self%conf%COEFFICIENT_PATH), &
154  quiet=.true.)
155  if ( err_stat /= success ) THEN
156  message = 'Error initializing CRTM'
157  call display_message( program_name, message, failure )
158  stop
159  end if
160 
161 
162  ! Loop over all sensors. Not necessary if we're calling CRTM for each sensor
163  ! ----------------------------------------------------------------------------
164  sensor_loop:DO n = 1, self%conf%n_Sensors
165 
166 
167  ! Determine the number of channels for the current sensor
168  ! -------------------------------------------------------
169  n_channels = crtm_channelinfo_n_channels(chinfo(n))
170 
171 
172  ! Allocate the ARRAYS
173  ! -------------------
174  allocate( geo( n_profiles ), &
175  atm( n_profiles ), &
176  sfc( n_profiles ), &
177  rts( n_channels, n_profiles ), &
178  stat = alloc_stat )
179  if ( alloc_stat /= 0 ) THEN
180  message = 'Error allocating structure arrays'
181  call display_message( program_name, message, failure )
182  stop
183  end if
184 
185 
186  ! Create the input FORWARD structure (atm)
187  ! ----------------------------------------
188  call crtm_atmosphere_create( atm, n_layers, self%conf%n_Absorbers, self%conf%n_Clouds, self%conf%n_Aerosols )
189  if ( any(.NOT. crtm_atmosphere_associated(atm)) ) THEN
190  message = 'Error allocating CRTM Forward Atmosphere structure'
191  CALL display_message( program_name, message, failure )
192  stop
193  END IF
194 
195  ALLOCATE( atm_k( n_channels, n_profiles ), &
196  rts_k( n_channels, n_profiles ), &
197  stat = alloc_stat )
198  IF ( alloc_stat /= 0 ) THEN
199  message = 'Error allocating structure arrays'
200  CALL display_message( program_name, message, failure )
201  stop
202  END IF
203 
204 ! The output K-MATRIX structure
205  CALL crtm_atmosphere_create( atm_k, n_layers, self%conf%n_Absorbers, self%conf%n_Clouds, self%conf%n_Aerosols)
206  IF ( any(.NOT. crtm_atmosphere_associated(atm_k)) ) THEN
207  message = 'Error allocating CRTM K-matrix Atmosphere structure'
208  CALL display_message( program_name, message, failure )
209  stop
210  END IF
211 
212  CALL crtm_rtsolution_create(rts, n_layers )
213  CALL crtm_rtsolution_create(rts_k, n_layers )
214 
215  !Assign the data from the GeoVaLs
216  !--------------------------------
217  CALL load_atm_data(n_profiles,n_layers,geovals,atm,self%conf)
218 
219  IF (trim(self%conf%aerosol_option) /= "") &
220  &CALL load_aerosol_data(n_profiles,n_layers,geovals,&
221  &self%conf%aerosol_option,atm)
222 
223  ! Call THE CRTM inspection
224  ! ------------------------
225  IF (self%conf%inspect > 0) THEN
226  CALL crtm_atmosphere_inspect(atm(self%conf%inspect))
227  CALL crtm_channelinfo_inspect(chinfo(n))
228  ENDIF
229 
230 ! 8b.1 The K-matrix model for AOD
231 ! ----------------------
232  err_stat = crtm_aod_k( atm, & ! FORWARD Input
233  rts_k , & ! K-MATRIX Input
234  chinfo(n:n) , & ! Input
235  rts , & ! FORWARD Output
236  atm_k ) ! K-MATRIX Output
237 
238  if ( err_stat /= success ) THEN
239  message = 'Error calling CRTM Forward Model for '//trim(self%conf%SENSOR_ID(n))
240  call display_message( program_name, message, failure )
241  stop
242  end if
243 
244 
245  ! Put simulated brightness temperature into hofx
246  ! ----------------------------------------------
247 
248  ! Set missing value
249  missing = missing_value(missing)
250  hofx = missing
251 
252  DO m = 1, n_profiles
253  DO l = 1, size(self%channels)
254  hofx(l,m) = sum(rts(self%channels(l),m)%layer_optical_depth)
255  END DO
256  END DO
257 
258  ! Deallocate the structures
259  ! -------------------------
260  call crtm_atmosphere_destroy(atm)
261  call crtm_rtsolution_destroy(rts)
262 
263  call crtm_atmosphere_destroy(atm_k)
264  call crtm_rtsolution_destroy(rts_k)
265 
266  ! Deallocate all arrays
267  ! ---------------------
268  DEALLOCATE(geo, atm, sfc, rts, atm_k, rts_k, stat = alloc_stat)
269  if ( alloc_stat /= 0 ) THEN
270  message = 'Error deallocating structure arrays'
271  call display_message( program_name, message, failure )
272  stop
273  end if
274 
275 end do sensor_loop
276 
277  ! Destroy CRTM instance
278  ! ---------------------
279  ! write( *, '( /5x, "Destroying the CRTM..." )' )
280  err_stat = crtm_destroy( chinfo )
281  if ( err_stat /= success ) THEN
282  message = 'Error destroying CRTM'
283  call display_message( program_name, message, failure )
284  stop
285  end if
286 
287 end subroutine ufo_aodcrtm_simobs
288 
289 ! ------------------------------------------------------------------------------
290 
291 end module ufo_aodcrtm_mod
Fortran module to handle aod observations.
character(maxvarlen), parameter varname_tmplate
subroutine ufo_aodcrtm_delete(self)
character(len=maxvarlen), dimension(5), parameter varin_default
subroutine ufo_aodcrtm_simobs(self, geovals, obss, nvars, nlocs, hofx)
subroutine ufo_aodcrtm_setup(self, f_confOper, channels)
Fortran module to provide code shared between nonlinear and tlm/adm radiance calculations.
subroutine, public crtm_conf_setup(conf, f_confOpts, f_confOper)
subroutine, public load_aerosol_data(n_profiles, n_layers, geovals, aerosol_option, atm)
subroutine, public assign_aerosol_names(aerosol_option, var_aerosols)
subroutine, public crtm_conf_delete(conf)
subroutine, public load_atm_data(n_Profiles, n_Layers, geovals, atm, conf)
subroutine, public ufo_geovals_get_var(self, varname, geoval)
character(len=maxvarlen), parameter, public var_prsi
integer function, public ufo_vars_getindex(vars, varname)
character(len=maxvarlen), parameter, public var_oz
character(len=maxvarlen), parameter, public var_prs
character(len=maxvarlen), parameter, public var_rh
character(len=maxvarlen), parameter, public var_mixr
character(len=maxvarlen), parameter, public var_ts
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