28 REAL(fp),
PARAMETER:: &
29 &ttp = 2.7316e+2_fp, &
30 &psat = 6.1078e+2_fp,&
34 &cliq = 4.1855e+3_fp,&
35 &csol = 2.1060e+3_fp,&
36 &cvap = 1.8460e+3_fp,&
37 &hvap = 2.5000e+6_fp,&
38 &hfus = 3.3358e+5_fp,&
41 REAL(fp),
PARAMETER :: &
50 &xb = xa+hvap/(rv*ttp),&
51 &xbi = xai+hsub/(rv*ttp)
68 class(ufo_aod),
intent(in) :: self
69 type(ufo_geovals),
intent(in) :: geovals
70 real(kind_real),
intent(inout) :: hofx(:)
71 type(c_ptr),
value,
intent(in) :: obss
73 real(kind_real),
allocatable :: Aod_Obs(:,:)
74 real(kind_real),
allocatable :: Omg_Aod(:,:)
83 CHARACTER(*),
PARAMETER :: PROGRAM_NAME =
'ufo_aod_mod.F90' 93 CHARACTER(*),
PARAMETER :: ENDIAN_TYPE=
'little_endian' 94 CHARACTER(*),
PARAMETER :: COEFFICIENT_PATH=
'Data/' 100 INTEGER,
PARAMETER :: N_ABSORBERS = 2
101 INTEGER,
PARAMETER :: N_CLOUDS = 0
102 INTEGER,
PARAMETER :: n_aerosols_gocart_crtm = 14,n_aerosols=n_aerosols_gocart_crtm
105 INTEGER :: N_PROFILES
110 INTEGER ,
PARAMETER :: N_SENSORS = 1
111 CHARACTER(*),
PARAMETER :: SENSOR_ID(N_SENSORS) = (/
'v.viirs-m_npp'/)
113 CHARACTER(max_string) :: err_msg
119 CHARACTER(256) :: message, version
120 INTEGER :: err_stat, alloc_stat
121 INTEGER :: n_channels
122 INTEGER :: l, m, n, nc, i,k
132 TYPE(CRTM_ChannelInfo_type) :: chinfo(N_SENSORS)
137 TYPE(CRTM_Atmosphere_type),
ALLOCATABLE :: atm(:)
138 TYPE(CRTM_RTSolution_type),
ALLOCATABLE :: rts(:,:)
143 TYPE(CRTM_Atmosphere_type),
ALLOCATABLE :: atm_K(:,:)
144 TYPE(CRTM_RTSolution_type),
ALLOCATABLE :: rts_K(:,:)
147 TYPE(CRTM_Aerosol_type),
ALLOCATABLE :: aerosols(:)
149 TYPE(ufo_geoval),
pointer :: geoval
150 character(MAXVARLEN) :: varname
156 character(len=3) :: chan_num
157 character(len=100) :: var_name
158 REAL(fp),
allocatable :: rmse(:)
159 real(fp),
allocatable :: diff(:,:)
160 real(kind_real),
allocatable :: ztmp(:)
168 n_profiles=geovals%nobs
174 n_layers=
SIZE(geoval%vals,1)
176 err_msg=trim(varname)//
' not found - Stopping' 177 CALL abor1_ftn(err_msg)
181 ALLOCATE(atm(n_profiles),aerosols(n_aerosols))
185 CALL program_message( program_name, &
186 'Check/example program for the CRTM Forward and K-Matrix functions using '//&
187 ENDIAN_TYPE//
' coefficient datafiles', &
188 'CRTM Version: '//trim(version) )
197 WRITE( *,
'(/5x,"Initializing the CRTM...")' )
198 err_stat = crtm_init( sensor_id, &
200 file_path=coefficient_path, &
202 IF ( err_stat /= success )
THEN 203 message =
'Error initializing CRTM' 204 CALL display_message( program_name, message, failure )
210 n_channels = sum(crtm_channelinfo_n_channels(chinfo))
223 sensor_loop:
DO n = 1, n_sensors
231 n_channels = crtm_channelinfo_n_channels(chinfo(n))
235 ALLOCATE( rts( n_channels, n_profiles ), &
236 atm_k( n_channels, n_profiles ), &
237 rts_k( n_channels, n_profiles ), &
239 IF ( alloc_stat /= 0 )
THEN 240 message =
'Error allocating structure arrays' 241 CALL display_message( program_name, message, failure )
250 CALL crtm_atmosphere_create( atm, n_layers, n_absorbers, n_clouds, n_aerosols )
251 IF ( any(.NOT. crtm_atmosphere_associated(atm)) )
THEN 252 message =
'Error allocating CRTM Forward Atmosphere structure' 253 CALL display_message( program_name, message, failure )
258 CALL crtm_atmosphere_create( atm_k, n_layers, n_absorbers, n_clouds, n_aerosols )
259 IF ( any(.NOT. crtm_atmosphere_associated(atm_k)) )
THEN 260 message =
'Error allocating CRTM K-matrix Atmosphere structure' 261 CALL display_message( program_name, message, failure )
265 CALL crtm_rtsolution_create(rts, n_layers )
266 CALL crtm_rtsolution_create(rts_k, n_layers )
287 CALL crtm_atmosphere_zero( atm_k )
292 rts_k%Radiance =
zero 293 rts_k%Brightness_Temperature =
zero 297 rts_k(l,m)%layer_optical_depth =
one 306 call crtm_atmosphere_inspect(atm)
307 call crtm_channelinfo_inspect(chinfo(1))
311 err_stat = crtm_aod_k( atm, &
316 IF ( err_stat /= success )
THEN 317 message =
'Error calling CRTM K-Matrix Model for '//trim(sensor_id(n))
318 CALL display_message( program_name, message, failure )
330 ALLOCATE(diff(n_channels,n_profiles),rmse(n_channels))
332 allocate(aod_obs(n_profiles, n_channels))
333 allocate(omg_aod(n_profiles, n_channels))
335 write(chan_num,
'(I0)') l
337 var_name =
'aerosol_optical_depth_' // trim(chan_num) //
'_' 340 var_name =
'obs_minus_forecast_unadjusted_' // trim(chan_num) //
'_' 347 diff(l,m) = sum(rts(l,m)%layer_optical_depth(:)) - (aod_obs(m,l) - omg_aod(m,l))
348 rmse(l) = rmse(l) + diff(l,m)**2
352 rmse=sqrt(rmse/n_profiles)
354 print *,
'N_profiles', n_profiles
356 print *,
'Channel: ',l
357 print *,
'Max difference: ', maxval(abs(diff(l,:)))
358 print *,
'RMSE: ', rmse(l)
361 DEALLOCATE(diff,rmse)
371 hofx(i) = sum(rts(l,m)%layer_optical_depth)
380 CALL crtm_atmosphere_destroy(atm_k)
381 CALL crtm_atmosphere_destroy(atm)
382 CALL crtm_rtsolution_destroy(rts_k)
383 CALL crtm_rtsolution_destroy(rts)
389 DEALLOCATE(rts, rts_k, atm_k, stat = alloc_stat)
390 IF ( alloc_stat /= 0 )
THEN 391 message =
'Error allocating structure arrays' 392 CALL display_message( program_name, message, failure )
402 WRITE( *,
'( /5x, "Destroying the CRTM..." )' )
403 err_stat = crtm_destroy( chinfo )
404 IF ( err_stat /= success )
THEN 405 message =
'Error destroying CRTM' 406 CALL display_message( program_name, message, failure )
445 IF (geoval%vals(1,k1) > geoval%vals(n_layers,k1))
THEN 456 atm(k1)%Temperature(1:n_layers) = geoval%vals(n_layers:1:-1,k1)
458 atm(k1)%Temperature(1:n_layers) = geoval%vals(:,k1)
465 atm(k1)%Pressure(1:n_layers) = geoval%vals(n_layers:1:-1,k1)
467 atm(k1)%Pressure(1:n_layers) = geoval%vals(:,k1)
475 atm(k1)%Level_Pressure(0:n_layers) = geoval%vals(n_layers+1:1:-1,k1)
477 atm(k1)%Level_Pressure(0:n_layers) = geoval%vals(:,k1)
481 atm(k1)%Climatology = us_standard_atmosphere
483 atm(k1)%Absorber_Id(1:1) = (/ h2o_id /)
484 atm(k1)%Absorber_Units(1:1) = (/ mass_mixing_ratio_units /)
488 atm(k1)%Absorber(1:n_layers,1) = geoval%vals(n_layers:1:-1,k1)
490 atm(k1)%Absorber(1:n_layers,1) = geoval%vals(:,k1)
494 atm(k1)%Absorber_Id(2:2) = (/ o3_id /)
495 atm(k1)%Absorber_Units(2:2) = (/ volume_mixing_ratio_units /)
496 atm(k1)%Absorber(1:n_layers,2)=1.e-10
507 REAL(fp),
DIMENSION(N_LAYERS) :: ugkg_kgm2,qsat,rh,prsl,tsen,p25
517 CHARACTER(len=MAXVARLEN) :: varname
519 INTEGER :: n_aerosols_all
527 ugkg_kgm2(k)=1.0e-9_fp*(atm(m)%Level_Pressure(k)-&
528 &atm(m)%Level_Pressure(k-1))*100_fp/
grav 529 prsl(k)=atm(m)%Pressure(n_layers-k+1)*0.1_fp
530 tsen(k)=atm(m)%Temperature(n_layers-k+1)
536 rh(k)=atm(m)%Absorber(k,1)*1.e-3_fp/&
544 DO i=1,n_aerosols_all
546 IF (trim(varname) ==
'p25')
THEN 550 p25(1:n_layers)=geoval%vals(n_layers:1:-1,m)
552 p25(1:n_layers)=geoval%vals(1:n_layers,m)
567 DO i=1,n_aerosols_all
569 IF (trim(varname) ==
'p25') cycle
574 atm(m)%aerosol(ii)%Concentration(1:n_layers)=geoval%vals(n_layers:1:-1,m)
576 atm(m)%aerosol(ii)%Concentration(1:n_layers)=geoval%vals(1:n_layers,m)
579 atm(m)%aerosol(ii)%Concentration=
max(atm(m)%aerosol(ii)%Concentration*ugkg_kgm2,&
582 SELECT CASE ( trim(varname))
584 atm(m)%aerosol(ii)%type = sulfate_aerosol
587 atm(m)%Aerosol(ii)%Effective_Radius(k)=&
593 atm(m)%aerosol(ii)%type = black_carbon_aerosol
594 atm(m)%Aerosol(ii)%Effective_Radius(:)=&
595 &
aeroc%Reff(1,atm(m)%aerosol(ii)%type)
597 atm(m)%aerosol(ii)%type = black_carbon_aerosol
599 atm(m)%Aerosol(ii)%Effective_Radius(k)=&
605 atm(m)%aerosol(ii)%type = organic_carbon_aerosol
606 atm(m)%Aerosol(ii)%Effective_Radius(:)=&
607 &
aeroc%Reff(1,atm(m)%aerosol(ii)%type)
609 atm(m)%aerosol(ii)%type = organic_carbon_aerosol
611 atm(m)%Aerosol(ii)%Effective_Radius(k)=&
617 atm(m)%aerosol(ii)%type = dust_aerosol
618 atm(m)%Aerosol(ii)%Effective_Radius(:)=0.55_fp
619 atm(m)%aerosol(ii)%Concentration=&
620 &atm(m)%aerosol(ii)%Concentration+0.78_fp*p25
622 atm(m)%aerosol(ii)%type = dust_aerosol
623 atm(m)%Aerosol(ii)%Effective_Radius(:)=1.4_fp
624 atm(m)%aerosol(ii)%Concentration=&
625 &atm(m)%aerosol(ii)%Concentration+0.22_fp*p25
627 atm(m)%aerosol(ii)%type = dust_aerosol
628 atm(m)%Aerosol(ii)%Effective_Radius(:)=2.4_fp
630 atm(m)%aerosol(ii)%type = dust_aerosol
631 atm(m)%Aerosol(ii)%Effective_Radius(:)=4.5_fp
633 atm(m)%aerosol(ii)%type = dust_aerosol
634 atm(m)%Aerosol(ii)%Effective_Radius(:)=8.0_fp
637 atm(m)%aerosol(ii)%type = seasalt_ssam_aerosol
639 atm(m)%Aerosol(ii)%Effective_Radius(k)=&
644 atm(m)%aerosol(ii)%type = seasalt_sscm1_aerosol
646 atm(m)%Aerosol(ii)%Effective_Radius(k)=&
651 atm(m)%aerosol(ii)%type = seasalt_sscm2_aerosol
653 atm(m)%Aerosol(ii)%Effective_Radius(k)=&
658 atm(m)%aerosol(ii)%type = seasalt_sscm3_aerosol
660 atm(m)%Aerosol(ii)%Effective_Radius(k)=&
681 INTEGER ,
INTENT(in) :: itype
682 REAL(fp) ,
INTENT(in) :: eh
689 IF ( eh <=
aeroc%RH(1) )
THEN 694 DO k = 1,
aeroc%n_RH-1
695 IF ( eh <
aeroc%RH(k+1) .AND. eh >
aeroc%RH(k) )
THEN 705 r_eff =
aeroc%Reff(j1,itype )
707 r_eff = (1.0_fp-h1)*
aeroc%Reff(j1,itype ) + h1*
aeroc%Reff(j2,itype )
714 SUBROUTINE genqsat(qsat,tsen,prsl,nsig,ice)
736 LOGICAL ,
INTENT(in ) :: ice
737 REAL(fp),
DIMENSION(nsig),
INTENT( out) :: qsat
738 REAL(fp),
DIMENSION(nsig),
INTENT(in ) :: tsen,prsl
739 INTEGER ,
INTENT(in ) :: nsig
743 REAL(fp) pw,tdry,tr,es,es2
744 REAL(fp) w,onep3,esmax
745 REAL(fp) desidt,deswdt,dwdt,desdt,esi,esw
746 REAL(fp) :: mint,estmax
755 IF((prsl(k) < 30._fp .AND. &
756 prsl(k) > 2._fp) .AND. &
766 IF (tdry >=
ttp .OR. .NOT. ice)
THEN 768 ELSEIF (tdry <
tmix)
THEN 780 IF (tdry >=
ttp .OR. .NOT. ice)
THEN 782 ELSEIF (tdry <
tmix)
THEN 796 esmax=
min(esmax,estmax)
799 qsat(k) =
eps * es2 / (pw -
omeps * es2)
subroutine, public ufo_geovals_get_var(self, varname, geoval, status)
character(len=maxvarlen), public var_mixr
real(fp), parameter, public zero
integer, parameter, public naerosols_gocart_esrl
character(len=maxvarlen), dimension(naerosols_gocart_esrl), public var_aerosols
character(len=maxvarlen), public var_prsi
real(fp), parameter omeps
real(fp) function gocart_aerosol_size(itype, eh)
integer, parameter max_string
integer function, public obsspace_get_nobs(c_dom)
Return the number of observations.
subroutine genqsat(qsat, tsen, prsl, nsig, ice)
type(aerosolcoeff_type), target, save, public aeroc
Fortran module to handle aod observations.
Fortran derived type for aod trajectory.
real(fp), parameter, public one
subroutine load_aerosol_data()
subroutine load_atm_data()
character(len=maxvarlen), public var_prs
subroutine crtm_version(version)
real, parameter, public small_value
logical, parameter ice4qsat
Fortran module handling observation locations.
character(len=maxvarlen), public var_t
Fortran interface to ObsSpace.
subroutine ufo_aod_simobs(self, geovals, hofx, obss)
integer function, public obsspace_get_nlocs(c_dom)
Return the number of observational locations.