FV3 Bundle
CRTM_Forward_Module.f90
Go to the documentation of this file.
1 !
2 ! CRTM_Forward_Module
3 !
4 ! Module containing the CRTM forward model function.
5 !
6 !
7 ! CREATION HISTORY:
8 ! Written by: Paul van Delst, 29-Jun-2004
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, &
31  USE crtm_spccoeff, ONLY: sc, &
32  spccoeff_isvisiblesensor, &
33  spccoeff_ismicrowavesensor
55  USE crtm_predictor, ONLY: crtm_pvar_type => ivar_type, &
57  USE crtm_atmabsorption, ONLY: crtm_aavar_type => ivar_type, &
66  USE crtm_atmoptics, ONLY: aovar_type , &
67  aovar_create, &
76  USE crtm_rtsolution, ONLY: crtm_rtsolution_type , &
84  USE crtm_nltecorrection, ONLY: nlte_predictor_type , &
85  nlte_predictor_isactive, &
91 
92  ! Internal variable definition modules
93  ! ...CloudScatter
94  USE csvar_define, ONLY: csvar_type, &
96  csvar_destroy , &
98  ! ...AerosolScatter
99  USE asvar_define, ONLY: asvar_type, &
101  asvar_destroy , &
103  ! ...Radiative transfer
104  USE rtv_define, ONLY: rtv_type , &
105  rtv_associated, &
106  rtv_destroy , &
107  rtv_create
108 
109 
110  ! -----------------------
111  ! Disable implicit typing
112  ! -----------------------
113  IMPLICIT NONE
114 
115 
116  ! ------------
117  ! Visibilities
118  ! ------------
119  ! Everything private by default
120  PRIVATE
121  ! Public procedures
122  PUBLIC :: crtm_forward
123  PUBLIC :: crtm_forward_version
124 
125 
126  ! -----------------
127  ! Module parameters
128  ! -----------------
129  ! Version Id for the module
130  CHARACTER(*), PARAMETER :: module_version_id = &
131  '$Id: CRTM_Forward_Module.f90 60152 2015-08-13 19:19:13Z paul.vandelst@noaa.gov $'
132 
133 
134 CONTAINS
135 
136 
137 !--------------------------------------------------------------------------------
138 !:sdoc+:
139 !
140 ! NAME:
141 ! CRTM_Forward
142 !
143 ! PURPOSE:
144 ! Function that calculates top-of-atmosphere (TOA) radiances
145 ! and brightness temperatures for an input atmospheric profile or
146 ! profile set and user specified satellites/channels.
147 !
148 ! CALLING SEQUENCE:
149 ! Error_Status = CRTM_Forward( Atmosphere , &
150 ! Surface , &
151 ! Geometry , &
152 ! ChannelInfo , &
153 ! RTSolution , &
154 ! Options = Options )
155 !
156 ! INPUTS:
157 ! Atmosphere: Structure containing the Atmosphere data.
158 ! UNITS: N/A
159 ! TYPE: CRTM_Atmosphere_type
160 ! DIMENSION: Rank-1 (n_Profiles)
161 ! ATTRIBUTES: INTENT(IN)
162 !
163 ! Surface: Structure containing the Surface data.
164 ! UNITS: N/A
165 ! TYPE: CRTM_Surface_type
166 ! DIMENSION: Same as input Atmosphere structure
167 ! ATTRIBUTES: INTENT(IN)
168 !
169 ! Geometry: Structure containing the view geometry
170 ! information.
171 ! UNITS: N/A
172 ! TYPE: CRTM_Geometry_type
173 ! DIMENSION: Same as input Atmosphere structure
174 ! ATTRIBUTES: INTENT(IN)
175 !
176 ! ChannelInfo: Structure returned from the CRTM_Init() function
177 ! that contains the satellite/sensor channel index
178 ! information.
179 ! UNITS: N/A
180 ! TYPE: CRTM_ChannelInfo_type
181 ! DIMENSION: Rank-1 (n_Sensors)
182 ! ATTRIBUTES: INTENT(IN)
183 !
184 ! OUTPUTS:
185 ! RTSolution: Structure containing the soluition to the RT equation
186 ! for the given inputs.
187 ! UNITS: N/A
188 ! TYPE: CRTM_RTSolution_type
189 ! DIMENSION: Rank-2 (n_Channels x n_Profiles)
190 ! ATTRIBUTES: INTENT(IN OUT)
191 !
192 ! OPTIONAL INPUTS:
193 ! Options: Options structure containing the optional arguments
194 ! for the CRTM.
195 ! UNITS: N/A
196 ! TYPE: CRTM_Options_type
197 ! DIMENSION: Same as input Atmosphere structure
198 ! ATTRIBUTES: INTENT(IN), OPTIONAL
199 !
200 ! FUNCTION RESULT:
201 ! Error_Status: The return value is an integer defining the error status.
202 ! The error codes are defined in the Message_Handler module.
203 ! If == SUCCESS the computation was sucessful
204 ! == FAILURE an unrecoverable error occurred
205 ! UNITS: N/A
206 ! TYPE: INTEGER
207 ! DIMENSION: Scalar
208 !
209 ! COMMENTS:
210 ! - The Options optional input structure argument contains
211 ! spectral information (e.g. emissivity) that must have the same
212 ! spectral dimensionality (the "L" dimension) as the output
213 ! RTSolution structure.
214 !
215 !:sdoc-:
216 !--------------------------------------------------------------------------------
217 
218  FUNCTION crtm_forward( &
219  Atmosphere , & ! Input, M
220  Surface , & ! Input, M
221  Geometry , & ! Input, M
222  ChannelInfo, & ! Input, n_Sensors
223  RTSolution , & ! Output, L x M
224  Options ) & ! Optional input, M
225  result( error_status )
226  ! Arguments
227  TYPE(crtm_atmosphere_type), INTENT(IN) :: atmosphere(:) ! M
228  TYPE(crtm_surface_type), INTENT(IN) :: surface(:) ! M
229  TYPE(crtm_geometry_type), INTENT(IN) :: geometry(:) ! M
230  TYPE(crtm_channelinfo_type), INTENT(IN) :: channelinfo(:) ! n_Sensors
231  TYPE(crtm_rtsolution_type), INTENT(IN OUT) :: rtsolution(:,:) ! L x M
232  TYPE(crtm_options_type), OPTIONAL, INTENT(IN) :: options(:) ! M
233  ! Function result
234  INTEGER :: error_status
235  ! Local parameters
236  CHARACTER(*), PARAMETER :: routine_name = 'CRTM_Forward'
237  ! Local variables
238  CHARACTER(256) :: message
239  LOGICAL :: options_present
240  LOGICAL :: check_input
241  LOGICAL :: user_emissivity, user_direct_reflectivity, user_n_streams
242  LOGICAL :: user_antcorr, compute_antcorr
243  LOGICAL :: apply_nlte_correction
244  LOGICAL :: atmosphere_invalid, surface_invalid, geometry_invalid, options_invalid
245  INTEGER :: rt_algorithm_id
246  INTEGER :: ifov
247  INTEGER :: n, n_sensors, sensorindex
248  INTEGER :: l, n_channels, channelindex
249  INTEGER :: m, n_profiles
250  INTEGER :: ln
251  INTEGER :: n_full_streams, mth_azi
252  REAL(fp) :: source_za
253  REAL(fp) :: wavenumber
254  REAL(fp) :: aircraft_pressure
255  REAL(fp) :: transmittance
256  ! Local ancillary input structure
257  TYPE(crtm_ancillaryinput_type) :: ancillaryinput
258  ! Local options structure for default values
259  TYPE(crtm_options_type) :: default_options
260  ! Local atmosphere structure for extra layering
261  TYPE(crtm_atmosphere_type) :: atm
262  ! Component variables
263  TYPE(crtm_geometryinfo_type) :: geometryinfo
264  TYPE(crtm_predictor_type) :: predictor
265  TYPE(crtm_atmoptics_type) :: atmoptics
266  TYPE(crtm_sfcoptics_type) :: sfcoptics
267  ! Component variable internals
268  TYPE(crtm_pvar_type) :: pvar ! Predictor
269  TYPE(crtm_aavar_type) :: aavar ! AtmAbsorption
270  TYPE(csvar_type) :: csvar ! CloudScatter
271  TYPE(asvar_type) :: asvar ! AerosolScatter
272  TYPE(aovar_type) :: aovar ! AtmOptics
273  TYPE(rtv_type) :: rtv ! RTSolution
274  ! NLTE correction term predictor
275  TYPE(nlte_predictor_type) :: nlte_predictor
276 
277 
278  ! ------
279  ! SET UP
280  ! ------
281  error_status = success
282 
283 
284  ! If no sensors or channels, simply return
285  n_sensors = SIZE(channelinfo)
286  n_channels = sum(crtm_channelinfo_n_channels(channelinfo))
287  IF ( n_sensors == 0 .OR. n_channels == 0 ) RETURN
288 
289 
290  ! Check output array
291  IF ( SIZE(rtsolution,dim=1) < n_channels ) THEN
292  error_status = failure
293  WRITE( message,'("Output RTSolution structure array too small (",i0,&
294  &") to hold results for the number of requested channels (",i0,")")') &
295  SIZE(rtsolution,dim=1), n_channels
296  CALL display_message( routine_name, message, error_status )
297  RETURN
298  END IF
299 
300 
301  ! Check the number of profiles
302  ! ...Number of atmospheric profiles.
303  n_profiles = SIZE(atmosphere)
304  ! ...Check the profile dimensionality of the other mandatory arguments
305  IF ( SIZE(surface) /= n_profiles .OR. &
306  SIZE(geometry) /= n_profiles .OR. &
307  SIZE(rtsolution,dim=2) /= n_profiles ) THEN
308  error_status = failure
309  message = 'Inconsistent profile dimensionality for input arguments.'
310  CALL display_message( routine_name, message, error_status )
311  RETURN
312  END IF
313  ! ...Check the profile dimensionality of the other optional arguments
314  options_present = .false.
315  IF ( PRESENT(options) ) THEN
316  options_present = .true.
317  IF ( SIZE(options) /= n_profiles ) THEN
318  error_status = failure
319  message = 'Inconsistent profile dimensionality for Options optional input argument.'
320  CALL display_message( routine_name, message, error_status )
321  RETURN
322  END IF
323  END IF
324 
325 
326  ! Allocate the profile independent surface opticss local structure
328  IF ( .NOT. crtm_sfcoptics_associated(sfcoptics) ) THEN
329  error_status = failure
330  message = 'Error allocating SfcOptics data structures'
331  CALL display_message( routine_name, message, error_status )
332  RETURN
333  END IF
334 
335 
336  ! ------------
337  ! PROFILE LOOP
338  ! ------------
339  profile_loop: DO m = 1, n_profiles
340 
341 
342  ! Check the cloud and aerosol coeff. data for cases with clouds and aerosol
343  IF( atmosphere(m)%n_Clouds > 0 .AND. .NOT. crtm_cloudcoeff_isloaded() )THEN
344  error_status = failure
345  WRITE( message,'("The CloudCoeff data must be loaded (with CRTM_Init routine) ", &
346  &"for the cloudy case profile #",i0)' ) m
347  CALL display_message( routine_name, message, error_status )
348  RETURN
349  END IF
350  IF( atmosphere(m)%n_Aerosols > 0 .AND. .NOT. crtm_aerosolcoeff_isloaded() )THEN
351  error_status = failure
352  WRITE( message,'("The AerosolCoeff data must be loaded (with CRTM_Init routine) ", &
353  &"for the aerosol case profile #",i0)' ) m
354  CALL display_message( routine_name, message, error_status )
355  RETURN
356  END IF
357 
358 
359  ! Check the optional Options structure argument
360  ! ...Specify default actions
361  check_input = default_options%Check_Input
362  user_emissivity = default_options%Use_Emissivity
363  user_antcorr = default_options%Use_Antenna_Correction
364  apply_nlte_correction = default_options%Apply_NLTE_Correction
365  rt_algorithm_id = default_options%RT_Algorithm_Id
366  user_n_streams = default_options%Use_N_Streams
367  aircraft_pressure = default_options%Aircraft_Pressure
368  ! ...Check the Options argument
369  IF (options_present) THEN
370  ! Override input checker with option
371  check_input = options(m)%Check_Input
372  ! Check if the supplied emissivity should be used
373  user_emissivity = options(m)%Use_Emissivity
374  IF ( options(m)%Use_Emissivity ) THEN
375  ! Are the channel dimensions consistent
376  IF ( options(m)%n_Channels < n_channels ) THEN
377  error_status = failure
378  WRITE( message,'( "Input Options channel dimension (", i0, ") is less ", &
379  &"than the number of requested channels (",i0, ")" )' ) &
380  options(m)%n_Channels, n_channels
381  CALL display_message( routine_name, message, error_status )
382  RETURN
383  END IF
384  ! Check if the supplied direct reflectivity should be used
385  user_direct_reflectivity = options(m)%Use_Direct_Reflectivity
386  END IF
387  ! Check if antenna correction should be attempted
388  user_antcorr = options(m)%Use_Antenna_Correction
389  ! Set NLTE correction option
390  apply_nlte_correction = options(m)%Apply_NLTE_Correction
391  ! Set aircraft pressure altitude
392  aircraft_pressure = options(m)%Aircraft_Pressure
393 
394  ! Copy over ancillary input
395  ancillaryinput%SSU = options(m)%SSU
396  ancillaryinput%Zeeman = options(m)%Zeeman
397  ! Copy over surface optics input
398  sfcoptics%Use_New_MWSSEM = .NOT. options(m)%Use_Old_MWSSEM
399  ! Specify the RT algorithm
400  rt_algorithm_id = options(m)%RT_Algorithm_Id
401  ! Check if n_Streams should be used
402  user_n_streams = options(m)%Use_N_Streams
403  ! Check value for nstreams
404  IF ( user_n_streams ) THEN
405  IF ( options(m)%n_Streams <= 0 .OR. mod(options(m)%n_Streams,2) /= 0 .OR. &
406  options(m)%n_Streams > max_n_streams ) THEN
407  error_status = failure
408  WRITE( message,'( "Input Options n_Streams (", i0, ") is invalid" )' ) &
409  options(m)%n_Streams
410  CALL display_message( routine_name, message, error_status )
411  RETURN
412  END IF
413  END IF
414  END IF
415 
416 
417  ! Check the input data if required
418  IF ( check_input ) THEN
419  ! ...Mandatory inputs
420  atmosphere_invalid = .NOT. crtm_atmosphere_isvalid( atmosphere(m) )
421  surface_invalid = .NOT. crtm_surface_isvalid( surface(m) )
422  geometry_invalid = .NOT. crtm_geometry_isvalid( geometry(m) )
423  IF ( atmosphere_invalid .OR. surface_invalid .OR. geometry_invalid ) THEN
424  error_status = failure
425  WRITE( message,'("Input data check failed for profile #",i0)' ) m
426  CALL display_message( routine_name, message, error_status )
427  RETURN
428  END IF
429  ! ...Optional input
430  IF ( options_present ) THEN
431  options_invalid = .NOT. crtm_options_isvalid( options(m) )
432  IF ( options_invalid ) THEN
433  error_status = failure
434  WRITE( message,'("Options data check failed for profile #",i0)' ) m
435  CALL display_message( routine_name, message, error_status )
436  RETURN
437  END IF
438  END IF
439  END IF
440 
441 
442  ! Process geometry
443  ! ...Compute derived geometry
444  CALL crtm_geometryinfo_setvalue( geometryinfo, geometry=geometry(m) )
445  CALL crtm_geometryinfo_compute( geometryinfo )
446  ! ...Retrieve components into local variable
448  geometryinfo, &
449  ifov = ifov, &
450  source_zenith_angle = source_za )
451 
452 
453  ! Average surface skin temperature for multi-surface types
454  CALL crtm_compute_surfacet( surface(m), sfcoptics )
455 
456 
457  ! Add extra layers to current atmosphere profile
458  ! if necessary to handle upper atmosphere
459  error_status = crtm_atmosphere_addlayers( atmosphere(m), atm )
460  IF ( error_status /= success ) THEN
461  error_status = failure
462  WRITE( message,'("Error adding extra layers to profile #",i0)' ) m
463  CALL display_message( routine_name, message, error_status )
464  RETURN
465  END IF
466  IF ( atm%n_Layers > max_n_layers ) THEN
467  error_status = failure
468  WRITE( message,'("Added layers [",i0,"] cause total [",i0,"] to exceed the ",&
469  &"maximum allowed [",i0,"] for profile #",i0)' ) &
470  atm%n_Added_Layers, atm%n_Layers, max_n_layers, m
471  CALL display_message( routine_name, message, error_status )
472  RETURN
473  END IF
474  ! ...Allocate the atmospheric optics structures based on Atm extension
475  CALL crtm_atmoptics_create( atmoptics, &
476  atm%n_Layers , &
479  IF (options_present) THEN
480  ! Set Scattering Switch
481  atmoptics%Include_Scattering = options(m)%Include_Scattering
482  END IF
483  IF ( .NOT. crtm_atmoptics_associated( atmoptics ) ) THEN
484  error_status = failure
485  WRITE( message,'("Error allocating AtmOptics data structure for profile #",i0)' ) m
486  CALL display_message( routine_name, message, error_status )
487  RETURN
488  END IF
489  ! ...Allocate the atmospheric optics internal structure
490  CALL aovar_create( aovar, atm%n_Layers )
491 
492 
493  ! Process aircraft pressure altitude
494  IF ( aircraft_pressure > zero ) THEN
495  rtv%aircraft%rt = .true.
496  rtv%aircraft%idx = crtm_get_pressurelevelidx(atm, aircraft_pressure)
497  ! ...Issue warning if profile level is TOO different from flight level
498  IF ( abs(atm%Level_Pressure(rtv%aircraft%idx)-aircraft_pressure) > aircraft_pressure_threshold ) THEN
499  WRITE( message,'("Difference between aircraft pressure level (",es13.6,&
500  &"hPa) and closest input profile level (",es13.6,&
501  &"hPa) is larger than recommended (",f4.1,"hPa) for profile #",i0)') &
502  aircraft_pressure, atm%Level_Pressure(rtv%aircraft%idx), &
504  CALL display_message( routine_name, message, warning )
505  END IF
506  ELSE
507  rtv%aircraft%rt = .false.
508  END IF
509 
510 
511  ! Allocate the scattering internal variables if necessary
512  ! ...Cloud
513  IF ( atm%n_Clouds > 0 ) THEN
514  CALL csvar_create( csvar, &
517  atm%n_Layers , &
518  atm%n_Clouds )
519  END IF
520  ! ...Aerosol
521  IF ( atm%n_Aerosols > 0 ) THEN
522  CALL asvar_create( asvar, &
525  atm%n_Layers , &
526  atm%n_Aerosols )
527  END IF
528 
529 
530  ! -----------
531  ! SENSOR LOOP
532  ! -----------
533  ! Initialise channel counter for channel(l)/sensor(n) count
534  ln = 0
535 
536  sensor_loop: DO n = 1, n_sensors
537 
538 
539  ! Shorter name
540  sensorindex = channelinfo(n)%Sensor_Index
541 
542 
543  ! Check if antenna correction to be applied for current sensor
544  IF ( user_antcorr .AND. &
545  accoeff_associated( sc(sensorindex)%AC ) .AND. &
546  ifov /= 0 ) THEN
547  compute_antcorr = .true.
548  ELSE
549  compute_antcorr = .false.
550  END IF
551 
552 
553  ! Compute predictors for AtmAbsorption calcs
554  ! ...Allocate the predictor structure
555  CALL crtm_predictor_create( &
556  predictor , &
557  atm%n_Layers, &
558  sensorindex )
559  IF ( .NOT. crtm_predictor_associated(predictor) ) THEN
560  error_status=failure
561  WRITE( message,'("Error allocating predictor structure for profile #",i0, &
562  &" and ",a," sensor.")' ) m, sc(sensorindex)%Sensor_Id
563  CALL display_message( routine_name, message, error_status )
564  RETURN
565  END IF
566  ! ...And now fill them
567  CALL crtm_compute_predictors( sensorindex , & ! Input
568  atm , & ! Input
569  geometryinfo , & ! Input
570  ancillaryinput, & ! Input
571  predictor , & ! Output
572  pvar ) ! Internal variable output
573 
574 
575  ! Allocate the RTV structure if necessary
576  IF( (atm%n_Clouds > 0 .OR. &
577  atm%n_Aerosols > 0 .OR. &
578  spccoeff_isvisiblesensor( sc(sensorindex) ) ) .and. atmoptics%Include_Scattering ) THEN
579  CALL rtv_create( rtv, max_n_angles, max_n_legendre_terms, atm%n_Layers )
580  IF ( .NOT. rtv_associated(rtv) ) THEN
581  error_status=failure
582  WRITE( message,'("Error allocating RTV structure for profile #",i0, &
583  &" and ",a," sensor.")' ) m, trim(sc(sensorindex)%Sensor_Id)
584  CALL display_message( routine_name, message, error_status )
585  RETURN
586  END IF
587  ! Assign algorithm selector
588  rtv%RT_Algorithm_Id = rt_algorithm_id
589  END IF
590 
591 
592  ! Compute NLTE correction predictors
593  IF ( apply_nlte_correction ) THEN
594  CALL compute_nlte_predictor( &
595  sc(sensorindex)%NC, & ! Input
596  atm , & ! Input
597  geometryinfo , & ! Input
598  nlte_predictor ) ! Output
599  END IF
600 
601 
602  ! ------------
603  ! CHANNEL LOOP
604  ! ------------
605  channel_loop: DO l = 1, channelinfo(n)%n_Channels
606 
607  ! Channel setup
608  ! ...Skip channel if requested
609  IF ( .NOT. channelinfo(n)%Process_Channel(l) ) cycle channel_loop
610  ! ...Shorter name
611  channelindex = channelinfo(n)%Channel_Index(l)
612  ! ...Increment the processed channel counter
613  ln = ln + 1
614  ! ...Assign sensor+channel information to output
615  rtsolution(ln,m)%Sensor_Id = channelinfo(n)%Sensor_Id
616  rtsolution(ln,m)%WMO_Satellite_Id = channelinfo(n)%WMO_Satellite_Id
617  rtsolution(ln,m)%WMO_Sensor_Id = channelinfo(n)%WMO_Sensor_Id
618  rtsolution(ln,m)%Sensor_Channel = channelinfo(n)%Sensor_Channel(l)
619 
620 
621  ! Initialisations
622  CALL crtm_atmoptics_zero( atmoptics )
623 
624  ! Determine the number of streams (n_Full_Streams) in up+downward directions
625  IF ( user_n_streams ) THEN
626  n_full_streams = options(m)%n_Streams
627  rtsolution(ln,m)%n_Full_Streams = n_full_streams + 2
628  rtsolution(ln,m)%Scattering_Flag = .true.
629  ELSE
630  n_full_streams = crtm_compute_nstreams( atm , & ! Input
631  sensorindex , & ! Input
632  channelindex , & ! Input
633  rtsolution(ln,m) ) ! Output
634  END IF
635  ! ...Transfer stream count to scattering structure
636  atmoptics%n_Legendre_Terms = n_full_streams
637 
638 
639  ! Compute the gas absorption
640  CALL crtm_compute_atmabsorption( sensorindex , & ! Input
641  channelindex , & ! Input
642  ancillaryinput, & ! Input
643  predictor , & ! Input
644  atmoptics , & ! Output
645  aavar ) ! Internal variable output
646 
647 
648  ! Compute the clear-sky atmospheric transmittance
649  ! for use in FASTEM-X reflection correction
650  CALL crtm_compute_transmittance(atmoptics,transmittance)
651 
652 
653  ! Compute the molecular scattering properties
654  ! ...Solar radiation
655  IF( sc(sensorindex)%Solar_Irradiance(channelindex) > zero .AND. &
656  source_za < max_source_zenith_angle ) THEN
657  rtv%Solar_Flag_true = .true.
658  END IF
659  ! ...Visible channel with solar radiation
660  IF( spccoeff_isvisiblesensor( sc(sensorindex) ) .AND. rtv%Solar_Flag_true ) THEN
661  rtv%Visible_Flag_true = .true.
662  ! Rayleigh phase function has 0, 1, 2 components.
663  IF( atmoptics%n_Legendre_Terms < 4 ) THEN
664  atmoptics%n_Legendre_Terms = 4
665  rtsolution(ln,m)%Scattering_FLAG = .true.
666  rtsolution(ln,m)%n_Full_Streams = atmoptics%n_Legendre_Terms + 2
667  END IF
668  rtv%n_Azi = min( atmoptics%n_Legendre_Terms - 1, max_n_azimuth_fourier )
669  ! Get molecular scattering and extinction
670  wavenumber = sc(sensorindex)%Wavenumber(channelindex)
671  error_status = crtm_compute_moleculescatter( &
672  wavenumber, &
673  atm , &
674  atmoptics )
675  IF ( error_status /= success ) THEN
676  WRITE( message,'("Error computing MoleculeScatter for ",a,&
677  &", channel ",i0,", profile #",i0)') &
678  trim(channelinfo(n)%Sensor_ID), &
679  channelinfo(n)%Sensor_Channel(l), &
680  m
681  CALL display_message( routine_name, message, error_status )
682  RETURN
683  END IF
684  ELSE
685  rtv%Visible_Flag_true = .false.
686  rtv%n_Azi = 0
687  END IF
688 
689 
690  ! Compute the cloud particle absorption/scattering properties
691  IF( atm%n_Clouds > 0 ) THEN
692  error_status = crtm_compute_cloudscatter( atm , & ! Input
693  sensorindex , & ! Input
694  channelindex, & ! Input
695  atmoptics , & ! Output
696  csvar ) ! Internal variable output
697  IF ( error_status /= success ) THEN
698  WRITE( message,'("Error computing CloudScatter for ",a,&
699  &", channel ",i0,", profile #",i0)' ) &
700  trim(channelinfo(n)%Sensor_ID), channelinfo(n)%Sensor_Channel(l), m
701  CALL display_message( routine_name, message, error_status )
702  RETURN
703  END IF
704  END IF
705 
706 
707  ! Compute the aerosol absorption/scattering properties
708  IF ( atm%n_Aerosols > 0 ) THEN
709  error_status = crtm_compute_aerosolscatter( atm , & ! Input
710  sensorindex , & ! Input
711  channelindex, & ! Input
712  atmoptics , & ! In/Output
713  asvar ) ! Internal variable output
714  IF ( error_status /= success ) THEN
715  WRITE( message,'("Error computing AerosolScatter for ",a,&
716  &", channel ",i0,", profile #",i0)' ) &
717  trim(channelinfo(n)%Sensor_ID), channelinfo(n)%Sensor_Channel(l), m
718  CALL display_message( routine_name, message, error_status )
719  RETURN
720  END IF
721  END IF
722 
723 
724  ! Compute the combined atmospheric optical properties
725  IF( atmoptics%Include_Scattering ) THEN
726  CALL crtm_combine_atmoptics( atmoptics, aovar )
727  END IF
728  ! ...Save vertically integrated scattering optical depth fro output
729  rtsolution(ln,m)%SOD = atmoptics%Scattering_Optical_Depth
730 
731 
732  ! Turn off FASTEM-X reflection correction for scattering conditions
733  IF ( crtm_include_scattering(atmoptics) .AND. spccoeff_ismicrowavesensor( sc(sensorindex) ) ) THEN
734  sfcoptics%Transmittance = -one
735  ELSE
736  sfcoptics%Transmittance = transmittance
737  END IF
738 
739 
740 
741  ! Fill the SfcOptics structure for the optional emissivity input case.
742  ! ...Indicate SfcOptics ARE to be computed
743  sfcoptics%Compute = .true.
744  ! ...Change SfcOptics emissivity/reflectivity contents/computation status
745  IF ( user_emissivity ) THEN
746  sfcoptics%Compute = .false.
747  sfcoptics%Emissivity(1,1) = options(m)%Emissivity(ln)
748  sfcoptics%Reflectivity(1,1,1,1) = one - options(m)%Emissivity(ln)
749  IF ( user_direct_reflectivity ) THEN
750  sfcoptics%Direct_Reflectivity(1,1) = options(m)%Direct_Reflectivity(ln)
751  ELSE
752  sfcoptics%Direct_Reflectivity(1,1) = sfcoptics%Reflectivity(1,1,1,1)
753  END IF
754  END IF
755 
756 
757  ! Fourier component loop for azimuth angles (VIS).
758  ! mth_Azi = 0 is for an azimuth-averaged value (IR, MW)
759  ! ...Initialise radiance
760  rtsolution(ln,m)%Radiance = zero
761  ! ...Fourier expansion over azimuth angle
762  azimuth_fourier_loop: DO mth_azi = 0, rtv%n_Azi
763 
764  ! Set dependent component counters
765  rtv%mth_Azi = mth_azi
766  sfcoptics%mth_Azi = mth_azi
767 
768  ! Solve the radiative transfer problem
769  error_status = crtm_compute_rtsolution( &
770  atm , & ! Input
771  surface(m) , & ! Input
772  atmoptics , & ! Input
773  sfcoptics , & ! Input
774  geometryinfo , & ! Input
775  sensorindex , & ! Input
776  channelindex , & ! Input
777  rtsolution(ln,m), & ! Output
778  rtv ) ! Internal variable output
779  IF ( error_status /= success ) THEN
780  WRITE( message,'( "Error computing RTSolution for ", a, &
781  &", channel ", i0,", profile #",i0)' ) &
782  trim(channelinfo(n)%Sensor_ID), channelinfo(n)%Sensor_Channel(l), m
783  CALL display_message( routine_name, message, error_status )
784  RETURN
785  END IF
786  END DO azimuth_fourier_loop
787 
788  ! Compute non-LTE correction to radiance if required
789  IF ( apply_nlte_correction .AND. nlte_predictor_isactive(nlte_predictor) ) THEN
791  sc(sensorindex)%NC , & ! Input
792  channelindex , & ! Input
793  nlte_predictor , & ! Input
794  rtsolution(ln,m)%Radiance ) ! In/Output
795  END IF
796 
797  ! Convert the radiance to brightness temperature
799  sensorindex , & ! Input
800  channelindex , & ! Input
801  rtsolution(ln,m)%Radiance , & ! Input
802  rtsolution(ln,m)%Brightness_Temperature ) ! Output
803 
804  ! Compute Antenna correction to brightness temperature if required
805  IF ( compute_antcorr ) THEN
806  CALL crtm_compute_antcorr( &
807  geometryinfo , & ! Input
808  sensorindex , & ! Input
809  channelindex , & ! Input
810  rtsolution(ln,m) ) ! Output
811  END IF
812  END DO channel_loop
813 
814 
815  ! Deallocate local sensor dependent data structures
816  ! ...RTV structure
817  IF ( rtv_associated(rtv) ) CALL rtv_destroy(rtv)
818  ! ...Predictor structure
819  CALL crtm_predictor_destroy( predictor )
820 
821  END DO sensor_loop
822 
823 
824  ! Deallocate local sensor independent data structures
825  ! ...Atmospheric optics
826  CALL crtm_atmoptics_destroy( atmoptics )
827 
828  END DO profile_loop
829 
830 
831  ! Destroy any remaining structures
832  CALL crtm_sfcoptics_destroy( sfcoptics )
833  CALL crtm_atmosphere_destroy( atm )
834 
835  END FUNCTION crtm_forward
836 
837 
838 !--------------------------------------------------------------------------------
839 !:sdoc+:
840 !
841 ! NAME:
842 ! CRTM_Forward_Version
843 !
844 ! PURPOSE:
845 ! Subroutine to return the module version information.
846 !
847 ! CALLING SEQUENCE:
848 ! CALL CRTM_Forward_Version( Id )
849 !
850 ! OUTPUTS:
851 ! Id: Character string containing the version Id information
852 ! for the module.
853 ! UNITS: N/A
854 ! TYPE: CHARACTER(*)
855 ! DIMENSION: Scalar
856 ! ATTRIBUTES: INTENT(OUT)
857 !
858 !:sdoc-:
859 !--------------------------------------------------------------------------------
860 
861  SUBROUTINE crtm_forward_version( Id )
862  CHARACTER(*), INTENT(OUT) :: id
863  id = module_version_id
864  END SUBROUTINE crtm_forward_version
865 
866 END MODULE crtm_forward_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
real(fp), parameter, public zero
integer, parameter, public warning
integer, parameter, public max_n_phase_elements
subroutine, public crtm_combine_atmoptics(AtmOptics, AOvar)
logical function, public crtm_options_isvalid(self)
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
subroutine, public crtm_forward_version(Id)
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)
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
integer, parameter, public max_n_stokes
integer function, public crtm_compute_aerosolscatter(Atm, SensorIndex, ChannelIndex, AScat, ASV)
integer function, public crtm_forward(Atmosphere, Surface, Geometry, ChannelInfo, RTSolution, Options)
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_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_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)
integer function, public crtm_atmosphere_addlayers(Atm_In, Atm_Out)
subroutine, public crtm_planck_temperature(n, l, Radiance, Temperature)
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
elemental logical function, public rtv_associated(RTV)
Definition: RTV_Define.f90:314
elemental subroutine, public asvar_create(self, n_Legendre_Terms, n_Phase_Elements, n_Layers, n_Aerosols)
real(fp), parameter, public aircraft_pressure_threshold
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
character(*), parameter module_version_id
integer function, public crtm_get_pressurelevelidx(Atm, Level_Pressure)
elemental logical function, public nltecoeff_associated(NLTECoeff)