FV3 Bundle
Azimuth_Emissivity_Module.f90
Go to the documentation of this file.
1 !
2 ! Helper module containing the azimuth emissivity routines for the
3 ! CRTM implementation of FASTEM4 and FASTEM5
4 !
5 !
6 ! CREATION HISTORY:
7 ! Written by: Original FASTEM1/2/3 authors
8 !
9 ! Modified by: Quanhua Liu, Quanhua.Liu@noaa.gov
10 ! Stephen English, Stephen.English@metoffice.gov.uk
11 ! July, 2009
12 !
13 ! Refactored by: Paul van Delst, December 2011
14 ! paul.vandelst@noaa.gov
15 !
16 
18 
19  ! -----------------
20  ! Environment setup
21  ! -----------------
22  ! Module use
23  USE type_kinds , ONLY: fp
25  ! Disable implicit typing
26  IMPLICIT NONE
27 
28 
29  ! ------------
30  ! Visibilities
31  ! ------------
32  PRIVATE
33  ! Data types
34  PUBLIC :: ivar_type
35  ! Science routines
36  PUBLIC :: azimuth_emissivity
37  PUBLIC :: azimuth_emissivity_tl
38  PUBLIC :: azimuth_emissivity_ad
39 
40 
41  ! -----------------
42  ! Module parameters
43  ! -----------------
44  CHARACTER(*), PARAMETER :: module_version_id = &
45  '$Id: Azimuth_Emissivity_Module.f90 60152 2015-08-13 19:19:13Z paul.vandelst@noaa.gov $'
46 
47  REAL(fp), PARAMETER :: zero = 0.0_fp
48  REAL(fp), PARAMETER :: one = 1.0_fp
49  REAL(fp), PARAMETER :: two = 2.0_fp
50  REAL(fp), PARAMETER :: three = 3.0_fp
51  REAL(fp), PARAMETER :: pi = 3.141592653589793238462643383279_fp
52  REAL(fp), PARAMETER :: degrees_to_radians = pi / 180.0_fp
53 
54  ! Dimensions
55  ! ...Number of component predictors for harmonic coefficients
56  INTEGER, PARAMETER :: n_predictors = 10
57  ! ...Number of Stokes parameters
58  INTEGER, PARAMETER :: n_stokes = 4
59  ! ...The number of harmonics considered in the trignometric parameterisation
60  INTEGER, PARAMETER :: n_harmonics = 3
61 
62 
63  ! --------------------------------------
64  ! Structure definition to hold internal
65  ! variables across FWD, TL, and AD calls
66  ! --------------------------------------
67  TYPE :: ivar_type
68  PRIVATE
69  ! Direct inputs
70  REAL(fp) :: wind_speed = zero
71  REAL(fp) :: frequency = zero
72  ! Derived inputs
73  REAL(fp) :: sec_z = zero
74  ! Cosine and sine of the harmonic angle, m*phi
75  REAL(fp) :: cos_angle(n_harmonics) = zero
76  REAL(fp) :: sin_angle(n_harmonics) = zero
77  ! Intermediate variables
78  REAL(fp) :: trig_coeff(n_stokes, n_harmonics) = zero
79  END TYPE ivar_type
80 
81 
82 CONTAINS
83 
84 
85  ! ===========================================================
86  ! Compute emissivity as a function of relative azimuth angle.
87  ! ===========================================================
88 
89  ! Forward model
90  SUBROUTINE azimuth_emissivity( &
91  AZCoeff , & ! Input
92  Wind_Speed , & ! Input
93  Azimuth_Angle, & ! Input
94  Frequency , & ! Input
95  cos_z , & ! Input
96  e_Azimuth , & ! Output
97  iVar ) ! Internal variable output
98  ! Arguments
99  TYPE(fitcoeff_3d_type), INTENT(IN) :: azcoeff
100  REAL(fp) , INTENT(IN) :: wind_speed
101  REAL(fp) , INTENT(IN) :: azimuth_angle
102  REAL(fp) , INTENT(IN) :: frequency
103  REAL(fp) , INTENT(IN) :: cos_z
104  REAL(fp) , INTENT(OUT) :: e_azimuth(:)
105  TYPE(ivar_type) , INTENT(IN OUT) :: ivar
106  ! Local variables
107  INTEGER :: i, m
108  REAL(fp) :: phi, angle
109  REAL(fp) :: predictor(n_predictors)
110 
111  ! Initialise output
112  e_azimuth = zero
113 
114  ! Save inputs for TL and AD calls
115  ivar%wind_speed = wind_speed
116  ivar%frequency = frequency
117  ivar%sec_z = one/cos_z
118 
119  ! Convert angle
120  phi = azimuth_angle * degrees_to_radians
121 
122  ! Compute the azimuth emissivity component predictors
123  CALL compute_predictors( wind_speed, frequency, ivar%sec_z, predictor )
124 
125  ! Compute the azimuth emissivity vector
126  harmonic_loop: DO m = 1, n_harmonics
127 
128  ! Compute the angles
129  angle = REAL(m,fp) * phi
130  ivar%cos_angle(m) = cos(angle)
131  ivar%sin_angle(m) = sin(angle)
132 
133  ! Compute the coefficients
134  DO i = 1, n_stokes
135  CALL compute_coefficient( &
136  azcoeff%C(:,i,m), &
137  predictor, &
138  ivar%trig_coeff(i,m) )
139  END DO
140 
141  ! Compute the emissivities
142  e_azimuth(1) = e_azimuth(1) + ivar%trig_coeff(1,m)*ivar%cos_angle(m) ! Vertical
143  e_azimuth(2) = e_azimuth(2) + ivar%trig_coeff(2,m)*ivar%cos_angle(m) ! Horizontal
144  e_azimuth(3) = e_azimuth(3) + ivar%trig_coeff(3,m)*ivar%sin_angle(m) ! +/- 45deg.
145  e_azimuth(4) = e_azimuth(4) + ivar%trig_coeff(4,m)*ivar%sin_angle(m) ! Circular
146 
147  END DO harmonic_loop
148 
149  ! Apply frequency correction
150  e_azimuth = e_azimuth * azimuth_freq_correction(frequency)
151 
152  END SUBROUTINE azimuth_emissivity
153 
154 
155  ! Tangent-linear model
156  SUBROUTINE azimuth_emissivity_tl( &
157  AZCoeff , & ! Input
158  Wind_Speed_TL , & ! Input
159  Azimuth_Angle_TL, & ! Input
160  e_Azimuth_TL , & ! Output
161  iVar ) ! Internal variable input
162  ! Arguments
163  TYPE(fitcoeff_3d_type), INTENT(IN) :: azcoeff
164  REAL(fp) , INTENT(IN) :: wind_speed_tl
165  REAL(fp) , INTENT(IN) :: azimuth_angle_tl
166  REAL(fp) , INTENT(OUT) :: e_azimuth_tl(:)
167  TYPE(ivar_type) , INTENT(IN) :: ivar
168  ! Local variables
169  INTEGER :: i, m
170  REAL(fp) :: phi_tl, angle_tl
171  REAL(fp) :: predictor_tl(n_predictors)
172  REAL(fp) :: trig_coeff_tl(n_stokes)
173 
174  ! Initialise output
175  e_azimuth_tl = zero
176 
177  ! Compute angle perturbation in radians
178  phi_tl = azimuth_angle_tl * degrees_to_radians
179 
180  ! Compute the azimuth emissivity component tangent-linear predictors
181  CALL compute_predictors_tl( ivar%wind_speed, ivar%frequency, ivar%sec_z, wind_speed_tl, predictor_tl )
182 
183  ! Compute the tangent-linear azimuth emissivity vector
184  harmonic_loop: DO m = 1, n_harmonics
185 
186  ! Compute the angles
187  angle_tl = REAL(m,fp) * phi_tl
188 
189  ! Compute the coefficients
190  DO i = 1, n_stokes
191  CALL compute_coefficient_tl( &
192  azcoeff%C(:,i,m), &
193  predictor_tl, &
194  trig_coeff_tl(i) )
195  END DO
196 
197  ! Compute the tangent-linear emissivities
198  ! ...Vertical polarisation
199  e_azimuth_tl(1) = e_azimuth_tl(1) + ivar%cos_angle(m)*trig_coeff_tl(1) - &
200  ivar%trig_coeff(1,m)*ivar%sin_angle(m)*angle_tl
201  ! ...Horizontal polarisation
202  e_azimuth_tl(2) = e_azimuth_tl(2) + ivar%cos_angle(m)*trig_coeff_tl(2) - &
203  ivar%trig_coeff(2,m)*ivar%sin_angle(m)*angle_tl
204  ! ...+/- 45deg. polarisation
205  e_azimuth_tl(3) = e_azimuth_tl(3) + ivar%sin_angle(m)*trig_coeff_tl(3) + &
206  ivar%trig_coeff(3,m)*ivar%cos_angle(m)*angle_tl
207  ! ...Circular polarisation
208  e_azimuth_tl(4) = e_azimuth_tl(4) + ivar%sin_angle(m)*trig_coeff_tl(4) + &
209  ivar%trig_coeff(4,m)*ivar%cos_angle(m)*angle_tl
210  END DO harmonic_loop
211 
212  ! Apply tangent-linear frequency correction
213  e_azimuth_tl = e_azimuth_tl * azimuth_freq_correction(ivar%frequency)
214 
215  END SUBROUTINE azimuth_emissivity_tl
216 
217 
218  ! Adjoint model
219  SUBROUTINE azimuth_emissivity_ad( &
220  AZCoeff , & ! Input
221  e_Azimuth_AD , & ! AD Input
222  Wind_Speed_AD , & ! AD Output
223  Azimuth_Angle_AD, & ! AD Output
224  iVar ) ! Internal variable input
225  ! Arguments
226  TYPE(fitcoeff_3d_type), INTENT(IN) :: azcoeff
227  REAL(fp) , INTENT(IN OUT) :: e_azimuth_ad(:)
228  REAL(fp) , INTENT(IN OUT) :: wind_speed_ad
229  REAL(fp) , INTENT(IN OUT) :: azimuth_angle_ad
230  TYPE(ivar_type) , INTENT(IN) :: ivar
231  ! Local variables
232  INTEGER :: i, m
233  REAL(fp) :: phi_ad, angle_ad
234  REAL(fp) :: predictor_ad(n_predictors)
235  REAL(fp) :: trig_coeff_ad(n_stokes)
236 
237  ! Initialise local adjoints
238  phi_ad = zero
239  predictor_ad = zero
240 
241  ! Adjoint of frequency correction
242  e_azimuth_ad = e_azimuth_ad * azimuth_freq_correction(ivar%frequency)
243 
244  ! Compute the azimuth emissivity vector adjoint
245  harmonic_loop: DO m = 1, n_harmonics
246 
247  ! Compute the adjoint of the emissivities
248  ! ...Circular polarisation
249  angle_ad = ivar%trig_coeff(4,m)*ivar%cos_angle(m)*e_azimuth_ad(4)
250  trig_coeff_ad(4) = ivar%sin_angle(m)*e_azimuth_ad(4)
251  ! ...+/- 45deg. polarisation
252  angle_ad = angle_ad + ivar%trig_coeff(3,m)*ivar%cos_angle(m)*e_azimuth_ad(3)
253  trig_coeff_ad(3) = ivar%sin_angle(m)*e_azimuth_ad(3)
254  ! ...Horizontal polarisation
255  angle_ad = angle_ad - ivar%trig_coeff(2,m)*ivar%sin_angle(m)*e_azimuth_ad(2)
256  trig_coeff_ad(2) = ivar%cos_angle(m)*e_azimuth_ad(2)
257  ! ...Vertical polarisation
258  angle_ad = angle_ad - ivar%trig_coeff(1,m)*ivar%sin_angle(m)*e_azimuth_ad(1)
259  trig_coeff_ad(1) = ivar%cos_angle(m)*e_azimuth_ad(1)
260 
261  ! Compute the adjoint of the coefficients
262  DO i = n_stokes, 1, -1
263  CALL compute_coefficient_ad( &
264  azcoeff%C(:,i,m), &
265  trig_coeff_ad(i), &
266  predictor_ad )
267  END DO
268 
269  ! Compute the angle adjoint
270  phi_ad = phi_ad + REAL(m,fp)*angle_ad
271 
272  END DO harmonic_loop
273 
274  ! Compute the azimuth emissivity component predictor adjoint
275  CALL compute_predictors_ad( ivar%wind_speed, ivar%frequency, ivar%sec_z, predictor_ad, wind_speed_ad )
276 
277  ! Adjoint of the angle perturbation in radians
278  azimuth_angle_ad = azimuth_angle_ad + phi_ad*degrees_to_radians
279 
280  END SUBROUTINE azimuth_emissivity_ad
281 
282 
283 !################################################################################
284 !################################################################################
285 !## ##
286 !## ## PRIVATE MODULE ROUTINES ## ##
287 !## ##
288 !################################################################################
289 !################################################################################
290 
291  ! =============================================
292  ! Compute predictors for the azimuth components
293  ! =============================================
294 
295  ! Forward model
296  SUBROUTINE compute_predictors( &
297  Wind_Speed, & ! Input
298  Frequency , & ! Input
299  sec_z , & ! Input
300  Predictor ) ! Output
301  ! Arguments
302  REAL(fp), INTENT(IN) :: Wind_Speed
303  REAL(fp), INTENT(IN) :: Frequency
304  REAL(fp), INTENT(IN) :: sec_z
305  REAL(fp), INTENT(OUT) :: Predictor(N_PREDICTORS)
306  ! Compute the predictors.
307  predictor( 1) = one
308  predictor( 2) = frequency
309  predictor( 3) = sec_z
310  predictor( 4) = sec_z * frequency
311  predictor( 5) = wind_speed
312  predictor( 6) = wind_speed * frequency
313  predictor( 7) = wind_speed**2
314  predictor( 8) = frequency * wind_speed**2
315  predictor( 9) = wind_speed * sec_z
316  predictor(10) = wind_speed * sec_z * frequency
317  END SUBROUTINE compute_predictors
318 
319 
320  ! Tangent-linear model
321  SUBROUTINE compute_predictors_tl( &
322  Wind_Speed , & ! FWD Input
323  Frequency , & ! FWD Input
324  sec_z , & ! FWD Input
325  Wind_Speed_TL, & ! TL Input
326  Predictor_TL ) ! TL Output
327  ! Arguments
328  REAL(fp), INTENT(IN) :: Wind_Speed
329  REAL(fp), INTENT(IN) :: Frequency
330  REAL(fp), INTENT(IN) :: sec_z
331  REAL(fp), INTENT(IN) :: Wind_Speed_TL
332  REAL(fp), INTENT(OUT) :: Predictor_TL(N_PREDICTORS)
333  ! Compute the tangent-linear predictors.
334  predictor_tl( 1) = zero
335  predictor_tl( 2) = zero
336  predictor_tl( 3) = zero
337  predictor_tl( 4) = zero
338  predictor_tl( 5) = wind_speed_tl
339  predictor_tl( 6) = frequency * wind_speed_tl
340  predictor_tl( 7) = two * wind_speed * wind_speed_tl
341  predictor_tl( 8) = two * frequency * wind_speed * wind_speed_tl
342  predictor_tl( 9) = sec_z * wind_speed_tl
343  predictor_tl(10) = sec_z * frequency * wind_speed_tl
344  END SUBROUTINE compute_predictors_tl
345 
346 
347  ! Adjoint model
348  SUBROUTINE compute_predictors_ad( &
349  Wind_Speed , & ! FWD Input
350  Frequency , & ! FWD Input
351  sec_z , & ! FWD Input
352  Predictor_AD , & ! AD Input
353  Wind_Speed_AD ) ! AD Output
354  ! Arguments
355  REAL(fp), INTENT(IN) :: Wind_Speed
356  REAL(fp), INTENT(IN) :: Frequency
357  REAL(fp), INTENT(IN) :: sec_z
358  REAL(fp), INTENT(IN OUT) :: Predictor_AD(N_PREDICTORS)
359  REAL(fp), INTENT(IN OUT) :: Wind_Speed_AD
360  ! Compute the predictor adjoints
361  wind_speed_ad = wind_speed_ad + &
362  sec_z * frequency * predictor_ad(10) + &
363  sec_z * predictor_ad( 9) + &
364  two * frequency * wind_speed * predictor_ad( 8) + &
365  two * wind_speed * predictor_ad( 7) + &
366  frequency * predictor_ad( 6) + &
367  predictor_ad( 5)
368  predictor_ad = zero
369  END SUBROUTINE compute_predictors_ad
370 
371 
372  ! ==============================================================
373  ! Compute the component coefficient from the regression equation
374  ! ==============================================================
375 
376  ! Forward model
377  SUBROUTINE compute_coefficient( &
378  c , & ! Input
379  X , & ! Input
380  Coefficient ) ! Output
381  ! Arguments
382  REAL(fp), INTENT(IN) :: c(:) ! regression coefficient
383  REAL(fp), INTENT(IN) :: X(:) ! predictor
384  REAL(fp), INTENT(OUT) :: Coefficient
385  ! Local variables
386  INTEGER :: i
387  ! Compute component coefficient
388  coefficient = zero
389  DO i = 1, n_predictors
390  coefficient = coefficient + c(i)*x(i)
391  END DO
392  END SUBROUTINE compute_coefficient
393 
394 
395  ! Tangent-linear model
396  SUBROUTINE compute_coefficient_tl( &
397  c , & ! Input
398  X_TL , & ! Input
399  Coefficient_TL ) ! Output
400  ! Arguments
401  REAL(fp), INTENT(IN) :: c(:) ! regression coefficient
402  REAL(fp), INTENT(IN) :: X_TL(:) ! predictor
403  REAL(fp), INTENT(OUT) :: Coefficient_TL
404  ! Local variables
405  INTEGER :: i
406  ! Compute tangent-linear component coefficient
407  coefficient_tl = zero
408  DO i = 1, n_predictors
409  coefficient_tl = coefficient_tl + c(i)*x_tl(i)
410  END DO
411  END SUBROUTINE compute_coefficient_tl
412 
413 
414  ! Adjoint model
415  SUBROUTINE compute_coefficient_ad( &
416  c , & ! Input
417  Coefficient_AD, & ! Input
418  X_AD ) ! Output
419  ! Arguments
420  REAL(fp), INTENT(IN) :: c(:) ! regression coefficient
421  REAL(fp), INTENT(IN OUT) :: Coefficient_AD
422  REAL(fp), INTENT(IN OUT) :: X_AD(:) ! predictor
423  ! Local variables
424  INTEGER :: i
425  ! Compute adjoint of the component coefficient
426  DO i = 1, n_predictors
427  x_ad(i) = x_ad(i) + c(i)*coefficient_ad
428  END DO
429  coefficient_ad = zero
430  END SUBROUTINE compute_coefficient_ad
431 
432 
433  PURE FUNCTION azimuth_freq_correction( Frequency ) RESULT( Fre_C )
434  IMPLICIT NONE
435  REAL( fp ), INTENT(IN) :: frequency
436  REAL( fp ) :: fre_c
437  INTEGER :: i
438  ! Data for the frequency correction
439  REAL(fp), PARAMETER :: x(9) = (/ 0.0_fp, 1.4_fp, 6.8_fp, 10.7_fp, 19.35_fp, &
440  37._fp, 89._fp, 150._fp, 200._fp/)
441  REAL(fp), PARAMETER :: y(9) = (/ 0.0_fp, 0.1_fp, 0.6_fp, 0.9_fp, 1._fp, &
442  1.0_fp, 0.4_fp, 0.2_fp, 0.0_fp/)
443  !
444  IF( frequency <= zero .or. frequency >= 200.0_fp ) THEN
445  fre_c = zero
446  RETURN
447  ELSE
448  DO i = 1, 8
449  IF( frequency >= x(i) .and. frequency <= x(i+1) ) THEN
450  fre_c = y(i) + (y(i+1)-y(i))/(x(i+1)-x(i))*(frequency-x(i))
451  RETURN
452  END IF
453  END DO
454  END IF
455  fre_c = zero
456 
457  END FUNCTION azimuth_freq_correction
458 
459 END MODULE azimuth_emissivity_module
subroutine, public azimuth_emissivity_tl(AZCoeff, Wind_Speed_TL, Azimuth_Angle_TL, e_Azimuth_TL, iVar)
integer, parameter, public fp
Definition: Type_Kinds.f90:124
pure real(fp) function azimuth_freq_correction(Frequency)
subroutine, public azimuth_emissivity_ad(AZCoeff, e_Azimuth_AD, Wind_Speed_AD, Azimuth_Angle_AD, iVar)
subroutine compute_coefficient(c, X, Coefficient)
subroutine compute_coefficient_tl(c, X_TL, Coefficient_TL)
subroutine compute_predictors(Wind_Speed, Frequency, sec_z, Predictor)
subroutine compute_coefficient_ad(c, Coefficient_AD, X_AD)
subroutine, public azimuth_emissivity(AZCoeff, Wind_Speed, Azimuth_Angle, Frequency, cos_z, e_Azimuth, iVar)
character(*), parameter module_version_id
subroutine compute_predictors_ad(Wind_Speed, Frequency, sec_z, Predictor_AD, Wind_Speed_AD)
subroutine compute_predictors_tl(Wind_Speed, Frequency, sec_z, Wind_Speed_TL, Predictor_TL)