FV3 Bundle
CRTM_Tangent_Linear_Module.f90
Go to the documentation of this file.
1 !
2 ! CRTM_Tangent_Linear_Module
3 !
4 ! Module containing the CRTM tangent-linear model function.
5 !
6 !
7 ! CREATION HISTORY:
8 ! Written by: Paul van Delst, 27-Jan-2005
9 ! paul.vandelst@noaa.gov
10 !
11 
13 
14 
15  ! ------------
16  ! Module usage
17  ! ------------
18  USE type_kinds, ONLY: fp
20  USE crtm_parameters, ONLY: set,not_set,zero,one, &
21  max_n_layers , &
24  max_n_stokes , &
25  max_n_angles , &
28  max_n_streams, &
30  USE crtm_spccoeff, ONLY: sc, &
31  spccoeff_isvisiblesensor, &
32  spccoeff_ismicrowavesensor
55  USE crtm_predictor, ONLY: crtm_pvar_type => ivar_type, &
58  USE crtm_atmabsorption, ONLY: crtm_aavar_type => ivar_type, &
70  USE crtm_atmoptics, ONLY: aovar_type , &
71  aovar_create, &
83  USE crtm_rtsolution, ONLY: crtm_rtsolution_type , &
87  USE rtv_define, ONLY: rtv_type , &
89  rtv_destroy , &
96 
99 
100  USE crtm_nltecorrection, ONLY: nlte_predictor_type , &
101  nlte_predictor_isactive , &
106 
109 
112 
113  ! Internal variable definition modules
114  ! ...CloudScatter
115  USE csvar_define, ONLY: csvar_type, &
117  csvar_destroy , &
119  ! ...AerosolScatter
120  USE asvar_define, ONLY: asvar_type, &
122  asvar_destroy , &
124 
125 
126  ! -----------------------
127  ! Disable implicit typing
128  ! -----------------------
129  IMPLICIT NONE
130 
131 
132  ! ------------
133  ! Visibilities
134  ! ------------
135  ! Everything private by default
136  PRIVATE
137  ! Public procedures
138  PUBLIC :: crtm_tangent_linear
140 
141 
142  ! -----------------
143  ! Module parameters
144  ! -----------------
145  ! Version Id for the module
146  CHARACTER(*), PARAMETER :: module_version_id = &
147  '$Id: CRTM_Tangent_Linear_Module.f90 60152 2015-08-13 19:19:13Z paul.vandelst@noaa.gov $'
148 
149 
150 CONTAINS
151 
152 
153 !--------------------------------------------------------------------------------
154 !:sdoc+:
155 !
156 ! NAME:
157 ! CRTM_Tangent_Linear
158 !
159 ! PURPOSE:
160 ! Function that calculates tangent-linear top-of-atmosphere (TOA)
161 ! radiances and brightness temperatures for an input atmospheric
162 ! profile or profile set and user specified satellites/channels.
163 !
164 ! CALLING SEQUENCE:
165 ! Error_Status = CRTM_Tangent_Linear( Atmosphere , &
166 ! Surface , &
167 ! Atmosphere_TL , &
168 ! Surface_TL , &
169 ! Geometry , &
170 ! ChannelInfo , &
171 ! RTSolution , &
172 ! RTSolution_TL , &
173 ! Options = Options )
174 !
175 ! INPUTS:
176 ! Atmosphere: Structure containing the Atmosphere data.
177 ! UNITS: N/A
178 ! TYPE: CRTM_Atmosphere_type
179 ! DIMENSION: Rank-1 (n_Profiles)
180 ! ATTRIBUTES: INTENT(IN)
181 !
182 ! Surface: Structure containing the Surface data.
183 ! UNITS: N/A
184 ! TYPE: CRTM_Surface_type
185 ! DIMENSION: Same as input Atmosphere structure
186 ! ATTRIBUTES: INTENT(IN)
187 !
188 ! Atmosphere_TL: Structure containing the tangent-linear Atmosphere data.
189 ! UNITS: N/A
190 ! TYPE: CRTM_Atmosphere_type
191 ! DIMENSION: Same as input Atmosphere structure
192 ! ATTRIBUTES: INTENT(IN)
193 !
194 ! Surface_TL: Structure containing the tangent-linear Surface data.
195 ! UNITS: N/A
196 ! TYPE: CRTM_Surface_type
197 ! DIMENSION: Same as input Atmosphere structure
198 ! ATTRIBUTES: INTENT(IN)
199 !
200 ! Geometry: Structure containing the view geometry
201 ! information.
202 ! UNITS: N/A
203 ! TYPE: CRTM_Geometry_type
204 ! DIMENSION: Same as input Atmosphere structure
205 ! ATTRIBUTES: INTENT(IN)
206 !
207 ! ChannelInfo: Structure returned from the CRTM_Init() function
208 ! that contains the satellite/sensor channel index
209 ! information.
210 ! UNITS: N/A
211 ! TYPE: CRTM_ChannelInfo_type
212 ! DIMENSION: Rank-1 (n_Sensors)
213 ! ATTRIBUTES: INTENT(IN)
214 !
215 ! OUTPUTS:
216 ! RTSolution: Structure containing the solution to the RT equation
217 ! for the given inputs.
218 ! UNITS: N/A
219 ! TYPE: CRTM_RTSolution_type
220 ! DIMENSION: Rank-2 (n_Channels x n_Profiles)
221 ! ATTRIBUTES: INTENT(IN OUT)
222 !
223 ! RTSolution_TL: Structure containing the solution to the tangent-
224 ! linear RT equation for the given inputs.
225 ! UNITS: N/A
226 ! TYPE: CRTM_RTSolution_type
227 ! DIMENSION: Rank-2 (n_Channels x n_Profiles)
228 ! ATTRIBUTES: INTENT(IN OUT)
229 !
230 ! OPTIONAL INPUTS:
231 ! Options: Options structure containing the optional forward model
232 ! arguments for the CRTM.
233 ! UNITS: N/A
234 ! TYPE: CRTM_Options_type
235 ! DIMENSION: Same as input Atmosphere structure
236 ! ATTRIBUTES: INTENT(IN), OPTIONAL
237 !
238 ! FUNCTION RESULT:
239 ! Error_Status: The return value is an integer defining the error status.
240 ! The error codes are defined in the Message_Handler module.
241 ! If == SUCCESS the computation was sucessful
242 ! == FAILURE an unrecoverable error occurred
243 ! UNITS: N/A
244 ! TYPE: INTEGER
245 ! DIMENSION: Scalar
246 !
247 ! COMMENTS:
248 ! - The Options optional input structure arguments contain
249 ! spectral information (e.g. emissivity) that must have the same
250 ! spectral dimensionality (the "L" dimension) as the output
251 ! RTSolution structures.
252 !
253 !:sdoc-:
254 !--------------------------------------------------------------------------------
255 
256  FUNCTION crtm_tangent_linear( &
257  Atmosphere , & ! FWD Input, M
258  Surface , & ! FWD Input, M
259  Atmosphere_TL, & ! TL Input, M
260  Surface_TL , & ! TL Input, M
261  Geometry , & ! Input, M
262  ChannelInfo , & ! Input, n_Sensors
263  RTSolution , & ! FWD Output, L x M
264  RTSolution_TL, & ! TL Output, L x M
265  Options ) & ! Optional FWD input, M
266  result( error_status )
267  ! Arguments
268  TYPE(crtm_atmosphere_type) , INTENT(IN) :: atmosphere(:) ! M
269  TYPE(crtm_surface_type) , INTENT(IN) :: surface(:) ! M
270  TYPE(crtm_atmosphere_type) , INTENT(IN) :: atmosphere_tl(:) ! M
271  TYPE(crtm_surface_type) , INTENT(IN) :: surface_tl(:) ! M
272  TYPE(crtm_geometry_type) , INTENT(IN) :: geometry(:) ! M
273  TYPE(crtm_channelinfo_type) , INTENT(IN) :: channelinfo(:) ! n_Sensors
274  TYPE(crtm_rtsolution_type) , INTENT(IN OUT) :: rtsolution(:,:) ! L x M
275  TYPE(crtm_rtsolution_type) , INTENT(IN OUT) :: rtsolution_tl(:,:) ! L x M
276  TYPE(crtm_options_type), OPTIONAL, INTENT(IN) :: options(:) ! M
277  ! Function result
278  INTEGER :: error_status
279  ! Local parameters
280  CHARACTER(*), PARAMETER :: routine_name = 'CRTM_Tangent_Linear'
281  ! Local variables
282  CHARACTER(256) :: message
283  LOGICAL :: options_present
284  LOGICAL :: check_input
285  LOGICAL :: user_emissivity, user_direct_reflectivity, user_n_streams
286  LOGICAL :: user_antcorr, compute_antcorr
287  LOGICAL :: apply_nlte_correction
288  LOGICAL :: atmosphere_invalid, surface_invalid, geometry_invalid, options_invalid
289  INTEGER :: rt_algorithm_id
290  INTEGER :: status_fwd, status_tl
291  INTEGER :: ifov
292  INTEGER :: n, n_sensors, sensorindex
293  INTEGER :: l, n_channels, channelindex
294  INTEGER :: m, n_profiles
295  INTEGER :: ln
296  INTEGER :: n_full_streams, mth_azi
297  REAL(fp) :: source_za
298  REAL(fp) :: wavenumber
299  REAL(fp) :: transmittance, transmittance_tl
300  ! Local ancillary input structure
301  TYPE(crtm_ancillaryinput_type) :: ancillaryinput
302  ! Local options structure for default values
303  TYPE(crtm_options_type) :: default_options
304  ! Local atmosphere structure for extra layering
305  TYPE(crtm_atmosphere_type) :: atm, atm_tl
306  ! Component variables
307  TYPE(crtm_geometryinfo_type) :: geometryinfo
308  TYPE(crtm_predictor_type) :: predictor, predictor_tl
309  TYPE(crtm_atmoptics_type) :: atmoptics, atmoptics_tl
310  TYPE(crtm_sfcoptics_type) :: sfcoptics, sfcoptics_tl
311  ! Component variable internals
312  TYPE(crtm_pvar_type) :: pvar ! Predictor
313  TYPE(crtm_aavar_type) :: aavar ! AtmAbsorption
314  TYPE(csvar_type) :: csvar ! CloudScatter
315  TYPE(asvar_type) :: asvar ! AerosolScatter
316  TYPE(aovar_type) :: aovar ! AtmOptics
317  TYPE(rtv_type) :: rtv ! RTSolution
318  ! NLTE correction term predictors
319  TYPE(nlte_predictor_type) :: nlte_predictor, nlte_predictor_tl
320 
321 
322  ! ------
323  ! SET UP
324  ! ------
325  error_status = success
326 
327 
328  ! If no sensors or channels, simply return
329  n_sensors = SIZE(channelinfo)
330  n_channels = sum(crtm_channelinfo_n_channels(channelinfo))
331  IF ( n_sensors == 0 .OR. n_channels == 0 ) RETURN
332 
333 
334  ! Check output arrays
335  IF ( SIZE(rtsolution, dim=1) < n_channels .OR. &
336  SIZE(rtsolution_tl,dim=1) < n_channels ) THEN
337  error_status = failure
338  WRITE( message,'("Output RTSolution structure arrays too small (",i0," and ",i0,&
339  &") to hold results for the number of requested channels (",i0,")")') &
340  SIZE(rtsolution,dim=1), SIZE(rtsolution_tl,dim=1), n_channels
341  CALL display_message( routine_name, message, error_status )
342  RETURN
343  END IF
344 
345 
346  ! Check the number of profiles
347  ! ...Number of atmospheric profiles.
348  n_profiles = SIZE(atmosphere)
349  ! ...Check the profile dimensionality of the other mandatory arguments
350  IF ( SIZE(surface) /= n_profiles .OR. &
351  SIZE(atmosphere_tl) /= n_profiles .OR. &
352  SIZE(surface_tl) /= n_profiles .OR. &
353  SIZE(geometry) /= n_profiles .OR. &
354  SIZE(rtsolution, dim=2) /= n_profiles .OR. &
355  SIZE(rtsolution_tl,dim=2) /= n_profiles ) THEN
356  error_status = failure
357  message = 'Inconsistent profile dimensionality for input arguments.'
358  CALL display_message( routine_name, message, error_status )
359  RETURN
360  END IF
361  ! ...Check the profile dimensionality of the other optional arguments
362  options_present = .false.
363  IF ( PRESENT(options) ) THEN
364  options_present = .true.
365  IF ( SIZE(options) /= n_profiles ) THEN
366  error_status = failure
367  message = 'Inconsistent profile dimensionality for Options optional input argument.'
368  CALL display_message( routine_name, message, error_status )
369  RETURN
370  END IF
371  END IF
372 
373 
374  ! Allocate the profile independent surface optics local structure
375  CALL crtm_sfcoptics_create( sfcoptics , max_n_angles, max_n_stokes )
376  CALL crtm_sfcoptics_create( sfcoptics_tl, max_n_angles, max_n_stokes )
377  IF ( (.NOT. crtm_sfcoptics_associated(sfcoptics )) .OR. &
378  (.NOT. crtm_sfcoptics_associated(sfcoptics_tl)) ) THEN
379  error_status = failure
380  message = 'Error allocating SfcOptics data structures'
381  CALL display_message( routine_name, message, error_status )
382  RETURN
383  END IF
384 
385 
386  ! ------------
387  ! PROFILE LOOP
388  ! ------------
389  profile_loop: DO m = 1, n_profiles
390 
391 
392  ! Check the cloud and aerosol coeff. data for cases with clouds and aerosol
393  IF( atmosphere(m)%n_Clouds > 0 .AND. .NOT. crtm_cloudcoeff_isloaded() )THEN
394  error_status = failure
395  WRITE( message,'("The CloudCoeff data must be loaded (with CRTM_Init routine) ", &
396  &"for the cloudy case profile #",i0)' ) m
397  CALL display_message( routine_name, message, error_status )
398  RETURN
399  END IF
400  IF( atmosphere(m)%n_Aerosols > 0 .AND. .NOT. crtm_aerosolcoeff_isloaded() )THEN
401  error_status = failure
402  WRITE( message,'("The AerosolCoeff data must be loaded (with CRTM_Init routine) ", &
403  &"for the aerosol case profile #",i0)' ) m
404  CALL display_message( routine_name, message, error_status )
405  RETURN
406  END IF
407 
408 
409  ! Check the optional Options structure argument
410  ! ...Specify default actions
411  check_input = default_options%Check_Input
412  user_emissivity = default_options%Use_Emissivity
413  user_antcorr = default_options%Use_Antenna_Correction
414  apply_nlte_correction = default_options%Apply_NLTE_Correction
415  rt_algorithm_id = default_options%RT_Algorithm_Id
416  user_n_streams = default_options%Use_N_Streams
417  ! ...Check the Options argument
418  IF (options_present) THEN
419  ! Override input checker with option
420  check_input = options(m)%Check_Input
421  ! Check if the supplied emissivity should be used
422  user_emissivity = options(m)%Use_Emissivity
423  IF ( options(m)%Use_Emissivity ) THEN
424  ! Are the channel dimensions consistent
425  IF ( options(m)%n_Channels < n_channels ) THEN
426  error_status = failure
427  WRITE( message,'( "Input Options channel dimension (", i0, ") is less ", &
428  &"than the number of requested channels (",i0, ")" )' ) &
429  options(m)%n_Channels, n_channels
430  CALL display_message( routine_name, message, error_status )
431  RETURN
432  END IF
433  ! Check if the supplied direct reflectivity should be used
434  user_direct_reflectivity = options(m)%Use_Direct_Reflectivity
435  END IF
436  ! Check if antenna correction should be attempted
437  user_antcorr = options(m)%Use_Antenna_Correction
438  ! Set NLTE correction option
439  apply_nlte_correction = options(m)%Apply_NLTE_Correction
440 
441  ! Copy over ancillary input
442  ancillaryinput%SSU = options(m)%SSU
443  ancillaryinput%Zeeman = options(m)%Zeeman
444  ! Copy over surface optics input
445  sfcoptics%Use_New_MWSSEM = .NOT. options(m)%Use_Old_MWSSEM
446  ! Specify the RT algorithm
447  rt_algorithm_id = options(m)%RT_Algorithm_Id
448  ! Check if n_Streams should be used
449  user_n_streams = options(m)%Use_N_Streams
450  ! Check value for nstreams
451  IF ( user_n_streams ) THEN
452  IF ( options(m)%n_Streams <= 0 .OR. mod(options(m)%n_Streams,2) /= 0 .OR. &
453  options(m)%n_Streams > max_n_streams ) THEN
454  error_status = failure
455  WRITE( message,'( "Input Options n_Streams (", i0, ") is invalid" )' ) &
456  options(m)%n_Streams
457  CALL display_message( routine_name, message, error_status )
458  RETURN
459  END IF
460  END IF
461  END IF
462 
463 
464  ! Check the input data if required
465  IF ( check_input ) THEN
466  ! ...Mandatory inputs
467  atmosphere_invalid = .NOT. crtm_atmosphere_isvalid( atmosphere(m) )
468  surface_invalid = .NOT. crtm_surface_isvalid( surface(m) )
469  geometry_invalid = .NOT. crtm_geometry_isvalid( geometry(m) )
470  IF ( atmosphere_invalid .OR. surface_invalid .OR. geometry_invalid ) THEN
471  error_status = failure
472  WRITE( message,'("Input data check failed for profile #",i0)' ) m
473  CALL display_message( routine_name, message, error_status )
474  RETURN
475  END IF
476  ! ...Optional input
477  IF ( options_present ) THEN
478  options_invalid = .NOT. crtm_options_isvalid( options(m) )
479  IF ( options_invalid ) THEN
480  error_status = failure
481  WRITE( message,'("Options data check failed for profile #",i0)' ) m
482  CALL display_message( routine_name, message, error_status )
483  RETURN
484  END IF
485  END IF
486  END IF
487 
488 
489  ! Process geometry
490  ! ...Compute derived geometry
491  CALL crtm_geometryinfo_setvalue( geometryinfo, geometry=geometry(m) )
492  CALL crtm_geometryinfo_compute( geometryinfo )
493  ! ...Retrieve components into local variable
495  geometryinfo, &
496  ifov = ifov, &
497  source_zenith_angle = source_za )
498 
499 
500  ! Average surface skin temperature for multi-surface types
501  CALL crtm_compute_surfacet( surface(m), sfcoptics )
502  CALL crtm_compute_surfacet_tl( surface(m), surface_tl(m), sfcoptics_tl )
503 
504 
505  ! Add extra layers to current atmosphere profile
506  ! if necessary to handle upper atmosphere
507  error_status = crtm_atmosphere_addlayers( atmosphere(m), atm )
508  IF ( error_status /= success ) THEN
509  error_status = failure
510  WRITE( message,'("Error adding FWD extra layers to profile #",i0)' ) m
511  CALL display_message( routine_name, message, error_status )
512  RETURN
513  END IF
514  error_status = crtm_atmosphere_addlayers_tl( atmosphere(m), atmosphere_tl(m), atm_tl )
515  IF ( error_status /= success ) THEN
516  error_status = failure
517  WRITE( message,'("Error adding TL extra layers to profile #",i0)' ) m
518  CALL display_message( routine_name, message, error_status )
519  RETURN
520  END IF
521  ! ...Check the total number of Atm layers
522  IF ( atm%n_Layers > max_n_layers .OR. atm_tl%n_Layers > max_n_layers) THEN
523  error_status = failure
524  WRITE( message,'("Added layers [",i0,"] cause total [",i0,"] to exceed the ",&
525  &"maximum allowed [",i0,"] for profile #",i0)' ) &
526  atm%n_Added_Layers, atm%n_Layers, max_n_layers, m
527  CALL display_message( routine_name, message, error_status )
528  RETURN
529  END IF
530  ! ...Allocate the atmospheric optics structures based on Atm extension
531  CALL crtm_atmoptics_create( atmoptics, &
532  atm%n_Layers , &
535  CALL crtm_atmoptics_create( atmoptics_tl, &
536  atm%n_Layers , &
539  IF ( .NOT. crtm_atmoptics_associated( atmoptics ) .OR. &
540  .NOT. crtm_atmoptics_associated( atmoptics_tl ) ) THEN
541  error_status = failure
542  WRITE( message,'("Error allocating AtmOptics data structures for profile #",i0)' ) m
543  CALL display_message( routine_name, message, error_status )
544  RETURN
545  END IF
546  IF (options_present) THEN
547  ! Set Scattering Switch
548  atmoptics%Include_Scattering = options(m)%Include_Scattering
549  atmoptics_tl%Include_Scattering = options(m)%Include_Scattering
550  END IF
551  ! ...Allocate the atmospheric optics internal structure
552  CALL aovar_create( aovar, atm%n_Layers )
553 
554 
555  ! Allocate the scattering internal variables if necessary
556  ! ...Cloud
557  IF ( atm%n_Clouds > 0 ) THEN
558  CALL csvar_create( csvar, &
561  atm%n_Layers , &
562  atm%n_Clouds )
563  END IF
564  ! ...Aerosol
565  IF ( atm%n_Aerosols > 0 ) THEN
566  CALL asvar_create( asvar, &
569  atm%n_Layers , &
570  atm%n_Aerosols )
571  END IF
572 
573 
574  ! -----------
575  ! SENSOR LOOP
576  ! -----------
577  ! Initialise channel counter for sensor(n)/channel(l) count
578  ln = 0
579 
580  sensor_loop: DO n = 1, n_sensors
581 
582 
583  ! Shorter name
584  sensorindex = channelinfo(n)%Sensor_Index
585 
586 
587  ! Check if antenna correction to be applied for current sensor
588  IF ( user_antcorr .AND. &
589  accoeff_associated( sc(sensorindex)%AC ) .AND. &
590  ifov /= 0 ) THEN
591  compute_antcorr = .true.
592  ELSE
593  compute_antcorr = .false.
594  END IF
595 
596 
597  ! Compute predictors for AtmAbsorption calcs
598  ! ...Allocate the predictor structures
599  CALL crtm_predictor_create( &
600  predictor , &
601  atm%n_Layers, &
602  sensorindex , &
603  savefwv = 1 )
604  CALL crtm_predictor_create( &
605  predictor_tl, &
606  atm%n_Layers, &
607  sensorindex )
608  IF ( (.NOT. crtm_predictor_associated(predictor)) .OR. &
609  (.NOT. crtm_predictor_associated(predictor_tl)) ) THEN
610  error_status=failure
611  WRITE( message,'("Error allocating predictor structures for profile #",i0, &
612  &" and ",a," sensor.")' ) m, sc(sensorindex)%Sensor_Id
613  CALL display_message( routine_name, message, error_status )
614  RETURN
615  END IF
616  ! ...And now fill them
617  CALL crtm_compute_predictors( sensorindex , & ! Input
618  atm , & ! Input
619  geometryinfo , & ! Input
620  ancillaryinput, & ! Input
621  predictor , & ! Output
622  pvar ) ! Internal variable output
623  CALL crtm_compute_predictors_tl( sensorindex , & ! Input
624  atm , & ! Input
625  predictor , & ! Input
626  atm_tl , & ! Input
627  ancillaryinput, & ! Input
628  predictor_tl , & ! Output
629  pvar ) ! Internal variable input
630 
631 
632  ! Allocate the RTV structure if necessary
633  IF( (atm%n_Clouds > 0 .OR. &
634  atm%n_Aerosols > 0 .OR. &
635  spccoeff_isvisiblesensor( sc(sensorindex) ) ) .and. atmoptics%Include_Scattering ) THEN
636  CALL rtv_create( rtv, max_n_angles, max_n_legendre_terms, atm%n_Layers )
637  IF ( .NOT. rtv_associated(rtv) ) THEN
638  error_status=failure
639  WRITE( message,'("Error allocating RTV structure for profile #",i0, &
640  &" and ",a," sensor.")' ) m, trim(sc(sensorindex)%Sensor_Id)
641  CALL display_message( routine_name, message, error_status )
642  RETURN
643  END IF
644  ! Assign algorithm selector
645  rtv%RT_Algorithm_Id = rt_algorithm_id
646  END IF
647 
648 
649  ! Compute NLTE correction predictors
650  IF ( apply_nlte_correction ) THEN
651  CALL compute_nlte_predictor( &
652  sc(sensorindex)%NC, & ! Input
653  atm , & ! Input
654  geometryinfo , & ! Input
655  nlte_predictor ) ! Output
657  nlte_predictor , & ! FWD Input
658  atm_tl , & ! TL Input
659  nlte_predictor_tl ) ! TL Output
660  END IF
661 
662 
663  ! ------------
664  ! CHANNEL LOOP
665  ! ------------
666  channel_loop: DO l = 1, channelinfo(n)%n_Channels
667 
668  ! Channel setup
669  ! ...Skip channel if requested
670  IF ( .NOT. channelinfo(n)%Process_Channel(l) ) cycle channel_loop
671  ! ...Shorter name
672  channelindex = channelinfo(n)%Channel_Index(l)
673  ! ...Increment the processed channel counter
674  ln = ln + 1
675  ! ...Assign sensor+channel information to output
676  rtsolution(ln,m)%Sensor_Id = channelinfo(n)%Sensor_Id
677  rtsolution(ln,m)%WMO_Satellite_Id = channelinfo(n)%WMO_Satellite_Id
678  rtsolution(ln,m)%WMO_Sensor_Id = channelinfo(n)%WMO_Sensor_Id
679  rtsolution(ln,m)%Sensor_Channel = channelinfo(n)%Sensor_Channel(l)
680  rtsolution_tl(ln,m)%Sensor_Id = rtsolution(ln,m)%Sensor_Id
681  rtsolution_tl(ln,m)%WMO_Satellite_Id = rtsolution(ln,m)%WMO_Satellite_Id
682  rtsolution_tl(ln,m)%WMO_Sensor_Id = rtsolution(ln,m)%WMO_Sensor_Id
683  rtsolution_tl(ln,m)%Sensor_Channel = rtsolution(ln,m)%Sensor_Channel
684 
685 
686  ! Initialisations
687  CALL crtm_atmoptics_zero( atmoptics )
688  CALL crtm_atmoptics_zero( atmoptics_tl )
689 
690 
691  ! Determine the number of streams (n_Full_Streams) in up+downward directions
692  IF ( user_n_streams ) THEN
693  n_full_streams = options(m)%n_Streams
694  rtsolution(ln,m)%n_Full_Streams = n_full_streams + 2
695  rtsolution(ln,m)%Scattering_Flag = .true.
696  ELSE
697  n_full_streams = crtm_compute_nstreams( atm , & ! Input
698  sensorindex , & ! Input
699  channelindex , & ! Input
700  rtsolution(ln,m) ) ! Output
701  END IF
702  ! ...Transfer stream count to scattering structures
703  atmoptics%n_Legendre_Terms = n_full_streams
704  atmoptics_tl%n_Legendre_Terms = n_full_streams
705 
706 
707  ! Compute the gas absorption
708  CALL crtm_compute_atmabsorption( sensorindex , & ! Input
709  channelindex , & ! Input
710  ancillaryinput, & ! Input
711  predictor , & ! Input
712  atmoptics , & ! Output
713  aavar ) ! Internal variable output
714  CALL crtm_compute_atmabsorption_tl( sensorindex , & ! Input
715  channelindex , & ! Input
716  predictor , & ! Input
717  predictor_tl , & ! Input
718  atmoptics_tl , & ! Output
719  aavar ) ! Internal variable input
720 
721 
722  ! Compute the total atmospheric transmittance
723  ! for use in FASTEM-X reflection correction
724  CALL crtm_compute_transmittance(atmoptics,transmittance)
725  sfcoptics%Transmittance = transmittance
726  CALL crtm_compute_transmittance_tl(atmoptics,atmoptics_tl,transmittance_tl)
727  sfcoptics_tl%Transmittance = transmittance_tl
728 
729 
730  ! Compute the molecular scattering properties
731  ! ...Solar radiation
732  IF( sc(sensorindex)%Solar_Irradiance(channelindex) > zero .AND. &
733  source_za < max_source_zenith_angle) THEN
734  rtv%Solar_Flag_true = .true.
735  END IF
736  ! ...Visible channel with solar radiation
737  IF( spccoeff_isvisiblesensor( sc(sensorindex) ) .AND. rtv%Solar_Flag_true ) THEN
738  rtv%Visible_Flag_true = .true.
739  ! Rayleigh phase function has 0, 1, 2 components.
740  IF( atmoptics%n_Legendre_Terms < 4 ) THEN
741  atmoptics%n_Legendre_Terms = 4
742  atmoptics_tl%n_Legendre_Terms = atmoptics%n_Legendre_Terms
743  rtsolution(ln,m)%Scattering_FLAG = .true.
744  rtsolution(ln,m)%n_Full_Streams = atmoptics%n_Legendre_Terms + 2
745  END IF
746  rtv%n_Azi = min( atmoptics%n_Legendre_Terms - 1, max_n_azimuth_fourier )
747  ! Get molecular scattering and extinction
748  wavenumber = sc(sensorindex)%Wavenumber(channelindex)
749  status_fwd = crtm_compute_moleculescatter( &
750  wavenumber, &
751  atm , &
752  atmoptics )
753  status_tl = crtm_compute_moleculescatter_tl( &
754  wavenumber , &
755  atm_tl , &
756  atmoptics_tl )
757  IF ( status_fwd /= success .OR. status_tl /= success) THEN
758  error_status = failure
759  WRITE( message,'("Error computing MoleculeScatter for ",a,&
760  &", channel ",i0,", profile #",i0)') &
761  trim(channelinfo(n)%Sensor_ID), &
762  channelinfo(n)%Sensor_Channel(l), &
763  m
764  CALL display_message( routine_name, message, error_status )
765  RETURN
766  END IF
767  ELSE
768  rtv%Visible_Flag_true = .false.
769  rtv%n_Azi = 0
770  END IF
771 
772 
773  ! Compute the cloud particle absorption/scattering properties
774  IF( atm%n_Clouds > 0 ) THEN
775  status_fwd = crtm_compute_cloudscatter( atm , & ! Input
776  sensorindex , & ! Input
777  channelindex, & ! Input
778  atmoptics , & ! Output
779  csvar ) ! Internal variable output
780  status_tl = crtm_compute_cloudscatter_tl( atm , & ! FWD Input
781  atmoptics , & ! FWD Input
782  atm_tl , & ! TL Input
783  sensorindex , & ! Input
784  channelindex, & ! Input
785  atmoptics_tl, & ! TL Output
786  csvar ) ! Internal variable input
787  IF ( status_fwd /= success .OR. status_tl /= success) THEN
788  error_status = failure
789  WRITE( message,'("Error computing CloudScatter for ",a,&
790  &", channel ",i0,", profile #",i0)' ) &
791  trim(channelinfo(n)%Sensor_ID), channelinfo(n)%Sensor_Channel(l), m
792  CALL display_message( routine_name, message, error_status )
793  RETURN
794  END IF
795  END IF
796 
797 
798  ! Compute the aerosol absorption/scattering properties
799  IF ( atm%n_Aerosols > 0 ) THEN
800  status_fwd = crtm_compute_aerosolscatter( atm , & ! Input
801  sensorindex , & ! Input
802  channelindex, & ! Input
803  atmoptics , & ! In/Output
804  asvar ) ! Internal variable output
805  status_tl = crtm_compute_aerosolscatter_tl( atm , & ! FWD Input
806  atmoptics , & ! FWD Input
807  atm_tl , & ! TL Input
808  sensorindex , & ! Input
809  channelindex, & ! Input
810  atmoptics_tl, & ! TL Output
811  asvar ) ! Internal variable input
812  IF ( status_fwd /= success .OR. status_tl /= success) THEN
813  error_status = failure
814  WRITE( message,'("Error computing AerosolScatter for ",a,&
815  &", channel ",i0,", profile #",i0)' ) &
816  trim(channelinfo(n)%Sensor_ID), channelinfo(n)%Sensor_Channel(l), m
817  CALL display_message( routine_name, message, error_status )
818  RETURN
819  END IF
820  END IF
821 
822 
823  ! Compute the combined atmospheric optical properties
824  IF( atmoptics%Include_Scattering ) THEN
825  CALL crtm_combine_atmoptics( atmoptics, aovar )
826  CALL crtm_combine_atmoptics_tl( atmoptics, atmoptics_tl, aovar )
827  END IF
828  ! ...Save vertically integrated scattering optical depth for output
829  rtsolution(ln,m)%SOD = atmoptics%Scattering_Optical_Depth
830 
831 
832  ! Turn off FASTEM-X reflection correction for scattering conditions
833  IF ( crtm_include_scattering(atmoptics) .AND. spccoeff_ismicrowavesensor( sc(sensorindex) ) ) THEN
834  sfcoptics%Transmittance = -one
835  ELSE
836  sfcoptics%Transmittance = transmittance
837  END IF
838 
839 
840  ! Fill the SfcOptics structure for the optional emissivity input case.
841  ! ...Indicate SfcOptics ARE to be computed
842  sfcoptics%Compute = .true.
843  ! ...Change SfcOptics emissivity/reflectivity contents/computation status
844  IF ( user_emissivity ) THEN
845  sfcoptics%Compute = .false.
846  sfcoptics%Emissivity(1,1) = options(m)%Emissivity(ln)
847  sfcoptics%Reflectivity(1,1,1,1) = one - options(m)%Emissivity(ln)
848  IF ( user_direct_reflectivity ) THEN
849  sfcoptics%Direct_Reflectivity(1,1) = options(m)%Direct_Reflectivity(ln)
850  ELSE
851  sfcoptics%Direct_Reflectivity(1,1) = sfcoptics%Reflectivity(1,1,1,1)
852  END IF
853  END IF
854 
855 
856  ! Fourier component loop for azimuth angles (VIS).
857  ! mth_Azi = 0 is for an azimuth-averaged value (IR, MW)
858  ! ...Initialise radiance
859  rtsolution(ln,m)%Radiance = zero
860  rtsolution_tl(ln,m)%Radiance = zero
861  ! ...Fourier expansion over azimuth angle
862  azimuth_fourier_loop: DO mth_azi = 0, rtv%n_Azi
863 
864  ! Set dependent component counters
865  rtv%mth_Azi = mth_azi
866  sfcoptics%mth_Azi = mth_azi
867 
868  ! Solve the radiative transfer problem
869  ! ...Forward model
870  error_status = crtm_compute_rtsolution( &
871  atm , & ! Input
872  surface(m) , & ! Input
873  atmoptics , & ! Input
874  sfcoptics , & ! Input
875  geometryinfo , & ! Input
876  sensorindex , & ! Input
877  channelindex , & ! Input
878  rtsolution(ln,m), & ! Output
879  rtv ) ! Internal variable output
880  IF ( error_status /= success ) THEN
881  WRITE( message,'( "Error computing RTSolution for ", a, &
882  &", channel ", i0,", profile #",i0)' ) &
883  trim(channelinfo(n)%Sensor_ID), channelinfo(n)%Sensor_Channel(l), m
884  CALL display_message( routine_name, message, error_status )
885  RETURN
886  END IF
887  ! ...Tangent-linear model
888  error_status = crtm_compute_rtsolution_tl( &
889  atm , & ! FWD Input
890  surface(m) , & ! FWD Input
891  atmoptics , & ! FWD Input
892  sfcoptics , & ! FWD Input
893  rtsolution(ln,m) , & ! FWD Input
894  atm_tl , & ! TL Input
895  surface_tl(m) , & ! TL Input
896  atmoptics_tl , & ! TL Input
897  sfcoptics_tl , & ! TL Input
898  geometryinfo , & ! Input
899  sensorindex , & ! Input
900  channelindex , & ! Input
901  rtsolution_tl(ln,m), & ! TL Output
902  rtv ) ! Internal variable input
903  IF ( error_status /= success ) THEN
904  WRITE( message,'( "Error computing RTSolution_TL for ", a, &
905  &", channel ", i0,", profile #",i0)' ) &
906  trim(channelinfo(n)%Sensor_ID), channelinfo(n)%Sensor_Channel(l), m
907  CALL display_message( routine_name, message, error_status )
908  RETURN
909  END IF
910  END DO azimuth_fourier_loop
911 
912  ! Compute non-LTE correction to radiance if required
913  IF ( apply_nlte_correction .AND. nlte_predictor_isactive(nlte_predictor) ) THEN
915  sc(sensorindex)%NC , & ! Input
916  channelindex , & ! Input
917  nlte_predictor , & ! Input
918  rtsolution(ln,m)%Radiance ) ! In/Output
920  sc(sensorindex)%NC , & ! Input
921  channelindex , & ! Input
922  nlte_predictor_tl , & ! Input
923  rtsolution_tl(ln,m)%Radiance ) ! In/Output
924  END IF
925 
926  ! Convert the radiance to brightness temperature
928  sensorindex , & ! Input
929  channelindex , & ! Input
930  rtsolution(ln,m)%Radiance , & ! Input
931  rtsolution(ln,m)%Brightness_Temperature ) ! Output
933  sensorindex , & ! Input
934  channelindex , & ! Input
935  rtsolution(ln,m)%Radiance , & ! Input
936  rtsolution_tl(ln,m)%Radiance , & ! Input
937  rtsolution_tl(ln,m)%Brightness_Temperature ) ! Output
938 
939  ! Compute Antenna correction to brightness temperature if required
940  IF ( compute_antcorr ) THEN
941  CALL crtm_compute_antcorr( &
942  geometryinfo , & ! Input
943  sensorindex , & ! Input
944  channelindex , & ! Input
945  rtsolution(ln,m) ) ! Output
947  geometryinfo , & ! Input
948  sensorindex , & ! Input
949  channelindex , & ! Input
950  rtsolution_tl(ln,m) ) ! Output
951  END IF
952  END DO channel_loop
953 
954 
955  ! Deallocate local sensor dependent data structures
956  ! ...RTV structure
957  IF ( rtv_associated(rtv) ) CALL rtv_destroy(rtv)
958  ! ...Predictor structures
959  CALL crtm_predictor_destroy( predictor )
960  CALL crtm_predictor_destroy( predictor_tl )
961 
962  END DO sensor_loop
963 
964 
965  ! Deallocate local sensor independent data structures
966  ! ...Atmospheric optics
967  CALL crtm_atmoptics_destroy( atmoptics )
968  CALL crtm_atmoptics_destroy( atmoptics_tl )
969 
970  END DO profile_loop
971 
972 
973  ! Destroy any remaining structures
974  CALL crtm_sfcoptics_destroy( sfcoptics )
975  CALL crtm_sfcoptics_destroy( sfcoptics_tl )
976  CALL crtm_atmosphere_destroy( atm_tl )
977  CALL crtm_atmosphere_destroy( atm )
978 
979  END FUNCTION crtm_tangent_linear
980 
981 
982 !--------------------------------------------------------------------------------
983 !:sdoc+:
984 !
985 ! NAME:
986 ! CRTM_Tangent_Linear_Version
987 !
988 ! PURPOSE:
989 ! Subroutine to return the module version information.
990 !
991 ! CALLING SEQUENCE:
992 ! CALL CRTM_Tangent_Linear_Version( Id )
993 !
994 ! OUTPUTS:
995 ! Id: Character string containing the version Id information
996 ! for the module.
997 ! UNITS: N/A
998 ! TYPE: CHARACTER(*)
999 ! DIMENSION: Scalar
1000 ! ATTRIBUTES: INTENT(OUT)
1001 !
1002 !:sdoc-:
1003 !--------------------------------------------------------------------------------
1004 
1005  SUBROUTINE crtm_tangent_linear_version( Id )
1006  CHARACTER(*), INTENT(OUT) :: id
1007  id = module_version_id
1008  END SUBROUTINE crtm_tangent_linear_version
1009 
1010 END MODULE crtm_tangent_linear_module
subroutine, public crtm_compute_transmittance(atmoptics, transmittance)
logical function, public crtm_aerosolcoeff_isloaded()
integer, parameter, public max_n_azimuth_fourier
logical function, public crtm_cloudcoeff_isloaded()
integer, parameter, public failure
integer, parameter, public set
subroutine, public crtm_compute_transmittance_tl(atmoptics, atmoptics_TL, transmittance_TL)
real(fp), parameter, public zero
integer, parameter, public warning
subroutine, public crtm_compute_antcorr_tl(gI, n, l, RT_TL)
integer, parameter, public max_n_phase_elements
subroutine, public crtm_combine_atmoptics(AtmOptics, AOvar)
logical function, public crtm_options_isvalid(self)
integer function, public crtm_atmosphere_addlayers_tl(Atm_In, Atm_In_TL, Atm_Out_TL)
integer function, public crtm_compute_aerosolscatter_tl(Atm, AScat, Atm_TL, SensorIndex, ChannelIndex, AScat_TL, ASV)
integer, parameter, public fp
Definition: Type_Kinds.f90:124
elemental subroutine, public crtm_atmosphere_destroy(Atm)
integer, parameter, public max_n_angles
real(fp), parameter, public scattering_albedo_threshold
integer function, public crtm_compute_rtsolution_tl(Atmosphere, Surface, AtmOptics, SfcOptics, RTSolution, Atmosphere_TL, Surface_TL, AtmOptics_TL, SfcOptics_TL, GeometryInfo, SensorIndex, ChannelIndex, RTSolution_TL, RTV)
subroutine, public compute_nlte_predictor_tl(NLTE_Predictor, Atm_TL, NLTE_Predictor_TL)
elemental subroutine, public crtm_geometryinfo_setvalue(gInfo, Geometry, iFOV, Longitude, Latitude, Surface_Altitude, Sensor_Scan_Angle, Sensor_Zenith_Angle, Sensor_Azimuth_Angle, Source_Zenith_Angle, Source_Azimuth_Angle, Flux_Zenith_Angle, Year, Month, Day, Distance_Ratio, Sensor_Scan_Radian, Sensor_Zenith_Radian, Sensor_Azimuth_Radian, Secant_Sensor_Zenith, Cosine_Sensor_Zenith, Source_Zenith_Radian, Source_Azimuth_Radian, Secant_Source_Zenith, Flux_Zenith_Radian, Secant_Flux_Zenith, Trans_Zenith_Radian, Secant_Trans_Zenith, AU_ratio2)
logical function, public crtm_atmosphere_isvalid(Atm)
elemental subroutine, public crtm_atmoptics_destroy(self)
integer function, public crtm_tangent_linear(Atmosphere, Surface, Atmosphere_TL, Surface_TL, Geometry, ChannelInfo, RTSolution, RTSolution_TL, Options)
elemental subroutine, public csvar_create(self, n_Legendre_Terms, n_Phase_Elements, n_Layers, n_Clouds)
elemental subroutine, public crtm_geometryinfo_compute(gInfo)
elemental subroutine, public crtm_predictor_create(self, n_Layers, SensorIndex, SaveFWV)
pure logical function, public crtm_include_scattering(atmoptics)
integer, parameter, public max_n_legendre_terms
elemental subroutine, public crtm_sfcoptics_create(SfcOptics, n_Angles, n_Stokes)
integer function, public crtm_compute_rtsolution(Atmosphere, Surface, AtmOptics, SfcOptics, GeometryInfo, SensorIndex, ChannelIndex, RTSolution, RTV)
elemental logical function, public crtm_atmoptics_associated(self)
real(fp), parameter, public max_source_zenith_angle
elemental subroutine, public rtv_create(RTV, n_Angles, n_Legendre_Terms, n_Layers)
Definition: RTV_Define.f90:408
elemental subroutine, public crtm_atmoptics_zero(self)
integer, parameter, public max_n_streams
subroutine, public crtm_compute_atmabsorption_tl(SensorIndex, ChannelIndex, Predictor, Predictor_TL, AtmOptics_TL, iVar)
integer, parameter, public max_n_stokes
integer function, public crtm_compute_aerosolscatter(Atm, SensorIndex, ChannelIndex, AScat, ASV)
integer function, public crtm_compute_cloudscatter(Atm, SensorIndex, ChannelIndex, CScat, CSV)
integer, parameter, public not_set
real(fp), parameter, public one
recursive subroutine, public display_message(Routine_Name, Message, Error_State, Message_Log)
integer function, public crtm_compute_moleculescatter(Wavenumber, Atmosphere, AtmOptics, Message_Log)
elemental logical function, public csvar_associated(self)
subroutine, public crtm_planck_temperature_tl(n, l, Radiance, Radiance_TL, Temperature_TL)
subroutine, public crtm_compute_surfacet(Surface, SfcOptics)
subroutine, public crtm_compute_antcorr(gI, n, l, RT)
elemental subroutine, public asvar_destroy(self)
elemental logical function, public crtm_sfcoptics_associated(SfcOptics)
elemental subroutine, public csvar_destroy(self)
integer function, public crtm_compute_nstreams(Atmosphere, SensorIndex, ChannelIndex, RTSolution)
elemental subroutine, public crtm_atmoptics_create(self, n_Layers, n_Legendre_Terms, n_Phase_Elements)
logical function, public crtm_surface_isvalid(Sfc)
logical function, public crtm_geometry_isvalid(geo)
elemental subroutine, public crtm_predictor_destroy(self)
subroutine, public crtm_compute_surfacet_tl(Surface, Surface_TL, SfcOptics_TL)
subroutine, public crtm_compute_predictors(SensorIndex, Atmosphere, GeometryInfo, AncillaryInput, Predictor, iVar)
type(spccoeff_type), dimension(:), allocatable, save, public sc
elemental logical function, public asvar_associated(self)
integer, parameter, public max_n_layers
subroutine, public compute_nlte_correction(NLTECoeff, ChannelIndex, NLTE_Predictor, Radiance)
subroutine, public crtm_compute_atmabsorption(SensorIndex, ChannelIndex, AncillaryInput, Predictor, AtmOptics, iVar)
elemental subroutine, public crtm_sfcoptics_destroy(SfcOptics)
subroutine, public crtm_compute_predictors_tl(SensorIndex, Atmosphere, Predictor, Atmosphere_TL, AncillaryInput, Predictor_TL, iVar)
integer function, public crtm_atmosphere_addlayers(Atm_In, Atm_Out)
subroutine, public crtm_planck_temperature(n, l, Radiance, Temperature)
integer function, public crtm_compute_cloudscatter_tl(Atm, CScat, Atm_TL, SensorIndex, ChannelIndex, CScat_TL, CSV)
character(*), parameter module_version_id
elemental integer function, public crtm_channelinfo_n_channels(ChannelInfo)
subroutine, public compute_nlte_predictor(NLTECoeff, Atm, gInfo, NLTE_Predictor)
elemental logical function, public crtm_predictor_associated(self)
#define min(a, b)
Definition: mosaic_util.h:32
integer function, public crtm_compute_moleculescatter_tl(Wavenumber, Atmosphere_TL, AtmOptics_TL, Message_Log)
elemental logical function, public rtv_associated(RTV)
Definition: RTV_Define.f90:314
subroutine, public compute_nlte_correction_tl(NLTECoeff, ChannelIndex, NLTE_Predictor_TL, Radiance_TL)
elemental subroutine, public asvar_create(self, n_Legendre_Terms, n_Phase_Elements, n_Layers, n_Aerosols)
subroutine, public crtm_tangent_linear_version(Id)
integer, parameter, public success
elemental subroutine, public crtm_geometryinfo_getvalue(gInfo, Geometry, iFOV, Longitude, Latitude, Surface_Altitude, Sensor_Scan_Angle, Sensor_Zenith_Angle, Sensor_Azimuth_Angle, Source_Zenith_Angle, Source_Azimuth_Angle, Flux_Zenith_Angle, Year, Month, Day, Distance_Ratio, Sensor_Scan_Radian, Sensor_Zenith_Radian, Sensor_Azimuth_Radian, Secant_Sensor_Zenith, Cosine_Sensor_Zenith, Source_Zenith_Radian, Source_Azimuth_Radian, Secant_Source_Zenith, Flux_Zenith_Radian, Secant_Flux_Zenith, Trans_Zenith_Radian, Secant_Trans_Zenith, AU_ratio2)
elemental logical function, public accoeff_associated(ACCoeff)
elemental subroutine, public rtv_destroy(RTV)
Definition: RTV_Define.f90:348
integer function, public crtm_get_pressurelevelidx(Atm, Level_Pressure)
elemental logical function, public nltecoeff_associated(NLTECoeff)
subroutine, public crtm_combine_atmoptics_tl(AtmOptics, AtmOptics_TL, AOvar)