FV3 Bundle
ufo_radiance_utils_mod.F90
Go to the documentation of this file.
1 ! (C) Copyright 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 provide code shared between nonlinear and tlm/adm radiance calculations
7 
9 
10 use iso_c_binding
11 use config_mod
12 use kinds
13 
14 use crtm_module
15 
16 use ufo_vars_mod
18 use ufo_basis_mod, only: ufo_basis
19 use obsspace_mod
20 
21 implicit none
22 private
23 
24 public rad_conf
25 public rad_conf_setup
26 public rad_conf_delete
27 public load_atm_data
28 public load_sfc_data
29 public load_geom_data
30 
31 integer, parameter, public :: max_string=800
32 
33 !Type for general config
35  integer :: n_sensors
36  integer :: n_absorbers
37  integer :: n_clouds
38  integer :: n_aerosols
39  integer, allocatable :: skiplist(:)
40  character(len=255), allocatable :: sensor_id(:)
41  character(len=255) :: endian_type
42  character(len=255) :: coefficient_path
43 end type rad_conf
44 
45 contains
46 
47 ! ------------------------------------------------------------------------------
48 
49 subroutine rad_conf_setup(rc, c_conf)
50 
51 implicit none
52 type(rad_conf), intent(inout) :: rc
53 type(c_ptr), intent(in) :: c_conf
54 
55 character(len=1023) :: skipchannels
56 integer :: nskip, i
57 character(len=100), allocatable :: skiplist_str(:)
58 
59  !Some config needs to come from user
60  !-----------------------------------
61 
62  !Number of sensors, each call to CRTM will be for a single sensor
63  !type (zenith/scan angle will be different)
64  rc%n_Sensors = 1
65 
66  !Number of absorbers, clouds and aerosols (should match what model will provide)
67  rc%n_Absorbers = config_get_int(c_conf,"n_Absorbers")
68  rc%n_Clouds = config_get_int(c_conf,"n_Clouds" )
69  rc%n_Aerosols = config_get_int(c_conf,"n_Aerosols" )
70 
71  !Allocate SENSOR_ID
72  allocate(rc%SENSOR_ID(rc%n_Sensors))
73 
74  !Get sensor ID from config
75  rc%SENSOR_ID(rc%n_Sensors) = config_get_string(c_conf,len(rc%SENSOR_ID(rc%n_Sensors)),"Sensor_ID")
76 
77  !ENDIAN type
78  rc%ENDIAN_TYPE = config_get_string(c_conf,len(rc%ENDIAN_TYPE),"EndianType")
79 
80  !Path to coefficient files
81  rc%COEFFICIENT_PATH = config_get_string(c_conf,len(rc%COEFFICIENT_PATH),"CoefficientPath")
82 
83  !Channels to skip
84  if (config_element_exists(c_conf,"SkipChannels")) then
85  skipchannels = config_get_string(c_conf,len(skipchannels),"SkipChannels")
86  nskip = 1 + count(transfer(skipchannels, 'a', len(skipchannels)) == ",")
87  allocate(skiplist_str(nskip))
88  read(skipchannels,*) skiplist_str
89  else
90  nskip = 0
91  endif
92  allocate(rc%skiplist(nskip))
93  do i = 1,nskip
94  read(skiplist_str(i),*) rc%skiplist(i)
95  enddo
96 
97 end subroutine rad_conf_setup
98 
99 ! -----------------------------------------------------------------------------
100 
101 subroutine rad_conf_delete(rc)
103 implicit none
104 type(rad_conf), intent(inout) :: rc
105 
106  deallocate(rc%SENSOR_ID)
107  deallocate(rc%skiplist)
108 
109 end subroutine rad_conf_delete
110 
111 ! ------------------------------------------------------------------------------
112 
113 subroutine load_atm_data(N_PROFILES,N_LAYERS,geovals,atm)
115 implicit none
116 integer, intent(in) :: n_profiles, n_layers
117 type(ufo_geovals), intent(in) :: geovals
118 type(crtm_atmosphere_type), intent(inout) :: atm(:)
119 
120 ! Local variables
121 integer :: k1
122 type(ufo_geoval), pointer :: geoval
123 character(MAXVARLEN) :: varname
124 character(max_string) :: err_msg
125 
126  ! Print profile and absorber definitions
127  ! --------------------------------------
128  do k1 = 1,geovals%nvar
129  varname = geovals%variables%fldnames(k1)
130  print *, k1, varname
131  end do
132 
133  ! Populate the atmosphere structures for CRTM (atm(k1), for the k1-th profile)
134  ! ----------------------------------------------------------------------------
135  do k1 = 1,n_profiles
136  call ufo_geovals_get_var(geovals, var_tv, geoval)
137 
138  ! Check model levels is consistent in geovals & crtm
139  if (k1 == 1) then
140  if (geoval%nval /= n_layers) then
141  write(err_msg,*) 'Load_Atm_Data error: layers inconsistent!'
142  call abor1_ftn(err_msg)
143  endif
144  endif
145 
146  atm(k1)%Temperature(1:n_layers) = geoval%vals(:,k1)
147 
148  call ufo_geovals_get_var(geovals, var_prs, geoval)
149  atm(k1)%Pressure(1:n_layers) = geoval%vals(:,k1)
150  call ufo_geovals_get_var(geovals, var_prsi, geoval)
151  atm(k1)%Level_Pressure(:) = geoval%vals(:,k1)
152  atm(k1)%Climatology = us_standard_atmosphere
153  atm(k1)%Absorber_Id(1:1) = (/ h2o_id /)
154  atm(k1)%Absorber_Units(1:1) = (/ mass_mixing_ratio_units /)
155  call ufo_geovals_get_var(geovals, var_mixr, geoval)
156  atm(k1)%Absorber(1:n_layers,1) = geoval%vals(:,k1)
157  atm(k1)%Absorber_Id(2:2) = (/ o3_id /)
158  atm(k1)%Absorber_Units(2:2) = (/ volume_mixing_ratio_units /)
159  call ufo_geovals_get_var(geovals, var_oz, geoval)
160  atm(k1)%Absorber(1:n_layers,2) = geoval%vals(:,k1)
161 
162  atm(k1)%Absorber_Id(3:3) = (/ co2_id /)
163  atm(k1)%Absorber_Units(3:3) = (/ volume_mixing_ratio_units /)
164  call ufo_geovals_get_var(geovals, var_co2, geoval)
165  atm(k1)%Absorber(1:n_layers,3) = geoval%vals(:,k1)
166 
167  atm(k1)%Cloud(1)%Type = water_cloud
168  call ufo_geovals_get_var(geovals, var_clw, geoval)
169  atm(k1)%Cloud(1)%Water_Content = geoval%vals(:,k1)
170  call ufo_geovals_get_var(geovals, var_clwefr, geoval)
171  atm(k1)%Cloud(1)%Effective_Radius = geoval%vals(:,k1)
172 
173  atm(k1)%Cloud(2)%Type = ice_cloud
174  call ufo_geovals_get_var(geovals, var_cli, geoval)
175  atm(k1)%Cloud(2)%Water_Content = geoval%vals(:,k1)
176  call ufo_geovals_get_var(geovals, var_cliefr, geoval)
177  atm(k1)%Cloud(2)%Effective_Radius = geoval%vals(:,k1)
178  end do
179 
180  end subroutine load_atm_data
181 
182 ! ------------------------------------------------------------------------------
183 
184 subroutine load_sfc_data(n_Profiles,n_Layers,N_Channels,geovals,sfc,chinfo,obss)
186 implicit none
187 integer, intent(in) :: n_profiles, n_layers, n_channels
188 type(ufo_geovals), intent(in) :: geovals
189 type(crtm_surface_type), intent(inout) :: sfc(:)
190 type(crtm_channelinfo_type), intent(in) :: chinfo(:)
191 type(c_ptr), value, intent(in) :: obss
192 
193 type(ufo_geoval), pointer :: geoval
194 integer :: k1, n1
195 
196 ! Surface type definitions for default SfcOptics definitions
197 ! for IR and VIS, this is the NPOESS reflectivities.
198 integer, parameter :: tundra_surface_type = 10 ! NPOESS Land surface type for IR/VIS Land SfcOptics
199 integer, parameter :: scrub_surface_type = 7 ! NPOESS Land surface type for IR/VIS Land SfcOptics
200 integer, parameter :: coarse_soil_type = 1 ! Soil type for MW land SfcOptics
201 integer, parameter :: groundcover_vegetation_type = 7 ! Vegetation type for MW Land SfcOptics
202 integer, parameter :: bare_soil_vegetation_type = 11 ! Vegetation type for MW Land SfcOptics
203 integer, parameter :: sea_water_type = 1 ! Water type for all SfcOptics
204 integer, parameter :: fresh_snow_type = 2 ! NPOESS Snow type for IR/VIS SfcOptics
205 integer, parameter :: fresh_ice_type = 1 ! NPOESS Ice type for IR/VIS SfcOptics
206 
207 character(len=100) :: varname_tmplate
208 character(len=200) :: varname
209 
210 real(kind_real), allocatable :: obstb(:,:)
211 
212  varname_tmplate = "brightness_temperature"
213 
214  allocate(obstb(n_profiles, n_channels))
215 
216  do n1 = 1,n_channels
217  !Get the variable name for this channel
218  call get_var_name(varname_tmplate,n1,varname)
219  call obsspace_get_db(obss, "ObsValue", varname, obstb(:,n1))
220  enddo
221 
222  !Loop over all n_Profiles, i.e. number of locations
223  do k1 = 1,n_profiles
224 
225  !Pass sensor information
226  sfc(k1)%sensordata%sensor_id = chinfo(1)%sensor_id
227  sfc(k1)%sensordata%wmo_sensor_id = chinfo(1)%wmo_sensor_id
228  sfc(k1)%sensordata%wmo_satellite_id = chinfo(1)%wmo_satellite_id
229  sfc(k1)%sensordata%sensor_channel = chinfo(1)%sensor_channel
230 
231  !Pass observation value
232  do n1 = 1, n_channels
233  sfc(k1)%sensordata%tb(n1) = obstb(k1,n1)
234  enddo
235 
236  !Water_type
237  sfc(k1)%Water_Type = sea_water_type !** NOTE: need to check how to determine fresh vs sea water types (salinity???)
238 
239  !Wind_Speed
240  call ufo_geovals_get_var(geovals, var_sfc_wspeed, geoval)
241  sfc(k1)%Wind_Speed = geoval%vals(1,k1)
242 
243  !Wind_Direction
244  call ufo_geovals_get_var(geovals, var_sfc_wdir, geoval)
245  sfc(k1)%Wind_Direction = geoval%vals(1,k1)
246 
247  !Water_Coverage
248  call ufo_geovals_get_var(geovals, var_sfc_wfrac, geoval)
249  sfc(k1)%Water_Coverage = geoval%vals(1,k1)
250 
251  !Water_Temperature
252  call ufo_geovals_get_var(geovals, var_sfc_wtmp, geoval)
253  sfc(k1)%Water_Temperature = geoval%vals(1,k1)
254 
255  !Ice_Coverage
256  call ufo_geovals_get_var(geovals, var_sfc_ifrac, geoval)
257  sfc(k1)%Ice_Coverage = geoval%vals(1,k1)
258 
259  !Ice_Temperature
260  call ufo_geovals_get_var(geovals, var_sfc_itmp, geoval)
261  sfc(k1)%Ice_Temperature = geoval%vals(1,k1)
262 
263  !Snow_Coverage
264  call ufo_geovals_get_var(geovals, var_sfc_sfrac, geoval)
265  sfc(k1)%Snow_Coverage = geoval%vals(1,k1)
266 
267  !Snow_Temperature
268  call ufo_geovals_get_var(geovals, var_sfc_stmp, geoval)
269  sfc(k1)%Snow_Temperature = geoval%vals(1,k1)
270 
271  !Snow_Depth
272  call ufo_geovals_get_var(geovals, var_sfc_sdepth, geoval)
273  sfc(k1)%Snow_Depth = geoval%vals(1,k1)
274 
275  !Land_Type
276  call ufo_geovals_get_var(geovals, var_sfc_landtyp, geoval)
277  sfc(k1)%Land_Type = int(geoval%vals(1,k1))
278 
279  !Land_Coverage
280  call ufo_geovals_get_var(geovals, var_sfc_lfrac, geoval)
281  sfc(k1)%Land_Coverage = geoval%vals(1,k1)
282 
283  !Land_Temperature
284  call ufo_geovals_get_var(geovals, var_sfc_ltmp, geoval)
285  sfc(k1)%Land_Temperature = geoval%vals(1,k1)
286 
287  !Lai
288  call ufo_geovals_get_var(geovals, var_sfc_lai, geoval)
289  sfc(k1)%Lai = geoval%vals(1,k1)
290 
291  !Vegetation_Fraction
292  call ufo_geovals_get_var(geovals, var_sfc_vegfrac, geoval)
293  sfc(k1)%Vegetation_Fraction = geoval%vals(1,k1)
294 
295  !Vegetation_Type
296  call ufo_geovals_get_var(geovals, var_sfc_vegtyp, geoval)
297  sfc(k1)%Vegetation_Type = int(geoval%vals(1,k1))
298 
299  !Soil_Type
300  call ufo_geovals_get_var(geovals, var_sfc_soiltyp, geoval)
301  sfc(k1)%Soil_Type = int(geoval%vals(1,k1))
302 
303  !Soil_Moisture_Content
304  call ufo_geovals_get_var(geovals, var_sfc_soilm, geoval)
305  sfc(k1)%Soil_Moisture_Content = geoval%vals(1,k1)
306 
307  !Soil_Temperature
308  call ufo_geovals_get_var(geovals, var_sfc_soilt, geoval)
309  sfc(k1)%Soil_Temperature = geoval%vals(1,k1)
310 
311  end do
312 
313  deallocate(obstb)
314 
315 end subroutine load_sfc_data
316 
317 ! ------------------------------------------------------------------------------
318 
319 subroutine load_geom_data(obss,geo)
321 implicit none
322 type(c_ptr), value, intent(in) :: obss
323 type(crtm_geometry_type), intent(inout) :: geo(:)
324 real(kind_real), allocatable :: tmpvar(:)
325 integer :: nlocs
326 
327  nlocs = obsspace_get_nlocs(obss)
328  allocate(tmpvar(nlocs))
329 
330  call obsspace_get_db(obss, "ObsValue", "Sat_Zenith_Angle", tmpvar)
331  geo(:)%Sensor_Zenith_Angle = tmpvar(:)
332 
333  call obsspace_get_db(obss, "ObsValue", "Sol_Zenith_Angle", tmpvar)
334  geo(:)%Source_Zenith_Angle = tmpvar(:)
335 
336  call obsspace_get_db(obss, "ObsValue", "Sat_Azimuth_Angle", tmpvar)
337  geo(:)%Sensor_Azimuth_Angle = tmpvar(:)
338 
339  call obsspace_get_db(obss, "ObsValue", "Sol_Azimuth_Angle", tmpvar)
340  geo(:)%Source_Azimuth_Angle = tmpvar(:)
341 
342  call obsspace_get_db(obss, "ObsValue", "Scan_Position", tmpvar)
343  geo(:)%Ifov = tmpvar(:)
344 
345  call obsspace_get_db(obss, "ObsValue", "Scan_Angle", tmpvar) !The Sensor_Scan_Angle is optional
346  geo(:)%Sensor_Scan_Angle = tmpvar(:)
347 
348  deallocate(tmpvar)
349 
350 end subroutine load_geom_data
351 
352 ! ------------------------------------------------------------------------------
353 
354 subroutine get_var_name(varname_tmplate,n,varname)
356 character(len=*), intent(in) :: varname_tmplate
357 integer, intent(in) :: n
358 character(len=*), intent(out) :: varname
359 
360 character(len=3) :: chan
361 
362  ! pass in varname_tmplate = "brigtness_temperature"
363  write(chan, '(I0)') n
364  varname = trim(varname_tmplate) // '_' // trim(chan) // '_'
365 
366 end subroutine get_var_name
367 
368 ! -----------------------------------------------------------------------------
369 
370 end module ufo_radiance_utils_mod
subroutine, public ufo_geovals_get_var(self, varname, geoval, status)
character(len=maxvarlen), public var_sfc_wspeed
character(len=maxvarlen), public var_mixr
subroutine get_var_name(varname_tmplate, n, varname)
character(len=maxvarlen), public var_prsi
character(len=maxvarlen), public var_sfc_vegfrac
Fortran module to provide code shared between nonlinear and tlm/adm radiance calculations.
character(len=maxvarlen), public var_co2
integer, parameter max_string
subroutine, public load_atm_data(N_PROFILES, N_LAYERS, geovals, atm)
character(len=maxvarlen), public var_sfc_lfrac
character(len=maxvarlen), public var_sfc_soilt
character(len=maxvarlen), public var_clw
character(len=maxvarlen), public var_sfc_sfrac
subroutine, public load_sfc_data(n_Profiles, n_Layers, N_Channels, geovals, sfc, chinfo, obss)
subroutine, public load_geom_data(obss, geo)
character(len=maxvarlen), public var_sfc_wdir
character(len=maxvarlen), public var_cli
character(len=maxvarlen), public var_sfc_stmp
character(len=maxvarlen), public var_sfc_lai
character(len=maxvarlen), public var_oz
subroutine, public rad_conf_setup(rc, c_conf)
subroutine, public rad_conf_delete(rc)
character(len=maxvarlen), public var_prs
character(len=maxvarlen), public var_sfc_wfrac
character(len=maxvarlen), public var_sfc_soiltyp
character(len=maxvarlen), public var_clwefr
type to hold interpolated fields required by the obs operators
character(len=maxvarlen), public var_sfc_itmp
character(len=maxvarlen), public var_sfc_soilm
character(len=maxvarlen), public var_cliefr
character(len=maxvarlen), public var_sfc_vegtyp
character(len=maxvarlen), public var_sfc_ifrac
character(len=maxvarlen), public var_sfc_sdepth
character(len=maxvarlen), public var_sfc_ltmp
character(len=maxvarlen), public var_sfc_landtyp
Fortran interface to ObsSpace.
Definition: obsspace_mod.F90:9
character(len=maxvarlen), public var_sfc_wtmp
character(len=maxvarlen), public var_tv
integer function, public obsspace_get_nlocs(c_dom)
Return the number of observational locations.
type to hold interpolated field for one variable, one observation