FV3 Bundle
ODPS_AtmAbsorption.f90
Go to the documentation of this file.
1 !
2 ! ODPS_AtmAbsorption
3 !
4 ! Module containing routines to compute the optical depth profile
5 ! due to gaseous absorption using the Optical Depth Pressure Space
6 ! (ODPS) algorithm
7 !
8 !
9 ! CREATION HISTORY:
10 ! Written by: Yong Han & Yong Chen, JCSDA, NOAA/NESDIS 20-Jun-2008
11 ! TL,AD: Tong Zhu, CIRA/CSU@NOAA/NESDIS 06-Jan-2009
12 !
13 
15 
16  ! -----------------
17  ! Environment setup
18  ! -----------------
19  ! Module use
20  USE type_kinds, ONLY: fp
26  USE odps_define, ONLY: odps_type , &
29  pafv_associated , &
36 
37  ! Disable implicit typing
38  IMPLICIT NONE
39 
40  ! ------------
41  ! Visibilities
42  ! ------------
43  ! Everything private by default
44  PRIVATE
45  ! Datatypes
46  PUBLIC :: ivar_type
47  ! Procedures
51 
52 
53  ! -----------------
54  ! Module parameters
55  ! -----------------
56  CHARACTER(*), PRIVATE, PARAMETER :: module_version_id = &
57  '$Id: $'
58  ! Maximum allowed layer optical depth
59  REAL(fp), PARAMETER :: max_od = 20.0_fp
60 
61 
62  ! ------------------------------------------
63  ! Structure definition to hold forward model
64  ! variables across FWD, TL, and AD calls
65  ! ------------------------------------------
66  TYPE :: ivar_type
67  PRIVATE
68  INTEGER :: dummy
69  END TYPE ivar_type
70 
71 
72 CONTAINS
73 
74 
75 !################################################################################
76 !################################################################################
77 !## ##
78 !## ## PUBLIC MODULE ROUTINES ## ##
79 !## ##
80 !################################################################################
81 !################################################################################
82 
83 !------------------------------------------------------------------------------
84 !:sdoc+:
85 !
86 ! NAME:
87 ! ODPS_Compute_AtmAbsorption
88 !
89 ! PURPOSE:
90 ! Subroutine to calculate the layer optical depths due to gaseous
91 ! absorption for a given sensor and channel and atmospheric profile.
92 !
93 ! CALLING SEQUENCE:
94 ! CALL ODPS_Compute_AtmAbsorption( &
95 ! TC , &
96 ! ChannelIndex , &
97 ! Predictor , &
98 ! AtmAbsorption )
99 !
100 ! INPUTS:
101 ! TC:
102 ! ODPS structure holding tau coefficients
103 ! UNITS: N/A
104 ! TYPE: ODPS_type
105 ! DIMENSION: Scalar
106 ! ATTRIBUTES: INTENT(IN)
107 !
108 ! ChannelIndex:
109 ! Channel index id. This is a unique index associated with a
110 ! supported sensor channel used to access the shared coefficient
111 ! data for a particular sensor's channel.
112 ! UNITS: N/A
113 ! TYPE: INTEGER
114 ! DIMENSION: Scalar
115 ! ATTRIBUTES: INTENT(IN)
116 !
117 ! Predictor:
118 ! Structure containing the predictor profile data.
119 ! UNITS: N/A
120 ! TYPE: ODPS_Predictor_type
121 ! DIMENSION: Scalar
122 ! ATTRIBUTES: INTENT(IN)
123 !
124 ! OUTPUTS:
125 ! AtmAbsorption:
126 ! Structure containing computed optical depth profile data.
127 ! UNITS: N/A
128 ! TYPE: CRTM_AtmOptics_type
129 ! DIMENSION: Scalar
130 ! ATTRIBUTES: INTENT(IN OUT)
131 !
132 !:sdoc-:
133 !------------------------------------------------------------------------------
134 
135  SUBROUTINE odps_compute_atmabsorption( &
136  TC , & ! Input
137  ChannelIndex , & ! Input
138  Predictor , & ! Input
139  AtmAbsorption ) ! Output
140  ! Arguments
141  TYPE(odps_type) , INTENT(IN) :: tc
142  INTEGER , INTENT(IN) :: channelindex
143  TYPE(odps_predictor_type), INTENT(IN OUT) :: predictor
144  TYPE(crtm_atmoptics_type), INTENT(IN OUT) :: atmabsorption
145  ! Local variables
146  INTEGER :: n_layers, n_user_layers
147  INTEGER :: i ! coefficent index
148  INTEGER :: k ! Layer index
149  INTEGER :: j ! Component index
150  INTEGER :: np ! number of predictors
151  REAL(fp) :: od(predictor%n_layers)
152  REAL(fp) :: od_path(0:predictor%n_layers)
153  REAL(fp) :: user_od_path(0:predictor%n_user_layers)
154  INTEGER :: odps2user_idx(2, 0:predictor%n_user_layers)
155  REAL(fp) :: od_tmp
156  LOGICAL :: optran
157  INTEGER :: j0, js
158 
159  ! ------
160  ! Set up
161  ! ------
162  ! Assign the indices to a short name
163  n_layers = predictor%n_Layers
164  n_user_layers = predictor%n_User_Layers
165 
166  !--------------------------------------------------------
167  ! Compute optical path profile
168  !--------------------------------------------------------
169  ! Loop over each tau component for optical depth calculation
170  od = zero
171  component_loop: DO j = 1, predictor%n_Components
172 
173  ! number of predictors for the current component and channel
174  ! Note, TC%n_Predictors(j, ChannelIndex) <= Predictor%n_CP(j).
175  ! For example, if the upper m predictors have zero coefficients,
176  ! then, only coefficients with indexed 1 to (Predictor%n_CP(j) - m)
177  ! are stored and used used in the OD calculations.
178  np = tc%n_Predictors(j, channelindex)
179 
180  ! Check if there is any absorption for the component&channel combination.
181  IF( np <= 0 ) cycle component_loop
182 
183  ! set flag for possible OPTRAN algorithm
184  ! If this flag is set, this component is computed using OPTRAN algorithm.
185  ! Otherwise, it is computed using ODPS algorithm.
186  IF( predictor%OPTRAN .AND. j == tc%OComponent_Index)THEN
187  optran = tc%OSignificance(channelindex) == significance_optran
188  ELSE
189  optran = .false.
190  END IF
191 
192  IF(optran)THEN
193  CALL add_optran_wlood(tc, &
194  channelindex, &
195  predictor, &
196  od )
197  ELSE
198 
199  ! ODPS algorithm
200  j0 = tc%Pos_Index(j, channelindex)
201  DO i = 1, np
202  js = j0+(i-1)*n_layers-1
203  DO k = 1, n_layers
204  od(k) = od(k) + tc%C(js+k)*predictor%X(k, i, j)
205  END DO
206  END DO
207 
208  END IF
209 
210  END DO component_loop
211 
212  !------------------------------------------------------
213  ! Compute optical path (level to space) profile
214  !------------------------------------------------------
215  od_path(0) = zero
216  DO k = 1, n_layers
217  od_tmp = od(k)
218  IF(od(k) < zero)THEN
219  od_tmp = zero
220  ELSE IF(od(k) > max_od)THEN
221  od_tmp = max_od
222  END IF
223  od_path(k) = od_path(k-1) + od_tmp
224  END DO
225 
226  ! Save forward variables
227  ! Interpolate the path profile back on the user pressure grids,
228  ! Compute layer optical depths (vertical direction)
229  IF ( pafv_associated(predictor%PAFV) ) THEN
230  ! save forwad variables
231  predictor%PAFV%OD = od
232  predictor%PAFV%OD_Path = od_path
233  ! If interpolation indexes are known
234  user_od_path(0) = zero
235  CALL interpolate_profile(predictor%PAFV%ODPS2User_Idx, &
236  od_path, &
237  predictor%Ref_Level_LnPressure, &
238  predictor%User_Level_LnPressure, &
239  user_od_path)
240  ELSE
241  ! interpolation indexes are not known
242  CALL compute_interp_index(predictor%Ref_Level_LnPressure, &
243  predictor%User_Level_LnPressure,&
244  odps2user_idx)
245  CALL interpolate_profile(odps2user_idx, &
246  od_path, &
247  predictor%Ref_Level_LnPressure, &
248  predictor%User_Level_LnPressure, &
249  user_od_path)
250  END IF
251 
252  ! Optical depth profile scaled to zenith. Note that the scaling
253  ! factor is the surface secant zenith angle.
254  atmabsorption%Optical_Depth = (user_od_path(1:n_user_layers) - &
255  user_od_path(0:n_user_layers-1)) / &
256  predictor%Secant_Zenith_Surface
257 
258  END SUBROUTINE odps_compute_atmabsorption
259 
260 !------------------------------------------------------------------------------
261 !:sdoc+:
262 !
263 ! NAME:
264 ! ODPS_Compute_AtmAbsorption_TL
265 !
266 ! PURPOSE:
267 ! Subroutine to calculate the tangent-linear layer optical depths due
268 ! to gaseous absorption for a given sensor and channel and atmospheric
269 ! profile.
270 !
271 ! CALLING SEQUENCE:
272 ! CALL ODPS_Compute_AtmAbsorption_TL( &
273 ! TC , &
274 ! ChannelIndex , &
275 ! Predictor , &
276 ! Predictor_TL, &
277 ! AtmAbsorption_TL )
278 !
279 ! INPUTS:
280 ! TC:
281 ! ODPS structure holding tau coefficients
282 ! UNITS: N/A
283 ! TYPE: ODPS_type
284 ! DIMENSION: Scalar
285 ! ATTRIBUTES: INTENT(IN)
286 !
287 ! ChannelIndex:
288 ! Channel index id. This is a unique index associated with a
289 ! supported sensor channel used to access the shared coefficient
290 ! data for a particular sensor's channel.
291 ! UNITS: N/A
292 ! TYPE: INTEGER
293 ! DIMENSION: Scalar
294 ! ATTRIBUTES: INTENT(IN)
295 !
296 ! Predictor:
297 ! Structure containing the predictor profile data.
298 ! UNITS: N/A
299 ! TYPE: ODPS_Predictor_type
300 ! DIMENSION: Scalar
301 ! ATTRIBUTES: INTENT(IN)
302 !
303 ! Predictor_TL:
304 ! Structure containing the tangent-linear predictor profile data.
305 ! UNITS: N/A
306 ! TYPE: ODPS_Predictor_type
307 ! DIMENSION: Scalar
308 ! ATTRIBUTES: INTENT(IN)
309 !
310 ! OUTPUTS:
311 ! AtmAbsorption_TL:
312 ! Structure containing computed tangent-linear optical depth profile
313 ! data.
314 ! UNITS: N/A
315 ! TYPE: CRTM_AtmOptics_type
316 ! DIMENSION: Scalar
317 ! ATTRIBUTES: INTENT(IN OUT)
318 !
319 !:sdoc-:
320 !------------------------------------------------------------------------------
321 
322  SUBROUTINE odps_compute_atmabsorption_tl( &
323  TC , & ! Input
324  ChannelIndex , & ! Input
325  Predictor , & ! Input
326  Predictor_TL , & ! Input
327  AtmAbsorption_TL ) ! Output
328  ! Arguments
329  TYPE(odps_type) , INTENT(IN) :: tc
330  INTEGER , INTENT(IN) :: channelindex
331  TYPE(odps_predictor_type), INTENT(IN) :: predictor
332  TYPE(odps_predictor_type), INTENT(IN OUT) :: predictor_tl
333  TYPE(crtm_atmoptics_type), INTENT(IN OUT) :: atmabsorption_tl
334  ! Local variables
335  INTEGER :: n_layers, n_user_layers
336  INTEGER :: i ! coefficent index
337  INTEGER :: k ! Layer index
338  INTEGER :: j ! Component index
339  INTEGER :: np ! number of predictors
340  REAL(fp) :: od_tl(predictor%n_layers)
341  REAL(fp) :: od_path_tl(0:predictor%n_layers)
342  REAL(fp) :: user_od_path_tl(0:predictor%n_user_layers)
343  LOGICAL :: optran
344  INTEGER :: j0, js
345 
346  ! ------
347  ! Set up
348  ! ------
349  ! Assign the indices to a short name
350  n_layers = predictor%n_Layers
351  n_user_layers = predictor%n_User_Layers
352 
353  !-----------------------------
354  ! Compute optical path profile
355  !-----------------------------
356  ! Loop over each tau component for optical depth calculation
357  od_tl = zero
358  component_loop: DO j = 1, predictor%n_Components
359 
360  ! number of predictors for the current component and channel
361  ! Note, TC%n_Predictors(j, ChannelIndex) <= Predictor%n_CP(j).
362  ! For example, if the upper m predictors have zero coefficients,
363  ! then, only coefficients with indexed 1 to (Predictor%n_CP(j) - m)
364  ! are stored and used used in the OD calculations.
365  np = tc%n_Predictors(j, channelindex)
366 
367  ! Check if there is any absorption for the component&channel combination.
368  IF( np <= 0 ) cycle component_loop
369 
370  ! set flag for possible OPTRAN algorithm
371  ! If this flag is set, this component is computed using OPTRAN algorithm.
372  ! Otherwise, it is computed using ODPS algorithm.
373  IF( predictor%OPTRAN .AND. j == tc%OComponent_Index)THEN
374  optran = tc%OSignificance(channelindex) == significance_optran
375  ELSE
376  optran = .false.
377  END IF
378 
379  IF(optran)THEN
380  CALL add_optran_wlood_tl(tc, &
381  channelindex, &
382  predictor, &
383  predictor_tl, &
384  od_tl)
385  ELSE
386 
387  ! ODPS algorithm
388  j0 = tc%Pos_Index(j, channelindex)
389  DO i = 1, np
390  js = j0+(i-1)*n_layers-1
391  DO k = 1, n_layers
392  od_tl(k) = od_tl(k) + tc%C(js+k)*predictor_tl%X(k, i, j)
393  END DO
394  END DO
395 
396  END IF
397 
398  END DO component_loop
399 
400  !------------------------------------------------------
401  ! Compute optical path (level to space) profile
402  !------------------------------------------------------
403  od_path_tl(0) = zero
404  DO k = 1, n_layers
405  IF(predictor%PAFV%OD(k) < zero)THEN
406  od_tl(k) = zero
407  ELSE IF(predictor%PAFV%OD(k) > max_od)THEN
408  od_tl(k) = zero
409  END IF
410  od_path_tl(k) = od_path_tl(k-1) + od_tl(k)
411  END DO
412 
413  ! Interpolate the path profile back on the user pressure grids,
414  ! Compute layer optical depths (vertical direction)
415  CALL interpolate_profile_f1_tl(predictor%PAFV%ODPS2User_Idx, &
416  predictor%Ref_Level_LnPressure, &
417  predictor%User_Level_LnPressure, &
418  od_path_tl, &
419  user_od_path_tl)
420 
421  atmabsorption_tl%Optical_Depth = (user_od_path_tl(1:n_user_layers) - &
422  user_od_path_tl(0:n_user_layers-1)) / &
423  predictor%Secant_Zenith_Surface
424 
425  END SUBROUTINE odps_compute_atmabsorption_tl
426 
427 !------------------------------------------------------------------------------
428 !:sdoc+:
429 !
430 ! NAME:
431 ! ODPS_Compute_AtmAbsorption_AD
432 !
433 ! PURPOSE:
434 ! Subroutine to calculate the layer optical depth adjoint due to gaseous
435 ! absorption for a given sensor and channel and atmospheric profile.
436 !
437 ! CALLING SEQUENCE:
438 ! CALL ODPS_Compute_AtmAbsorption_AD( &
439 ! TC , &
440 ! ChannelIndex , &
441 ! Predictor , &
442 ! AtmAbsorption_AD, &
443 ! Predictor_AD )
444 !
445 ! INPUTS:
446 ! TC:
447 ! ODPS structure holding tau coefficients
448 ! UNITS: N/A
449 ! TYPE: ODPS_type
450 ! DIMENSION: Scalar
451 ! ATTRIBUTES: INTENT(IN)
452 !
453 ! ChannelIndex:
454 ! Channel index id. This is a unique index associated with a
455 ! supported sensor channel used to access the shared coefficient
456 ! data for a particular sensor's channel.
457 ! UNITS: N/A
458 ! TYPE: INTEGER
459 ! DIMENSION: Scalar
460 ! ATTRIBUTES: INTENT(IN)
461 !
462 ! Predictor:
463 ! Structure containing the predictor profile data.
464 ! UNITS: N/A
465 ! TYPE: ODPS_Predictor_type
466 ! DIMENSION: Scalar
467 ! ATTRIBUTES: INTENT(IN)
468 !
469 ! AtmAbsorption_AD:
470 ! Structure containing optical depth adjoint profile data.
471 ! **NOTE: Optical depth component Set to zero upon exit **
472 ! UNITS: N/A
473 ! TYPE: CRTM_AtmOptics_type
474 ! DIMENSION: Scalar
475 ! ATTRIBUTES: INTENT(IN OUT)
476 !
477 ! OUTPUTS:
478 ! Predictor_AD:
479 ! Structure containing the adjoint predictor profile data.
480 ! **NOTE: Must contain data upon entry **
481 ! UNITS: N/A
482 ! TYPE: ODPS_Predictor_type
483 ! DIMENSION: Scalar
484 ! ATTRIBUTES: INTENT(IN OUT)
485 !
486 !:sdoc-:
487 !------------------------------------------------------------------------------
488 
489  SUBROUTINE odps_compute_atmabsorption_ad( &
490  TC , & ! Input
491  ChannelIndex , & ! Input
492  Predictor , & ! Input
493  AtmAbsorption_AD, & ! Input
494  Predictor_AD ) ! Output
495  ! Arguments
496  TYPE(odps_type) , INTENT(IN) :: tc
497  INTEGER , INTENT(IN) :: channelindex
498  TYPE(odps_predictor_type), INTENT(IN) :: predictor
499  TYPE(crtm_atmoptics_type), INTENT(IN OUT) :: atmabsorption_ad
500  TYPE(odps_predictor_type), INTENT(IN OUT) :: predictor_ad
501  ! Local variables
502  INTEGER :: n_layers, n_user_layers
503  INTEGER :: i ! coefficent index
504  INTEGER :: k ! Layer index
505  INTEGER :: j ! Component index
506  INTEGER :: np ! number of predictors
507  REAL(fp) :: od_ad(predictor%n_layers)
508  REAL(fp) :: od_path_ad(0:predictor%n_layers)
509  REAL(fp) :: user_od_path_ad(0:predictor%n_user_layers)
510  LOGICAL :: optran
511  INTEGER :: j0, js
512 
513  ! ------
514  ! Set up
515  ! ------
516  ! Assign the indices to a short name
517  n_layers = predictor%n_Layers
518  n_user_layers = predictor%n_User_Layers
519 
520  !------- Adjoint part ---------
521 
522  ! Interpolate the path profile back on the user pressure grids,
523  ! Compute layer optical depths (vertical direction)
524  user_od_path_ad(n_user_layers) = zero
525  DO k = n_user_layers, 1, -1
526  user_od_path_ad(k) = user_od_path_ad(k) &
527  + atmabsorption_ad%Optical_Depth(k)/predictor%Secant_Zenith_Surface
528  ! combined with initilization
529  user_od_path_ad(k-1) = -atmabsorption_ad%Optical_Depth(k)/predictor%Secant_Zenith_Surface
530  END DO
531  atmabsorption_ad%Optical_Depth = zero
532 
533  od_path_ad = zero
534  CALL interpolate_profile_f1_ad(predictor%PAFV%ODPS2User_Idx, &
535  predictor%Ref_Level_LnPressure, &
536  predictor%User_Level_LnPressure, &
537  user_od_path_ad, &
538  od_path_ad )
539 
540 
541  user_od_path_ad(0) = zero
542 
543  !-----------------------------
544  ! Compute optical path profile
545  !-----------------------------
546 
547  DO k = n_layers, 1, -1
548  od_path_ad(k-1) = od_path_ad(k-1) + od_path_ad(k)
549  ! combined with initialization
550  od_ad(k) = od_path_ad(k)
551  od_path_ad(k) = zero
552  IF(predictor%PAFV%OD(k) < zero)THEN
553  od_ad(k) = zero
554  ELSE IF(predictor%PAFV%OD(k) > max_od)THEN
555  od_ad(k) = zero
556  END IF
557  END DO
558  od_path_ad(0) = zero
559 
560  ! Loop over each tau component for optical depth calculation
561 
562  component_loop_ad: DO j = 1, predictor%n_Components
563 
564  ! number of predictors for the current component and channel
565  ! Note, TC%n_Predictors(j, ChannelIndex) <= Predictor%n_CP(j).
566  ! For example, if the upper m predictors have zero coefficients,
567  ! then, only coefficients with indexed 1 to (Predictor%n_CP(j) - m)
568  ! are stored and used used in the OD calculations.
569  np = tc%n_Predictors(j, channelindex)
570 
571  ! Check if there is any absorption for the component&channel combination.
572  IF( np <= 0 ) cycle component_loop_ad
573 
574  IF( predictor%OPTRAN .AND. j == tc%OComponent_Index)THEN
575  optran = tc%OSignificance(channelindex) == significance_optran
576  ELSE
577  optran = .false.
578  END IF
579 
580  IF(optran)THEN
581 
582  CALL add_optran_wlood_ad(tc, &
583  channelindex, &
584  predictor, &
585  od_ad, &
586  predictor_ad )
587  ELSE
588 
589  ! ODPS algorithm
590  j0 = tc%Pos_Index(j, channelindex)
591  DO i = 1, np
592  js = j0+(i-1)*n_layers-1
593  DO k = n_layers, 1, -1
594  predictor_ad%X(k, i, j) = predictor_ad%X(k, i, j) + tc%C(js+k)*od_ad(k)
595  END DO
596  END DO
597 
598  END IF
599 
600  END DO component_loop_ad
601 
602  END SUBROUTINE odps_compute_atmabsorption_ad
603 
604 
605 !################################################################################
606 !################################################################################
607 !## ##
608 !## ## PRIVATE MODULE ROUTINES ## ##
609 !## ##
610 !################################################################################
611 !################################################################################
612 
613 !------------------------------------------------------------------------------
614 !
615 ! NAME:
616 ! Add_OPTRAN_wloOD
617 !
618 ! PURPOSE:
619 ! Subroutine to calculate and add the layer optical depths due to water
620 ! vapor line absorption via the ODAS algorithm.
621 ! Note the OD argument is an in/out argument, which may hold accumulated
622 ! optical depths from other absorbers.
623 !
624 ! CALLING SEQUENCE:
625 ! CALL Add_OPTRAN_wloOD( &
626 ! TC , &
627 ! ChannelIndex, &
628 ! Predictor , &
629 ! OD )
630 !
631 ! INPUTS:
632 ! TC:
633 ! ODPS structure holding tau coefficients
634 ! UNITS: N/A
635 ! TYPE: ODPS_type
636 ! DIMENSION: Scalar
637 ! ATTRIBUTES: INTENT(IN)
638 !
639 ! ChannelIndex:
640 ! Channel index id. This is a unique index associated with a
641 ! supported sensor channel used to access the shared coefficient
642 ! data for a particular sensor's channel.
643 ! UNITS: N/A
644 ! TYPE: INTEGER
645 ! DIMENSION: Scalar
646 ! ATTRIBUTES: INTENT(IN)
647 !
648 ! Predictor:
649 ! Structure containing the predictor profile data.
650 ! UNITS: N/A
651 ! TYPE: ODPS_Predictor_type
652 ! DIMENSION: Scalar
653 ! ATTRIBUTES: INTENT(IN)
654 !
655 ! IN/OUTPUTS:
656 ! OD:
657 ! Slant path optical depth profile.
658 ! UNITS: N/A
659 ! TYPE: REAL(fp)
660 ! DIMENSION: Rank-1 array (n_Layers)
661 ! ATTRIBUTES: INTENT(IN OUT)
662 !
663 !
664 !------------------------------------------------------------------------------
665 
666  SUBROUTINE add_optran_wlood( &
667  TC , & ! Input
668  ChannelIndex, & ! Input
669  Predictor , & ! Input
670  OD ) ! In/Output
671  ! Arguments
672  TYPE(ODPS_type), INTENT(IN) :: TC
673  INTEGER, INTENT(IN) :: ChannelIndex
674  TYPE(ODPS_Predictor_type), INTENT(IN OUT) :: Predictor
675  REAL(fp), INTENT(IN OUT) :: OD(:)
676  ! Local variables
677  REAL(fp) :: LN_Chi(TC%n_Layers), coeff(0:MAX_OPTRAN_ORDER)
678  REAL(fp) :: b(TC%n_Layers, 0:MAX_OPTRAN_USED_PREDICTORS)
679  REAL(fp) :: Chi(TC%n_Layers)
680  INTEGER :: np, n_Layers, n_orders, js, i, j, k, ii, jj
681 
682  ! -----------------------------------------
683  ! Check if there is any absorption for this
684  ! absorber/channel combination.
685  ! -----------------------------------------
686  np = tc%OP_Index(0,channelindex) ! number of predictors
687  IF ( np <= 0 ) RETURN
688 
689  n_layers = tc%n_Layers
690  js = tc%OPos_Index(channelindex)
691  n_orders = tc%Order(channelindex)
692 
693  DO i = 0, np
694  jj = js + i*(n_orders+1)
695  coeff(0:n_orders) = tc%OC(jj:jj+n_orders)
696  DO k = 1, n_layers
697  b(k,i) = coeff(0)
698  DO j = 1, n_orders
699  b(k,i) = b(k,i) + coeff(j)*predictor%Ap(k, j)
700  END DO
701  END DO
702  END DO
703 
704  ln_chi = b(:,0)
705  DO i = 1, np
706  ii = tc%OP_Index(i,channelindex)
707  DO k = 1, n_layers
708  ln_chi(k) = ln_chi(k) + b(k, i)* predictor%OX(k, ii)
709  END DO
710  END DO
711 
712  DO k = 1, n_layers
713  IF( ln_chi(k) > limit_exp ) THEN
714  chi(k) = limit_log
715  ELSE IF( ln_chi(k) < -limit_exp ) THEN
716  chi(k) = zero
717  ELSE
718  chi(k) = exp(ln_chi(k))
719  ENDIF
720  od(k) = od(k) + chi(k)*predictor%dA(k)
721  END DO
722 
723  IF(predictor%PAFV%OPTRAN)THEN
724  predictor%PAFV%b = b
725  predictor%PAFV%LN_Chi = ln_chi
726  predictor%PAFV%Chi = chi
727  END IF
728 
729  END SUBROUTINE add_optran_wlood
730 
731 
732 !------------------------------------------------------------------------------
733 !
734 ! NAME:
735 ! Add_OPTRAN_wloOD_TL
736 !
737 ! PURPOSE:
738 ! Subroutine to calculate and add the tangent-linear layer optical depths
739 ! due to water vapor line absorption via the ODAS algorithm.
740 ! Note the OD_TL argument is an in/out argument, which may hold accumulated
741 ! tangent-linear optical depths from other absorbers.
742 !
743 ! CALLING SEQUENCE:
744 ! CALL Add_OPTRAN_wloOD_TL( &
745 ! TC , &
746 ! ChannelIndex, &
747 ! Predictor , &
748 ! Predictor_TL, &
749 ! OD_TL )
750 !
751 ! INPUTS:
752 ! TC:
753 ! ODPS structure holding tau coefficients
754 ! UNITS: N/A
755 ! TYPE: ODPS_type
756 ! DIMENSION: Scalar
757 ! ATTRIBUTES: INTENT(IN)
758 !
759 ! ChannelIndex:
760 ! Channel index id. This is a unique index associated with a
761 ! supported sensor channel used to access the shared coefficient
762 ! data for a particular sensor's channel.
763 ! UNITS: N/A
764 ! TYPE: INTEGER
765 ! DIMENSION: Scalar
766 ! ATTRIBUTES: INTENT(IN)
767 !
768 ! Predictor:
769 ! Structure containing the predictor profile data.
770 ! UNITS: N/A
771 ! TYPE: ODPS_Predictor_type
772 ! DIMENSION: Scalar
773 ! ATTRIBUTES: INTENT(IN)
774 !
775 ! Predictor_TL:
776 ! Structure containing the tangent-linear predictor profile data.
777 ! UNITS: N/A
778 ! TYPE: ODPS_Predictor_type
779 ! DIMENSION: Scalar
780 ! ATTRIBUTES: INTENT(IN)
781 !
782 ! IN/OUTPUT ARGUMENTS:
783 ! OD_TL:
784 ! Slant path tangent-linear optical depth profile
785 ! UNITS: N/A
786 ! TYPE: REAL(fp)
787 ! DIMENSION: Rank-1 array (n_Layers)
788 ! ATTRIBUTES: INTENT(IN OUT)
789 !
790 !------------------------------------------------------------------------------
791 
792  SUBROUTINE add_optran_wlood_tl( &
793  TC , &
794  ChannelIndex, &
795  Predictor , &
796  Predictor_TL, &
797  OD_TL )
798  ! Arguments
799  TYPE(ODPS_type), INTENT(IN) :: TC
800  INTEGER, INTENT(IN) :: ChannelIndex
801  TYPE(ODPS_Predictor_type), INTENT(IN) :: Predictor
802  TYPE(ODPS_Predictor_type), INTENT(IN) :: Predictor_TL
803  REAL(fp), INTENT(IN OUT) :: OD_TL(:)
804  ! Local variables
805  REAL(fp) :: coeff(0:MAX_OPTRAN_ORDER)
806  REAL(fp) :: LN_Chi_TL(TC%n_Layers), b_TL(TC%n_Layers, 0:MAX_OPTRAN_USED_PREDICTORS)
807  REAL(fp) :: chi_TL(TC%n_Layers)
808  INTEGER :: np, n_Layers, n_orders, js, i, j, k, ii, jj
809 
810  ! -----------------------------------------
811  ! Check if there is any absorption for this
812  ! absorber/channel combination.
813  ! -----------------------------------------
814  np = tc%OP_Index(0,channelindex) ! number of predictors
815  IF ( np <= 0 ) RETURN
816 
817  n_layers = tc%n_Layers
818  js = tc%OPos_Index(channelindex)
819  n_orders = tc%Order(channelindex)
820 
821  DO i = 0, np
822  jj = js + i*(n_orders+1)
823  coeff(0:n_orders) = tc%OC(jj:jj+n_orders)
824  DO k = 1, n_layers
825  b_tl(k,i) = zero
826  DO j = 1, n_orders
827  b_tl(k,i) = b_tl(k,i) + coeff(j)*predictor_tl%Ap(k, j)
828  END DO
829  END DO
830  END DO
831 
832  ln_chi_tl = b_tl(:,0)
833  DO i = 1, np
834  ii = tc%OP_Index(i,channelindex)
835  DO k = 1, n_layers
836  ln_chi_tl(k) = ln_chi_tl(k) + b_tl(k, i)* predictor%OX(k, ii) + predictor%PAFV%b(k, i)* predictor_tl%OX(k, ii)
837  END DO
838  END DO
839 
840  DO k = 1, n_layers
841  IF( predictor%PAFV%LN_Chi(k) > limit_exp ) THEN
842  chi_tl(k) = zero
843  ELSE IF( predictor%PAFV%LN_Chi(k) < -limit_exp ) THEN
844  chi_tl(k) = zero
845  ELSE
846  chi_tl(k) = predictor%PAFV%Chi(k) * ln_chi_tl(k)
847  ENDIF
848  od_tl(k) = od_tl(k) + chi_tl(k)*predictor%dA(k) + predictor%PAFV%Chi(k)*predictor_tl%dA(k)
849  END DO
850 
851  END SUBROUTINE add_optran_wlood_tl
852 
853 
854 !------------------------------------------------------------------------------
855 !
856 ! NAME:
857 ! Add_OPTRAN_wloOD_AD
858 !
859 ! PURPOSE:
860 ! Subroutine to calculate and add the layer optical depth adjoints due
861 ! to water vapor line absorption via the ODAS algorithm.
862 !
863 ! CALLING SEQUENCE:
864 ! CALL Add_OPTRAN_wloOD_AD( &
865 ! TC , &
866 ! ChannelIndex, &
867 ! Predictor , &
868 ! OD_AD , &
869 ! Predictor_AD )
870 !
871 ! INPUTS:
872 ! TC:
873 ! ODPS structure holding tau coefficients
874 ! UNITS: N/A
875 ! TYPE: ODPS_type
876 ! DIMENSION: Scalar
877 ! ATTRIBUTES: INTENT(IN)
878 !
879 ! ChannelIndex:
880 ! Channel index id. This is a unique index associated with a
881 ! supported sensor channel used to access the shared coefficient
882 ! data for a particular sensor's channel.
883 ! UNITS: N/A
884 ! TYPE: INTEGER
885 ! DIMENSION: Scalar
886 ! ATTRIBUTES: INTENT(IN)
887 !
888 ! Predictor:
889 ! Structure containing the predictor profile data.
890 ! UNITS: N/A
891 ! TYPE: ODPS_Predictor_type
892 ! DIMENSION: Scalar
893 ! ATTRIBUTES: INTENT(IN)
894 !
895 ! OD_AD:
896 ! Slant path adjoint optical depth profile
897 ! UNITS: N/A
898 ! TYPE: REAL(fp)
899 ! DIMENSION: Rank-1 array (n_Layers)
900 ! ATTRIBUTES: INTENT(IN)
901 !
902 ! IN/OUTPUTS:
903 ! Predictor_AD:
904 ! Structure containing the adjoint predictor profile data.
905 ! **NOTE: Must contain data upon entry **
906 ! UNITS: N/A
907 ! TYPE: ODPS_Predictor_type
908 ! DIMENSION: Scalar
909 ! ATTRIBUTES: INTENT(IN OUT)
910 !
911 !------------------------------------------------------------------------------
912 
913  SUBROUTINE add_optran_wlood_ad( &
914  TC , &
915  ChannelIndex, &
916  Predictor , &
917  OD_AD , &
918  Predictor_AD )
919  ! Arguments
920  TYPE(ODPS_type), INTENT(IN) :: TC
921  INTEGER, INTENT(IN) :: ChannelIndex
922  TYPE(ODPS_Predictor_type), INTENT(IN) :: Predictor
923  REAL(fp), INTENT(IN OUT) :: OD_AD(:)
924  TYPE(ODPS_Predictor_type), INTENT(IN OUT) :: Predictor_AD
925  ! Local variables
926  REAL(fp) :: coeff(0:MAX_OPTRAN_ORDER)
927  REAL(fp) :: LN_Chi_AD(TC%n_Layers), b_AD(TC%n_Layers, 0:MAX_OPTRAN_USED_PREDICTORS)
928  REAL(fp) :: Chi_AD(TC%n_Layers)
929  INTEGER :: np, n_Layers, n_orders, js, i, j, k, ii, jj
930 
931  !------ Forward part for LN_Chi, b -----------
932 
933  ! -----------------------------------------
934  ! Check if there is any absorption for this
935  ! absorber/channel combination.
936  ! -----------------------------------------
937  np = tc%OP_Index(0,channelindex) ! number of predictors
938  IF ( np <= 0 ) RETURN
939 
940  n_layers = tc%n_Layers
941  js = tc%OPos_Index(channelindex)
942  n_orders = tc%Order(channelindex)
943 
944  !------ Adjoint part ----------------------
945 
946  ! -----------------------------------------
947  ! Check if there is any absorption for this
948  ! absorber/channel combination.
949  ! -----------------------------------------
950 
951  chi_ad = zero
952  ln_chi_ad = zero
953  DO k = n_layers, 1, -1
954 
955  chi_ad(k) = chi_ad(k) + od_ad(k) * predictor%dA(k)
956  predictor_ad%dA(k) = predictor_ad%dA(k) + od_ad(k) * predictor%PAFV%Chi(k)
957  IF( predictor%PAFV%LN_Chi(k) > limit_exp ) THEN
958  chi_ad(k) = zero
959  ELSE IF( predictor%PAFV%LN_Chi(k) < -limit_exp ) THEN
960  chi_ad(k) = zero
961  ELSE
962  ln_chi_ad(k) = predictor%PAFV%Chi(k) * chi_ad(k) ! combinded with initialization for LN_Chi_AD(k)
963  ENDIF
964  END DO
965 
966  DO i = 1, np
967  ii = tc%OP_Index(i,channelindex)
968  DO k = n_layers, 1, -1
969  b_ad(k, i) = ln_chi_ad(k) * predictor%OX(k, ii) ! Combinded with initialization for b_AD
970  predictor_ad%OX(k, ii) = predictor_ad%OX(k, ii) + ln_chi_ad(k)*predictor%PAFV%b(k, i)
971  END DO
972  END DO
973  b_ad(:,0) = ln_chi_ad
974 
975  DO i = 0, np
976  jj = js + i*(n_orders+1)
977  coeff(0:n_orders) = tc%OC(jj:jj+n_orders)
978  DO k = n_layers, 1, -1
979  DO j = 1, n_orders
980  predictor_ad%Ap(k, j) = predictor_ad%Ap(k, j) + coeff(j)*b_ad(k,i)
981  END DO
982  b_ad(k,i) = zero
983  END DO
984  END DO
985 
986  END SUBROUTINE add_optran_wlood_ad
987 
988 END MODULE odps_atmabsorption
real(fp), parameter, public zero
integer, parameter, public max_optran_used_predictors
integer, parameter, public fp
Definition: Type_Kinds.f90:124
real(fp), parameter, public limit_exp
subroutine add_optran_wlood_ad(TC, ChannelIndex, Predictor, OD_AD, Predictor_AD)
real(fp), parameter, public limit_log
subroutine, public odps_compute_atmabsorption(TC, ChannelIndex, Predictor, AtmAbsorption)
integer, parameter, public significance_optran
subroutine add_optran_wlood_tl(TC, ChannelIndex, Predictor, Predictor_TL, OD_TL)
character(*), parameter, private module_version_id
subroutine, public odps_compute_atmabsorption_ad(TC, ChannelIndex, Predictor, AtmAbsorption_AD, Predictor_AD)
subroutine, public interpolate_profile_f1_tl(interp_index, x, u, y_TL, y_int_TL)
subroutine add_optran_wlood(TC, ChannelIndex, Predictor, OD)
subroutine, public compute_interp_index(x, u, interp_index)
real(fp), parameter max_od
subroutine, public interpolate_profile(interp_index, y, x, u, y_int)
subroutine, public interpolate_profile_f1_ad(interp_index, x, u, y_int_AD, y_AD)
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)
subroutine, public odps_compute_atmabsorption_tl(TC, ChannelIndex, Predictor, Predictor_TL, AtmAbsorption_TL)
integer, parameter, public max_optran_order