-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathCRTM_Tangent_Linear_Module.f90
1164 lines (1052 loc) · 53.8 KB
/
CRTM_Tangent_Linear_Module.f90
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
!
! CRTM_Tangent_Linear_Module
!
! Module containing the CRTM tangent-linear model function.
!
!
! CREATION HISTORY:
! Written by: Paul van Delst, 27-Jan-2005
!
MODULE CRTM_Tangent_Linear_Module
! ------------
! Module usage
! ------------
USE Type_Kinds, ONLY: fp
USE Message_Handler, ONLY: SUCCESS, FAILURE, WARNING, Display_Message
USE CRTM_Parameters, ONLY: SET,NOT_SET,ZERO,ONE, &
MAX_N_LAYERS , &
MAX_N_PHASE_ELEMENTS, &
MAX_N_LEGENDRE_TERMS, &
MAX_N_STOKES , &
MAX_N_ANGLES , &
MAX_N_AZIMUTH_FOURIER, &
MAX_SOURCE_ZENITH_ANGLE, &
MAX_N_STREAMS, &
MIN_COVERAGE_THRESHOLD, &
SCATTERING_ALBEDO_THRESHOLD
USE CRTM_SpcCoeff, ONLY: SC, &
SpcCoeff_IsVisibleSensor, &
SpcCoeff_IsMicrowaveSensor
USE CRTM_Atmosphere_Define, ONLY: CRTM_Atmosphere_type, &
CRTM_Atmosphere_Destroy, &
CRTM_Atmosphere_IsValid, &
CRTM_Get_PressureLevelIdx
USE CRTM_Surface_Define, ONLY: CRTM_Surface_type, &
CRTM_Surface_IsValid
USE CRTM_Geometry_Define, ONLY: CRTM_Geometry_type, &
CRTM_Geometry_IsValid
USE CRTM_ChannelInfo_Define, ONLY: CRTM_ChannelInfo_type, &
CRTM_ChannelInfo_n_Channels
USE CRTM_RTSolution_Define, ONLY: CRTM_RTSolution_type , &
CRTM_RTSolution_Destroy, &
CRTM_RTSolution_Zero
USE CRTM_Options_Define, ONLY: CRTM_Options_type, &
CRTM_Options_IsValid
USE CRTM_Atmosphere, ONLY: CRTM_Atmosphere_AddLayers , &
CRTM_Atmosphere_AddLayers_TL , &
CRTM_Atmosphere_IsFractional , &
CRTM_Atmosphere_Coverage , &
CRTM_Atmosphere_ClearSkyCopy , &
CRTM_Atmosphere_ClearSkyCopy_TL
USE CRTM_GeometryInfo_Define, ONLY: CRTM_GeometryInfo_type, &
CRTM_GeometryInfo_SetValue, &
CRTM_GeometryInfo_GetValue
USE CRTM_GeometryInfo, ONLY: CRTM_GeometryInfo_Compute
USE CRTM_Predictor_Define, ONLY: CRTM_Predictor_type , &
CRTM_Predictor_Associated, &
CRTM_Predictor_Destroy , &
CRTM_Predictor_Create
USE CRTM_Predictor, ONLY: CRTM_PVar_type => iVar_type, &
CRTM_Compute_Predictors , &
CRTM_Compute_Predictors_TL
USE CRTM_AtmAbsorption, ONLY: CRTM_AAvar_type => iVar_type, &
CRTM_Compute_AtmAbsorption , &
CRTM_Compute_AtmAbsorption_TL
USE CRTM_AtmOptics_Define, ONLY: CRTM_AtmOptics_type , &
CRTM_AtmOptics_Associated, &
CRTM_AtmOptics_Create , &
CRTM_AtmOptics_Destroy , &
CRTM_AtmOptics_Zero
USE CRTM_AerosolScatter, ONLY: CRTM_Compute_AerosolScatter , &
CRTM_Compute_AerosolScatter_TL
USE CRTM_CloudScatter, ONLY: CRTM_Compute_CloudScatter , &
CRTM_Compute_CloudScatter_TL
USE CRTM_AtmOptics, ONLY: CRTM_Include_Scattering, &
CRTM_Compute_Transmittance , &
CRTM_Compute_Transmittance_TL , &
CRTM_AtmOptics_Combine , &
CRTM_AtmOptics_Combine_TL , &
CRTM_AtmOptics_NoScatterCopy , &
CRTM_AtmOptics_NoScatterCopy_TL
USE CRTM_SfcOptics_Define, ONLY: CRTM_SfcOptics_type , &
CRTM_SfcOptics_Associated, &
CRTM_SfcOptics_Create , &
CRTM_SfcOptics_Destroy
USE CRTM_SfcOptics, ONLY: CRTM_Compute_SurfaceT , &
CRTM_Compute_SurfaceT_TL
USE CRTM_RTSolution, ONLY: CRTM_Compute_nStreams , &
CRTM_Compute_RTSolution , &
CRTM_Compute_RTSolution_TL
USE CRTM_AntennaCorrection, ONLY: CRTM_Compute_AntCorr, &
CRTM_Compute_AntCorr_TL
USE CRTM_MoleculeScatter, ONLY: CRTM_Compute_MoleculeScatter, &
CRTM_Compute_MoleculeScatter_TL
USE CRTM_AncillaryInput_Define, ONLY: CRTM_AncillaryInput_type
USE CRTM_CloudCoeff, ONLY: CRTM_CloudCoeff_IsLoaded
USE CRTM_AerosolCoeff, ONLY: CRTM_AerosolCoeff_IsLoaded
USE CRTM_NLTECorrection, ONLY: NLTE_Predictor_type , &
NLTE_Predictor_IsActive , &
Compute_NLTE_Predictor , &
Compute_NLTE_Predictor_TL , &
Compute_NLTE_Correction , &
Compute_NLTE_Correction_TL
USE ACCoeff_Define, ONLY: ACCoeff_Associated
USE NLTECoeff_Define, ONLY: NLTECoeff_Associated
USE CRTM_Planck_Functions, ONLY: CRTM_Planck_Temperature , &
CRTM_Planck_Temperature_TL
USE CRTM_CloudCover_Define, ONLY: CRTM_CloudCover_type
! Internal variable definition modules
! ...AtmOptics
USE AOvar_Define, ONLY: AOvar_type, &
AOvar_Associated, &
AOvar_Destroy , &
AOvar_Create
! ...CloudScatter
USE CSvar_Define, ONLY: CSvar_type, &
CSvar_Associated, &
CSvar_Destroy , &
CSvar_Create
! ...AerosolScatter
USE ASvar_Define, ONLY: ASvar_type, &
ASvar_Associated, &
ASvar_Destroy , &
ASvar_Create
! ...Radiative transfer
USE RTV_Define, ONLY: RTV_type, &
RTV_Associated, &
RTV_Destroy , &
RTV_Create
! -----------------------
! Disable implicit typing
! -----------------------
IMPLICIT NONE
! ------------
! Visibilities
! ------------
! Everything private by default
PRIVATE
! Public procedures
PUBLIC :: CRTM_Tangent_Linear
CONTAINS
!--------------------------------------------------------------------------------
!:sdoc+:
!
! NAME:
! CRTM_Tangent_Linear
!
! PURPOSE:
! Function that calculates tangent-linear top-of-atmosphere (TOA)
! radiances and brightness temperatures for an input atmospheric
! profile or profile set and user specified satellites/channels.
!
! CALLING SEQUENCE:
! Error_Status = CRTM_Tangent_Linear( Atmosphere , &
! Surface , &
! Atmosphere_TL , &
! Surface_TL , &
! Geometry , &
! ChannelInfo , &
! RTSolution , &
! RTSolution_TL , &
! Options = Options )
!
! INPUTS:
! Atmosphere: Structure containing the Atmosphere data.
! UNITS: N/A
! TYPE: CRTM_Atmosphere_type
! DIMENSION: Rank-1 (n_Profiles)
! ATTRIBUTES: INTENT(IN)
!
! Surface: Structure containing the Surface data.
! UNITS: N/A
! TYPE: CRTM_Surface_type
! DIMENSION: Same as input Atmosphere structure
! ATTRIBUTES: INTENT(IN)
!
! Atmosphere_TL: Structure containing the tangent-linear Atmosphere data.
! UNITS: N/A
! TYPE: CRTM_Atmosphere_type
! DIMENSION: Same as input Atmosphere structure
! ATTRIBUTES: INTENT(IN)
!
! Surface_TL: Structure containing the tangent-linear Surface data.
! UNITS: N/A
! TYPE: CRTM_Surface_type
! DIMENSION: Same as input Atmosphere structure
! ATTRIBUTES: INTENT(IN)
!
! Geometry: Structure containing the view geometry
! information.
! UNITS: N/A
! TYPE: CRTM_Geometry_type
! DIMENSION: Same as input Atmosphere structure
! ATTRIBUTES: INTENT(IN)
!
! ChannelInfo: Structure returned from the CRTM_Init() function
! that contains the satellite/sensor channel index
! information.
! UNITS: N/A
! TYPE: CRTM_ChannelInfo_type
! DIMENSION: Rank-1 (n_Sensors)
! ATTRIBUTES: INTENT(IN)
!
! OUTPUTS:
! RTSolution: Structure containing the solution to the RT equation
! for the given inputs.
! UNITS: N/A
! TYPE: CRTM_RTSolution_type
! DIMENSION: Rank-2 (n_Channels x n_Profiles)
! ATTRIBUTES: INTENT(IN OUT)
!
! RTSolution_TL: Structure containing the solution to the tangent-
! linear RT equation for the given inputs.
! UNITS: N/A
! TYPE: CRTM_RTSolution_type
! DIMENSION: Rank-2 (n_Channels x n_Profiles)
! ATTRIBUTES: INTENT(IN OUT)
!
! OPTIONAL INPUTS:
! Options: Options structure containing the optional forward model
! arguments for the CRTM.
! UNITS: N/A
! TYPE: CRTM_Options_type
! DIMENSION: Same as input Atmosphere structure
! ATTRIBUTES: INTENT(IN), OPTIONAL
!
! FUNCTION RESULT:
! Error_Status: The return value is an integer defining the error status.
! The error codes are defined in the Message_Handler module.
! If == SUCCESS the computation was sucessful
! == FAILURE an unrecoverable error occurred
! UNITS: N/A
! TYPE: INTEGER
! DIMENSION: Scalar
!
! COMMENTS:
! - The Options optional input structure arguments contain
! spectral information (e.g. emissivity) that must have the same
! spectral dimensionality (the "L" dimension) as the output
! RTSolution structures.
!
!:sdoc-:
!--------------------------------------------------------------------------------
FUNCTION CRTM_Tangent_Linear( &
Atmosphere , & ! FWD Input, M
Surface , & ! FWD Input, M
Atmosphere_TL, & ! TL Input, M
Surface_TL , & ! TL Input, M
Geometry , & ! Input, M
ChannelInfo , & ! Input, n_Sensors
RTSolution , & ! FWD Output, L x M
RTSolution_TL, & ! TL Output, L x M
Options ) & ! Optional FWD input, M
RESULT( Error_Status )
! Arguments
TYPE(CRTM_Atmosphere_type) , INTENT(IN OUT) :: Atmosphere(:) ! M
TYPE(CRTM_Surface_type) , INTENT(IN) :: Surface(:) ! M
TYPE(CRTM_Atmosphere_type) , INTENT(IN) :: Atmosphere_TL(:) ! M
TYPE(CRTM_Surface_type) , INTENT(IN) :: Surface_TL(:) ! M
TYPE(CRTM_Geometry_type) , INTENT(IN) :: Geometry(:) ! M
TYPE(CRTM_ChannelInfo_type) , INTENT(IN) :: ChannelInfo(:) ! n_Sensors
TYPE(CRTM_RTSolution_type) , INTENT(IN OUT) :: RTSolution(:,:) ! L x M
TYPE(CRTM_RTSolution_type) , INTENT(IN OUT) :: RTSolution_TL(:,:) ! L x M
TYPE(CRTM_Options_type), OPTIONAL, INTENT(IN) :: Options(:) ! M
! Function result
INTEGER :: Error_Status
! Local parameters
CHARACTER(*), PARAMETER :: ROUTINE_NAME = 'CRTM_Tangent_Linear'
! Local variables
CHARACTER(256) :: Message
LOGICAL :: Options_Present
LOGICAL :: compute_antenna_correction
LOGICAL :: Atmosphere_Invalid, Surface_Invalid, Geometry_Invalid, Options_Invalid
INTEGER :: Status_FWD, Status_TL
INTEGER :: iFOV
INTEGER :: n, n_Sensors, SensorIndex
INTEGER :: l, n_Channels, ChannelIndex
INTEGER :: m, n_Profiles
INTEGER :: ln, nc
INTEGER :: n_Full_Streams, mth_Azi
INTEGER :: cloud_coverage_flag
REAL(fp) :: Source_ZA
REAL(fp) :: Wavenumber
REAL(fp) :: transmittance, transmittance_TL
REAL(fp) :: transmittance_clear, transmittance_clear_TL
REAL(fp) :: r_cloudy
! Local ancillary input structure
TYPE(CRTM_AncillaryInput_type) :: AncillaryInput
! Local options structure for default and use values
TYPE(CRTM_Options_type) :: Default_Options, Opt
! Local atmosphere structure for extra layering
TYPE(CRTM_Atmosphere_type) :: Atm, Atm_TL
! Clear sky structures
TYPE(CRTM_Atmosphere_type) :: Atm_Clear , Atm_Clear_TL
TYPE(CRTM_AtmOptics_type) :: AtmOptics_Clear , AtmOptics_Clear_TL
TYPE(CRTM_SfcOptics_type) :: SfcOptics_Clear , SfcOptics_Clear_TL
TYPE(CRTM_RTSolution_type) :: RTSolution_Clear, RTSolution_Clear_TL
TYPE(RTV_type) :: RTV_Clear
! Component variables
TYPE(CRTM_GeometryInfo_type) :: GeometryInfo
TYPE(CRTM_Predictor_type) :: Predictor, Predictor_TL
TYPE(CRTM_AtmOptics_type) :: AtmOptics, AtmOptics_TL
TYPE(CRTM_SfcOptics_type) :: SfcOptics, SfcOptics_TL
! Component variable internals
TYPE(CRTM_PVar_type) :: PVar ! Predictor
TYPE(CRTM_AAvar_type) :: AAvar ! AtmAbsorption
TYPE(CSvar_type) :: CSvar ! CloudScatter
TYPE(ASvar_type) :: ASvar ! AerosolScatter
TYPE(AOvar_type) :: AOvar ! AtmOptics
TYPE(RTV_type) :: RTV ! RTSolution
! NLTE correction term predictors
TYPE(NLTE_Predictor_type) :: NLTE_Predictor, NLTE_Predictor_TL
! Cloud cover object
TYPE(CRTM_CloudCover_type) :: CloudCover, CloudCover_TL
! ------
! SET UP
! ------
Error_Status = SUCCESS
! If no sensors or channels, simply return
n_Sensors = SIZE(ChannelInfo)
n_Channels = SUM(CRTM_ChannelInfo_n_Channels(ChannelInfo))
IF ( n_Sensors == 0 .OR. n_Channels == 0 ) RETURN
! Check output arrays
IF ( SIZE(RTSolution, DIM=1) < n_Channels .OR. &
SIZE(RTSolution_TL,DIM=1) < n_Channels ) THEN
Error_Status = FAILURE
WRITE( Message,'("Output RTSolution structure arrays too small (",i0," and ",i0,&
&") to hold results for the number of requested channels (",i0,")")') &
SIZE(RTSolution,DIM=1), SIZE(RTSolution_TL,DIM=1), n_Channels
CALL Display_Message( ROUTINE_NAME, Message, Error_Status )
RETURN
END IF
! Check the number of profiles
! ...Number of atmospheric profiles.
n_Profiles = SIZE(Atmosphere)
! ...Check the profile dimensionality of the other mandatory arguments
IF ( SIZE(Surface) /= n_Profiles .OR. &
SIZE(Atmosphere_TL) /= n_Profiles .OR. &
SIZE(Surface_TL) /= n_Profiles .OR. &
SIZE(Geometry) /= n_Profiles .OR. &
SIZE(RTSolution, DIM=2) /= n_Profiles .OR. &
SIZE(RTSolution_TL,DIM=2) /= n_Profiles ) THEN
Error_Status = FAILURE
Message = 'Inconsistent profile dimensionality for input arguments.'
CALL Display_Message( ROUTINE_NAME, Message, Error_Status )
RETURN
END IF
! ...Check the profile dimensionality of the other optional arguments
Options_Present = .FALSE.
IF ( PRESENT(Options) ) THEN
Options_Present = .TRUE.
IF ( SIZE(Options) /= n_Profiles ) THEN
Error_Status = FAILURE
Message = 'Inconsistent profile dimensionality for Options optional input argument.'
CALL Display_Message( ROUTINE_NAME, Message, Error_Status )
RETURN
END IF
END IF
! Reinitialise the output RTSolution
CALL CRTM_RTSolution_Zero(RTSolution)
! Allocate the profile independent surface optics local structure
CALL CRTM_SfcOptics_Create( SfcOptics , MAX_N_ANGLES, MAX_N_STOKES )
CALL CRTM_SfcOptics_Create( SfcOptics_TL, MAX_N_ANGLES, MAX_N_STOKES )
IF ( (.NOT. CRTM_SfcOptics_Associated(SfcOptics )) .OR. &
(.NOT. CRTM_SfcOptics_Associated(SfcOptics_TL)) ) THEN
Error_Status = FAILURE
Message = 'Error allocating SfcOptics data structures'
CALL Display_Message( ROUTINE_NAME, Message, Error_Status )
RETURN
END IF
! ------------
! PROFILE LOOP
! ------------
Profile_Loop: DO m = 1, n_Profiles
! Check the cloud and aerosol coeff. data for cases with clouds and aerosol
IF ( Atmosphere(m)%n_Clouds > 0) then
!** clear clouds where cloud_fraction < threshold
do nc = 1, Atmosphere(m)%n_clouds
where (Atmosphere(m)%Cloud_Fraction(:) < MIN_COVERAGE_THRESHOLD)
Atmosphere(m)%Cloud_Fraction(:) = ZERO
Atmosphere(m)%Cloud(nc)%Water_Content(:) = ZERO
Atmosphere(m)%Cloud(nc)%Effective_Radius(:) = ZERO
end where
end do
IF(.NOT. CRTM_CloudCoeff_IsLoaded() )THEN
Error_Status = FAILURE
WRITE( Message,'("The CloudCoeff data must be loaded (with CRTM_Init routine) ", &
&"for the cloudy case profile #",i0)' ) m
CALL Display_Message( ROUTINE_NAME, Message, Error_Status )
RETURN
END IF
END IF
IF( Atmosphere(m)%n_Aerosols > 0 .AND. .NOT. CRTM_AerosolCoeff_IsLoaded() )THEN
Error_Status = FAILURE
WRITE( Message,'("The AerosolCoeff data must be loaded (with CRTM_Init routine) ", &
&"for the aerosol case profile #",i0)' ) m
CALL Display_Message( ROUTINE_NAME, Message, Error_Status )
RETURN
END IF
! Check the optional Options structure argument
Opt = Default_Options
IF ( Options_Present ) THEN
Opt = Options(m)
! Copy over ancillary input
AncillaryInput%SSU = Options(m)%SSU
AncillaryInput%Zeeman = Options(m)%Zeeman
END IF
! ...Assign the option specific SfcOptics input
SfcOptics%Use_New_MWSSEM = .NOT. Opt%Use_Old_MWSSEM
SfcOptics_TL%Use_New_MWSSEM = .NOT. Opt%Use_Old_MWSSEM
! Check whether to skip this profile
IF ( Opt%Skip_Profile ) CYCLE Profile_Loop
! Check the input data if required
IF ( Opt%Check_Input ) THEN
! ...Mandatory inputs
Atmosphere_Invalid = .NOT. CRTM_Atmosphere_IsValid( Atmosphere(m) )
Surface_Invalid = .NOT. CRTM_Surface_IsValid( Surface(m) )
Geometry_Invalid = .NOT. CRTM_Geometry_IsValid( Geometry(m) )
IF ( Atmosphere_Invalid .OR. Surface_Invalid .OR. Geometry_Invalid ) THEN
Error_Status = FAILURE
WRITE( Message,'("Input data check failed for profile #",i0)' ) m
CALL Display_Message( ROUTINE_NAME, Message, Error_Status )
RETURN
END IF
! ...Optional input
IF ( Options_Present ) THEN
Options_Invalid = .NOT. CRTM_Options_IsValid( Options(m) )
IF ( Options_Invalid ) THEN
Error_Status = FAILURE
WRITE( Message,'("Options data check failed for profile #",i0)' ) m
CALL Display_Message( ROUTINE_NAME, Message, Error_Status )
RETURN
END IF
! Are the channel dimensions consistent if emissivity is passed?
IF ( Options(m)%Use_Emissivity ) THEN
IF ( Options(m)%n_Channels < n_Channels ) THEN
Error_Status = FAILURE
WRITE( Message,'( "Input Options channel dimension (", i0, ") is less ", &
&"than the number of requested channels (",i0, ")" )' ) &
Options(m)%n_Channels, n_Channels
CALL Display_Message( ROUTINE_NAME, Message, Error_Status )
RETURN
END IF
END IF
! Check value for user-defined n_Streams
IF ( Options(m)%Use_N_Streams ) THEN
IF ( Options(m)%n_Streams <= 0 .OR. MOD(Options(m)%n_Streams,2) /= 0 .OR. &
Options(m)%n_Streams > MAX_N_STREAMS ) THEN
Error_Status = FAILURE
WRITE( Message,'( "Input Options n_Streams (", i0, ") is invalid" )' ) &
Options(m)%n_Streams
CALL Display_Message( ROUTINE_NAME, Message, Error_Status )
RETURN
END IF
END IF
END IF
END IF
! Process geometry
! ...Compute derived geometry
CALL CRTM_GeometryInfo_SetValue( GeometryInfo, Geometry=Geometry(m) )
CALL CRTM_GeometryInfo_Compute( GeometryInfo )
! ...Retrieve components into local variable
CALL CRTM_GeometryInfo_GetValue( &
GeometryInfo, &
iFOV = iFOV, &
Source_Zenith_Angle = Source_ZA )
! Add extra layers to current atmosphere profile
! if necessary to handle upper atmosphere
Error_Status = CRTM_Atmosphere_AddLayers( Atmosphere(m), Atm )
IF ( Error_Status /= SUCCESS ) THEN
Error_Status = FAILURE
WRITE( Message,'("Error adding FWD extra layers to profile #",i0)' ) m
CALL Display_Message( ROUTINE_NAME, Message, Error_Status )
RETURN
END IF
Error_Status = CRTM_Atmosphere_AddLayers_TL( Atmosphere(m), Atmosphere_TL(m), Atm_TL )
IF ( Error_Status /= SUCCESS ) THEN
Error_Status = FAILURE
WRITE( Message,'("Error adding TL extra layers to profile #",i0)' ) m
CALL Display_Message( ROUTINE_NAME, Message, Error_Status )
RETURN
END IF
! ...Check the total number of Atm layers
IF ( Atm%n_Layers > MAX_N_LAYERS .OR. Atm_TL%n_Layers > MAX_N_LAYERS) THEN
Error_Status = FAILURE
WRITE( Message,'("Added layers [",i0,"] cause total [",i0,"] to exceed the ",&
&"maximum allowed [",i0,"] for profile #",i0)' ) &
Atm%n_Added_Layers, Atm%n_Layers, MAX_N_LAYERS, m
CALL Display_Message( ROUTINE_NAME, Message, Error_Status )
RETURN
END IF
! Prepre the atmospheric optics structures
! ...Allocate the AtmOptics structures based on Atm extension
CALL CRTM_AtmOptics_Create( AtmOptics, &
Atm%n_Layers , &
MAX_N_LEGENDRE_TERMS, &
MAX_N_PHASE_ELEMENTS )
CALL CRTM_AtmOptics_Create( AtmOptics_TL, &
Atm%n_Layers , &
MAX_N_LEGENDRE_TERMS, &
MAX_N_PHASE_ELEMENTS )
IF ( (.NOT. CRTM_AtmOptics_Associated( Atmoptics )) .OR. &
(.NOT. CRTM_AtmOptics_Associated( Atmoptics_TL )) ) THEN
Error_Status = FAILURE
WRITE( Message,'("Error allocating AtmOptics data structures for profile #",i0)' ) m
CALL Display_Message( ROUTINE_NAME, Message, Error_Status )
RETURN
END IF
! ...Set the scattering switch
AtmOptics%Include_Scattering = Opt%Include_Scattering
AtmOptics_TL%Include_Scattering = Opt%Include_Scattering
! ...Allocate the atmospheric optics internal structure
CALL AOvar_Create( AOvar, Atm%n_Layers )
! Allocate the scattering internal variables if necessary
! ...Cloud
IF ( Atm%n_Clouds > 0 ) THEN
CALL CSvar_Create( CSvar, &
MAX_N_LEGENDRE_TERMS, &
MAX_N_PHASE_ELEMENTS, &
Atm%n_Layers , &
Atm%n_Clouds )
END IF
! ...Aerosol
IF ( Atm%n_Aerosols > 0 ) THEN
CALL ASvar_Create( ASvar, &
MAX_N_LEGENDRE_TERMS, &
MAX_N_PHASE_ELEMENTS, &
Atm%n_Layers , &
Atm%n_Aerosols )
END IF
! Determine the type of cloud coverage
cloud_coverage_flag = CRTM_Atmosphere_Coverage( atm )
! Setup for fractional cloud coverage
IF ( CRTM_Atmosphere_IsFractional(cloud_coverage_flag) ) THEN
! Compute cloudcover
Status_FWD = CloudCover%Compute_CloudCover(atm, Overlap = opt%Overlap_Id)
Status_TL = CloudCover_TL%Compute_CloudCover_TL(CloudCover, atm, atm_TL)
IF ( Status_FWD /= SUCCESS .OR. Status_TL /= SUCCESS ) THEN
Error_Status = FAILURE
WRITE( Message,'("Error computing cloud cover for profile #",i0)' ) m
CALL Display_Message( ROUTINE_NAME, Message, Error_Status )
RETURN
END IF
! Allocate all the CLEAR sky structures for fractional cloud coverage
! ...Clear sky atmosphere
Status_FWD = CRTM_Atmosphere_ClearSkyCopy(Atm, Atm_Clear)
Status_TL = CRTM_Atmosphere_ClearSkyCopy_TL(Atm, Atm_TL, Atm_Clear_TL)
IF ( Status_FWD /= SUCCESS .OR. Status_TL /= SUCCESS ) THEN
Error_status = FAILURE
WRITE( Message,'("Error copying CLEAR SKY Atmopshere structures for profile #",i0)' ) m
CALL Display_Message( ROUTINE_NAME, Message, Error_Status )
RETURN
END IF
! ...Clear sky SfcOptics
CALL CRTM_SfcOptics_Create( SfcOptics_Clear , MAX_N_ANGLES, MAX_N_STOKES )
CALL CRTM_SfcOptics_Create( SfcOptics_Clear_TL, MAX_N_ANGLES, MAX_N_STOKES )
IF ( (.NOT. CRTM_SfcOptics_Associated(SfcOptics_Clear)) .OR. &
(.NOT. CRTM_SfcOptics_Associated(SfcOptics_Clear_TL))) THEN
Error_Status = FAILURE
WRITE( Message,'("Error allocating CLEAR SKY SfcOptics data structures for profile #",i0)' ) m
CALL Display_Message( ROUTINE_NAME, Message, Error_Status )
RETURN
END IF
! ...Copy over surface optics input
SfcOptics_Clear%Use_New_MWSSEM = .NOT. Opt%Use_Old_MWSSEM
SfcOptics_Clear_TL%Use_New_MWSSEM = .NOT. Opt%Use_Old_MWSSEM
! ...CLEAR SKY average surface skin temperature for multi-surface types
CALL CRTM_Compute_SurfaceT( Surface(m), SfcOptics_Clear )
CALL CRTM_Compute_SurfaceT_TL( Surface(m), Surface_TL(m), SfcOptics_Clear_TL )
END IF
! Average surface skin temperature for multi-surface types
CALL CRTM_Compute_SurfaceT( Surface(m), SfcOptics )
CALL CRTM_Compute_SurfaceT_TL( Surface(m), Surface_TL(m), SfcOptics_TL )
! -----------
! SENSOR LOOP
! -----------
! Initialise channel counter for sensor(n)/channel(l) count
ln = 0
Sensor_Loop: DO n = 1, n_Sensors
! Shorter name
SensorIndex = ChannelInfo(n)%Sensor_Index
! Check if antenna correction to be applied for current sensor
compute_antenna_correction = ( Opt%Use_Antenna_Correction .AND. &
ACCoeff_Associated( SC(SensorIndex)%AC ) .AND. &
iFOV /= 0 )
! Compute predictors for AtmAbsorption calcs
! ...Allocate the predictor structures
CALL CRTM_Predictor_Create( &
Predictor , &
atm%n_Layers, &
SensorIndex , &
SaveFWV = 1 )
CALL CRTM_Predictor_Create( &
Predictor_TL, &
atm%n_Layers, &
SensorIndex )
IF ( (.NOT. CRTM_Predictor_Associated(Predictor)) .OR. &
(.NOT. CRTM_Predictor_Associated(Predictor_TL)) ) THEN
Error_Status=FAILURE
WRITE( Message,'("Error allocating predictor structures for profile #",i0, &
&" and ",a," sensor.")' ) m, SC(SensorIndex)%Sensor_Id
CALL Display_Message( ROUTINE_NAME, Message, Error_Status )
RETURN
END IF
! ...And now fill them
CALL CRTM_Compute_Predictors( SensorIndex , & ! Input
Atm , & ! Input
GeometryInfo , & ! Input
AncillaryInput, & ! Input
Predictor , & ! Output
PVar ) ! Internal variable output
CALL CRTM_Compute_Predictors_TL( SensorIndex , & ! Input
Atm , & ! Input
Predictor , & ! Input
Atm_TL , & ! Input
AncillaryInput, & ! Input
Predictor_TL , & ! Output
PVar ) ! Internal variable input
! Allocate the RTV structure if necessary
IF( ( Atm%n_Clouds > 0 .OR. &
Atm%n_Aerosols > 0 .OR. &
SpcCoeff_IsVisibleSensor(SC(SensorIndex)) ) .AND. &
AtmOptics%Include_Scattering ) THEN
CALL RTV_Create( RTV, MAX_N_ANGLES, MAX_N_LEGENDRE_TERMS, Atm%n_Layers )
IF ( .NOT. RTV_Associated(RTV) ) THEN
Error_Status=FAILURE
WRITE( Message,'("Error allocating RTV structure for profile #",i0, &
&" and ",a," sensor.")' ) m, TRIM(SC(SensorIndex)%Sensor_Id)
CALL Display_Message( ROUTINE_NAME, Message, Error_Status )
RETURN
END IF
! Assign algorithm selector
RTV%RT_Algorithm_Id = Opt%RT_Algorithm_Id
END IF
! Compute NLTE correction predictors
IF ( Opt%Apply_NLTE_Correction ) THEN
CALL Compute_NLTE_Predictor( &
SC(SensorIndex)%NC, & ! Input
Atm , & ! Input
GeometryInfo , & ! Input
NLTE_Predictor ) ! Output
CALL Compute_NLTE_Predictor_TL( &
NLTE_Predictor , & ! FWD Input
Atm_TL , & ! TL Input
NLTE_Predictor_TL ) ! TL Output
END IF
! ------------
! CHANNEL LOOP
! ------------
Channel_Loop: DO l = 1, ChannelInfo(n)%n_Channels
! Channel setup
! ...Skip channel if requested
IF ( .NOT. ChannelInfo(n)%Process_Channel(l) ) CYCLE Channel_Loop
! ...Shorter name
ChannelIndex = ChannelInfo(n)%Channel_Index(l)
! ...Increment the processed channel counter
ln = ln + 1
! ...Assign sensor+channel information to output
RTSolution(ln,m)%Sensor_Id = ChannelInfo(n)%Sensor_Id
RTSolution(ln,m)%WMO_Satellite_Id = ChannelInfo(n)%WMO_Satellite_Id
RTSolution(ln,m)%WMO_Sensor_Id = ChannelInfo(n)%WMO_Sensor_Id
RTSolution(ln,m)%Sensor_Channel = ChannelInfo(n)%Sensor_Channel(l)
RTSolution_TL(ln,m)%Sensor_Id = RTSolution(ln,m)%Sensor_Id
RTSolution_TL(ln,m)%WMO_Satellite_Id = RTSolution(ln,m)%WMO_Satellite_Id
RTSolution_TL(ln,m)%WMO_Sensor_Id = RTSolution(ln,m)%WMO_Sensor_Id
RTSolution_TL(ln,m)%Sensor_Channel = RTSolution(ln,m)%Sensor_Channel
! Initialisations
CALL CRTM_AtmOptics_Zero( AtmOptics )
CALL CRTM_AtmOptics_Zero( AtmOptics_TL )
CALL CRTM_AtmOptics_Zero( AtmOptics_Clear )
CALL CRTM_AtmOptics_Zero( AtmOptics_Clear_TL )
CALL CRTM_RTSolution_Zero( RTSolution_Clear )
CALL CRTM_RTSolution_Zero( RTSolution_Clear_TL )
! Determine the number of streams (n_Full_Streams) in up+downward directions
IF ( Opt%Use_N_Streams ) THEN
n_Full_Streams = Opt%n_Streams
RTSolution(ln,m)%n_Full_Streams = n_Full_Streams + 2
RTSolution(ln,m)%Scattering_Flag = .TRUE.
ELSE
n_Full_Streams = CRTM_Compute_nStreams( Atm , & ! Input
SensorIndex , & ! Input
ChannelIndex , & ! Input
RTSolution(ln,m) ) ! Output
END IF
! ...Transfer stream count to scattering structures
AtmOptics%n_Legendre_Terms = n_Full_Streams
AtmOptics_TL%n_Legendre_Terms = n_Full_Streams
! Compute the gas absorption
CALL CRTM_Compute_AtmAbsorption( SensorIndex , & ! Input
ChannelIndex , & ! Input
AncillaryInput, & ! Input
Predictor , & ! Input
AtmOptics , & ! Output
AAvar ) ! Internal variable output
CALL CRTM_Compute_AtmAbsorption_TL( SensorIndex , & ! Input
ChannelIndex , & ! Input
Predictor , & ! Input
Predictor_TL , & ! Input
AtmOptics_TL , & ! Output
AAvar ) ! Internal variable input
! Compute the molecular scattering properties
! ...Solar radiation
IF( SC(SensorIndex)%Solar_Irradiance(ChannelIndex) > ZERO .AND. &
Source_ZA < MAX_SOURCE_ZENITH_ANGLE) THEN
RTV%Solar_Flag_true = .TRUE.
END IF
! ...Visible channel with solar radiation
IF( SpcCoeff_IsVisibleSensor( SC(SensorIndex) ) .AND. RTV%Solar_Flag_true ) THEN
RTV%Visible_Flag_true = .true.
! Rayleigh phase function has 0, 1, 2 components.
IF( AtmOptics%n_Legendre_Terms < 4 ) THEN
AtmOptics%n_Legendre_Terms = 4
AtmOptics_TL%n_Legendre_Terms = AtmOptics%n_Legendre_Terms
RTSolution(ln,m)%Scattering_FLAG = .TRUE.
RTSolution(ln,m)%n_Full_Streams = AtmOptics%n_Legendre_Terms + 2
END IF
RTV%n_Azi = MIN( AtmOptics%n_Legendre_Terms - 1, MAX_N_AZIMUTH_FOURIER )
! Get molecular scattering and extinction
Wavenumber = SC(SensorIndex)%Wavenumber(ChannelIndex)
Status_FWD = CRTM_Compute_MoleculeScatter( &
Wavenumber, &
Atm , &
AtmOptics )
Status_TL = CRTM_Compute_MoleculeScatter_TL( &
Wavenumber , &
Atm_TL , &
AtmOptics_TL )
IF ( Status_FWD /= SUCCESS .OR. Status_TL /= SUCCESS) THEN
Error_Status = FAILURE
WRITE( Message,'("Error computing MoleculeScatter for ",a,&
&", channel ",i0,", profile #",i0)') &
TRIM(ChannelInfo(n)%Sensor_ID), &
ChannelInfo(n)%Sensor_Channel(l), &
m
CALL Display_Message( ROUTINE_NAME, Message, Error_Status )
RETURN
END IF
ELSE
RTV%Visible_Flag_true = .FALSE.
RTV%n_Azi = 0
IF ( CRTM_Atmosphere_IsFractional(cloud_coverage_flag) ) THEN
RTV_Clear%Visible_Flag_true = .FALSE.
RTV_Clear%n_Azi = 0
END IF
END IF
! Copy the clear-sky AtmOptics
IF ( CRTM_Atmosphere_IsFractional(cloud_coverage_flag) ) THEN
Status_FWD = CRTM_AtmOptics_NoScatterCopy( AtmOptics, AtmOptics_Clear )
Status_TL = CRTM_AtmOptics_NoScatterCopy_TL( AtmOptics, AtmOptics_TL, AtmOptics_Clear_TL )
IF ( Status_FWD /= SUCCESS .OR. Status_TL /= SUCCESS ) THEN
Error_Status = FAILURE
WRITE( Message,'("Error copying CLEAR SKY AtmOptics for ",a,&
&", channel ",i0,", profile #",i0)' ) &
TRIM(ChannelInfo(n)%Sensor_ID), ChannelInfo(n)%Sensor_Channel(l), m
CALL Display_Message( ROUTINE_NAME, Message, Error_Status )
RETURN
END IF
END IF
! Compute the cloud particle absorption/scattering properties
IF( Atm%n_Clouds > 0 ) THEN
Status_FWD = CRTM_Compute_CloudScatter( Atm , & ! Input
SensorIndex , & ! Input
ChannelIndex, & ! Input
AtmOptics , & ! Output
CSvar ) ! Internal variable output
Status_TL = CRTM_Compute_CloudScatter_TL( Atm , & ! FWD Input
AtmOptics , & ! FWD Input
Atm_TL , & ! TL Input
SensorIndex , & ! Input
ChannelIndex, & ! Input
AtmOptics_TL, & ! TL Output
CSvar ) ! Internal variable input
IF ( Status_FWD /= SUCCESS .OR. Status_TL /= SUCCESS) THEN
Error_Status = FAILURE
WRITE( Message,'("Error computing CloudScatter for ",a,&
&", channel ",i0,", profile #",i0)' ) &
TRIM(ChannelInfo(n)%Sensor_ID), ChannelInfo(n)%Sensor_Channel(l), m
CALL Display_Message( ROUTINE_NAME, Message, Error_Status )
RETURN
END IF
END IF
! Compute the aerosol absorption/scattering properties
IF ( Atm%n_Aerosols > 0 ) THEN
Status_FWD = CRTM_Compute_AerosolScatter( Atm , & ! Input
SensorIndex , & ! Input
ChannelIndex, & ! Input
AtmOptics , & ! In/Output
ASvar ) ! Internal variable output
Status_TL = CRTM_Compute_AerosolScatter_TL( Atm , & ! FWD Input
AtmOptics , & ! FWD Input
Atm_TL , & ! TL Input
SensorIndex , & ! Input
ChannelIndex, & ! Input
AtmOptics_TL, & ! TL Output
ASvar ) ! Internal variable input
IF ( Status_FWD /= SUCCESS .OR. Status_TL /= SUCCESS) THEN
Error_Status = FAILURE
WRITE( Message,'("Error computing AerosolScatter for ",a,&
&", channel ",i0,", profile #",i0)' ) &
TRIM(ChannelInfo(n)%Sensor_ID), ChannelInfo(n)%Sensor_Channel(l), m
CALL Display_Message( ROUTINE_NAME, Message, Error_Status )
RETURN
END IF
END IF
! Compute the combined atmospheric optical properties
IF( AtmOptics%Include_Scattering ) THEN
CALL CRTM_AtmOptics_Combine( AtmOptics, AOvar )
CALL CRTM_AtmOptics_Combine_TL( AtmOptics, AtmOptics_TL, AOvar )
END IF
! ...Save vertically integrated scattering optical depth for output
RTSolution(ln,m)%SOD = AtmOptics%Scattering_Optical_Depth
RTSolution_TL(ln,m)%SOD = AtmOptics_TL%Scattering_Optical_Depth
! Compute the all-sky atmospheric transmittance
! for use in FASTEM-X reflection correction
CALL CRTM_Compute_Transmittance(AtmOptics,transmittance)
SfcOptics%Transmittance = transmittance
CALL CRTM_Compute_Transmittance_TL(AtmOptics,AtmOptics_TL,transmittance_TL)
SfcOptics_TL%Transmittance = transmittance_TL
! ...Clear sky for fractional cloud cover
IF ( CRTM_Atmosphere_IsFractional(cloud_coverage_flag) ) THEN
CALL CRTM_Compute_Transmittance(AtmOptics_Clear,transmittance_clear)
SfcOptics_Clear%Transmittance = transmittance_clear
CALL CRTM_Compute_Transmittance_TL(AtmOptics_Clear,AtmOptics_Clear_TL,transmittance_clear_TL)
SfcOptics_Clear_TL%Transmittance = transmittance_clear_TL
END IF
! Fill the SfcOptics structure for the optional emissivity input case.
SfcOptics%Compute = .TRUE.
SfcOptics_Clear%Compute = .TRUE.
IF ( Opt%Use_Emissivity ) THEN
! ...Cloudy/all-sky case
SfcOptics%Compute = .FALSE.
SfcOptics%Emissivity(1,1) = Opt%Emissivity(ln)
SfcOptics%Reflectivity(1,1,1,1) = ONE - Opt%Emissivity(ln)
IF ( Opt%Use_Direct_Reflectivity ) THEN
SfcOptics%Direct_Reflectivity(1,1) = Opt%Direct_Reflectivity(ln)
ELSE
SfcOptics%Direct_Reflectivity(1,1) = SfcOptics%Reflectivity(1,1,1,1)
END IF
! ...Repeat for fractional clear-sky case
IF ( CRTM_Atmosphere_IsFractional(cloud_coverage_flag) ) THEN
SfcOptics_Clear%Compute = .FALSE.
SfcOptics_Clear%Emissivity(1,1) = Opt%Emissivity(ln)
SfcOptics_Clear%Reflectivity(1,1,1,1) = ONE - Opt%Emissivity(ln)
IF ( Opt%Use_Direct_Reflectivity ) THEN
SfcOptics_Clear%Direct_Reflectivity(1,1) = Opt%Direct_Reflectivity(ln)
ELSE
SfcOptics_Clear%Direct_Reflectivity(1,1) = SfcOptics%Reflectivity(1,1,1,1)
END IF
END IF
END IF
! Fourier component loop for azimuth angles (VIS).
! mth_Azi = 0 is for an azimuth-averaged value (IR, MW)
! ...Initialise radiance
RTSolution(ln,m)%Radiance = ZERO
RTSolution_TL(ln,m)%Radiance = ZERO
! ...Fourier expansion over azimuth angle
Azimuth_Fourier_Loop: DO mth_Azi = 0, RTV%n_Azi
! Set dependent component counters
RTV%mth_Azi = mth_Azi
SfcOptics%mth_Azi = mth_Azi
! Solve the radiative transfer problem
! ...Forward model
Error_Status = CRTM_Compute_RTSolution( &
Atm , & ! Input
Surface(m) , & ! Input
AtmOptics , & ! Input
SfcOptics , & ! Input
GeometryInfo , & ! Input
SensorIndex , & ! Input
ChannelIndex , & ! Input
RTSolution(ln,m), & ! Output
RTV ) ! Internal variable output
IF ( Error_Status /= SUCCESS ) THEN
WRITE( Message,'( "Error computing RTSolution for ", a, &
&", channel ", i0,", profile #",i0)' ) &
TRIM(ChannelInfo(n)%Sensor_ID), ChannelInfo(n)%Sensor_Channel(l), m
CALL Display_Message( ROUTINE_NAME, Message, Error_Status )
RETURN
END IF
! ...Tangent-linear model
Error_Status = CRTM_Compute_RTSolution_TL( &
Atm , & ! FWD Input
Surface(m) , & ! FWD Input
AtmOptics , & ! FWD Input
SfcOptics , & ! FWD Input
RTSolution(ln,m) , & ! FWD Input
Atm_TL , & ! TL Input
Surface_TL(m) , & ! TL Input
AtmOptics_TL , & ! TL Input
SfcOptics_TL , & ! TL Input
GeometryInfo , & ! Input
SensorIndex , & ! Input
ChannelIndex , & ! Input
RTSolution_TL(ln,m), & ! TL Output
RTV ) ! Internal variable input
IF ( Error_Status /= SUCCESS ) THEN
WRITE( Message,'( "Error computing RTSolution_TL for ", a, &
&", channel ", i0,", profile #",i0)' ) &
TRIM(ChannelInfo(n)%Sensor_ID), ChannelInfo(n)%Sensor_Channel(l), m
CALL Display_Message( ROUTINE_NAME, Message, Error_Status )
RETURN
END IF
! Do clear-sky calculation for fractionally cloudy atmospheres
IF ( CRTM_Atmosphere_IsFractional(cloud_coverage_flag) ) THEN
RTV_Clear%mth_Azi = mth_Azi
SfcOptics_Clear%mth_Azi = mth_Azi
! ...Forward model
Error_Status = CRTM_Compute_RTSolution( &