10 use fckit_configuration_module,
only: fckit_configuration
11 use fckit_log_module,
only : fckit_log
14 use missing_values_mod
16 use rttov_types,
only : rttov_options, rttov_profile, rttov_coefs, &
17 rttov_radiance, rttov_transmission, rttov_emissivity, &
45 character(len=max_string),
public ::
message
72 character(len=*),
parameter :: &
74 [gas_name(1:ngases_max),
'CLW']
76 integer,
parameter :: &
88 character(len=MAXVARLEN),
parameter ::
null_str =
''
91 character(len=MAXVARLEN),
parameter :: &
94 'mole_fraction_of_carbon_monoxide_in_air',
'mole_fraction_of_methane_in_air', &
95 'mole_fraction_of_sulfur_dioxide_in_air',
var_clw]
105 logical,
pointer :: calcemis(:)
107 type(rttov_emissivity),
pointer :: emissivity(:)
108 type(rttov_profile),
pointer :: profiles(:)
109 type(rttov_profile),
pointer :: profiles_k(:)
110 type(rttov_chanprof),
pointer :: chanprof(:)
111 type(rttov_transmission) :: transmission
112 type(rttov_radiance) :: radiance
114 type(rttov_emissivity),
pointer :: emissivity_k(:)
115 type(rttov_transmission) :: transmission_k
116 type(rttov_radiance) :: radiance_k
130 character(len=MAXVARLEN),
allocatable :: absorbers(:)
131 integer,
allocatable :: absorber_id(:)
133 character(len=255),
allocatable :: sensor_id(:)
134 character(len=255) :: coefficient_path
136 type(rttov_coefs),
allocatable :: rttov_coef_array(:)
137 character(len=8) :: rttov_default_opts =
'RTTOV'
138 type(rttov_options) :: rttov_opts
139 logical :: rttov_is_setup = .false.
141 logical :: satrad_compatibility = .true.
142 logical :: useqtsplitrain, splitqtotal = .false.
143 logical :: rttov_profile_checkinput = .false.
146 integer :: nchan_max_sim
164 type(fckit_configuration),
intent(in) :: f_confopts
165 type(fckit_configuration),
intent(in) :: f_confoper
167 character(*),
parameter :: routine_name =
'rttov_conf_setup'
168 integer :: ivar, jspec
169 character(len=:),
allocatable :: str
170 character(len=:),
allocatable :: str_array(:)
171 logical :: varin_satrad = .false.
177 if (f_confoper%has(
"Debug"))
then
178 call f_confoper % get_or_die(
"Debug",
debug)
183 if (f_confoper%has(
"GeoVal_type"))
then
184 call f_confoper%get_or_die(
"GeoVal_type",str)
185 if (trim(str) ==
'MetO' .or. trim(str) ==
'SatRad')
then
187 varin_satrad = .true.
188 elseif(trim(str) ==
'CRTM')
then
190 varin_satrad = .false.
192 write(
message,*) trim(routine_name),
' error: ',trim(str),
' is not a supported GeoVal type'
202 if (f_confoper%has(
"Absorbers")) &
203 conf%ngas =
conf%ngas + f_confoper%get_size(
"Absorbers")
205 allocate(
conf%Absorbers(
conf%ngas ), &
208 if (
conf%ngas > 0)
then
209 call f_confoper%get_or_die(
"Absorbers",str_array)
210 conf%Absorbers(1:
conf%ngas) = str_array
215 do jspec = 2,
conf%ngas
216 if ( any(
conf%Absorbers(jspec-1) ==
conf%Absorbers(jspec:
conf%ngas)) )
then
217 write(
message,*) trim(routine_name),
' error: ',trim(
conf%Absorbers(jspec)),
' is duplicated in Absorbers'
223 do jspec = 1,
conf%ngas
227 write(
message,*) trim(routine_name),
' error: ',trim(
conf%Absorbers(jspec)),
' not supported by UFO_Absorbers'
235 if(
conf%Absorbers(jspec) ==
var_mixr .and. varin_satrad)
then
243 allocate(
conf % SENSOR_ID(
conf % nSensors))
246 call f_confopts % get_or_die(
"Sensor_ID",str)
247 conf % SENSOR_ID(
conf%nSensors) = str
250 call f_confopts % get_or_die(
"CoefficientPath",str)
251 conf % COEFFICIENT_PATH = str
253 if(f_confopts % has(
"RTTOV_default_opts"))
then
254 call f_confopts % get_or_die(
"RTTOV_default_opts",str)
255 conf % RTTOV_default_opts = str
258 if(f_confopts % has(
"SatRad_compatibility"))
then
259 call f_confopts % get_or_die(
"SatRad_compatibility",
conf % SatRad_compatibility)
262 if(f_confopts % has(
"max_channels_per_batch"))
then
263 call f_confopts % get_or_die(
"max_channels_per_batch",
conf % nchan_max_sim)
265 conf % nchan_max_sim = 10000
268 if( .not.
conf % rttov_is_setup)
then
269 call conf % setup(f_confopts, asw=1)
274 if (
conf % rttov_coef_array(1) % coef % id_sensor == sensor_id_mw)
then
275 if(
conf % rttov_opts % rt_mw % clw_data .and.
conf % SatRad_compatibility)
then
276 conf % UseQtsplitRain = .true.
277 conf % splitQtotal = .true.
280 conf % rttov_opts % rt_ir % ozone_data = .false.
281 conf % rttov_opts % rt_ir % co2_data = .false.
282 conf % rttov_opts % rt_ir % n2o_data = .false.
283 conf % rttov_opts % rt_ir % ch4_data = .false.
284 conf % rttov_opts % rt_ir % so2_data = .false.
286 conf % UseQtsplitRain = .false.
287 conf % splitQtotal = .false.
290 if(f_confopts % has(
"RTTOV_profile_checkinput"))
then
291 call f_confopts % get_or_die(
"RTTOV_profile_checkinput",
conf % RTTOV_profile_checkinput)
295 if (f_confopts%has(
"InspectProfileNumber"))
then
296 call f_confopts % get_or_die(
"InspectProfileNumber",
conf % inspect)
297 conf % RTTOV_profile_checkinput = .true.
309 deallocate(
conf%SENSOR_ID)
310 deallocate(
conf%Absorbers)
311 deallocate(
conf%Absorber_Id)
324 type(c_ptr),
value,
intent(in) :: obss
325 type(rttov_profile),
intent(inout) :: profiles(:)
326 integer,
intent(in) :: prof_start
328 logical,
intent(inout) :: layer_quantities
329 logical,
optional,
intent(in) :: obs_info
337 character(MAXVARLEN) :: varname
339 real(kind_real) :: ifrac, sfrac, lfrac, wfrac
340 real(kind_real) :: itmp, stmp, ltmp
342 real(kind_real),
allocatable :: tmpvar(:), windsp(:), p(:)
343 logical :: variable_present
345 integer :: top_level, bottom_level, stride
346 real(kind_real) :: tstar, newt
347 integer :: level_1000hpa, level_950hpa
349 real(kind_real),
allocatable :: q_temp(:), clw_temp(:), ciw_temp(:), qtotal(:)
351 if(
present(obs_info))
then
357 nprofiles = min(
size(profiles), geovals%nlocs - prof_start + 1)
359 nlevels =
size(profiles(1)%p)
363 bottom_level = nlevels
370 do iprof = 1, nprofiles
371 p = geoval%vals(geoval%nval-nlevels+1:geoval%nval,prof_start +
iprof - 1) *
pa_to_hpa
373 if (p(1) > p(2))
then
379 profiles(
iprof)%p(top_level:bottom_level:stride) = p(:)
387 allocate(p(nlevels-1))
388 do iprof = 1, nprofiles
389 p = geoval%vals(geoval%nval-(nlevels-1)+1:geoval%nval,prof_start +
iprof - 1) *
pa_to_hpa
391 if (p(1) > p(2))
then
392 top_level = nlevels - 1
397 bottom_level = nlevels - 1
401 profiles(
iprof)%p(top_level+stride:bottom_level:stride) =
half * (p(top_level:bottom_level-stride:stride) + p(top_level+stride:bottom_level:stride))
403 profiles(
iprof)%p(nlevels) = profiles(
iprof)%p(nlevels-1) -
half * (profiles(
iprof)%p(nlevels-2) - profiles(
iprof)%p(nlevels-1))
415 if(
size(geoval%vals(:,1)) == nlevels)
then
416 do iprof = 1, nprofiles
417 profiles(
iprof)%t(top_level:bottom_level:stride) = geoval%vals(:,prof_start +
iprof - 1)
420 layer_quantities = .true.
421 bottom_level = nlevels-1
423 do iprof = 1, nprofiles
424 profiles(
iprof)%t(top_level+stride:bottom_level:stride) =
half * (profiles(
iprof)%t(top_level:bottom_level-stride:stride) + &
425 profiles(
iprof)%t(top_level+stride:bottom_level:stride))
427 profiles(
iprof)%t(nlevels) = profiles(
iprof)%t(nlevels-1) -
half * (profiles(
iprof)%t(nlevels-2) - profiles(
iprof)%t(nlevels-1))
435 profiles(1:nprofiles)%gas_units = 1
437 do jspec = 1,
conf%ngas
440 select case (
conf%Absorbers(jspec))
442 do iprof = 1, nprofiles
443 profiles(
iprof)%q(top_level:bottom_level:stride) = geoval%vals(:,prof_start +
iprof - 1) *
g_to_kg
446 do iprof = 1, nprofiles
447 profiles(
iprof)%q(top_level:bottom_level:stride) = geoval%vals(:,prof_start +
iprof - 1)
450 if (
associated(profiles(1)%o3))
then
451 do iprof = 1, nprofiles
452 profiles(
iprof)%o3(top_level:bottom_level:stride) = geoval%vals(:,prof_start +
iprof - 1)
456 if (
associated(profiles(1)%co2))
then
457 do iprof = 1, nprofiles
458 profiles(
iprof)%co2(top_level:bottom_level:stride) = geoval%vals(:,prof_start +
iprof - 1)
462 if (
associated(profiles(1)%clw))
then
463 do iprof = 1, nprofiles
464 profiles(
iprof)%clw(top_level:bottom_level:stride) = geoval%vals(:,prof_start +
iprof - 1)
479 profiles(1:nprofiles)%s2m%p = geoval%vals(1,prof_start:prof_start + nprofiles - 1) *
pa_to_hpa
481 write(
message,
'(A)')
'No near-surface pressure. Using bottom pressure level'
484 do iprof = 1, nprofiles
485 profiles(
iprof)%s2m%p = profiles(
iprof)%p(nlevels)
492 profiles(1:nprofiles)%s2m%t = geoval%vals(1,prof_start:prof_start + nprofiles - 1)
494 write(
message,
'(A)')
'No near-surface temperature. Using bottom temperature level'
497 do iprof = 1, nprofiles
498 profiles(
iprof)%s2m%t = profiles(
iprof)%t(nlevels)
506 profiles(1:nprofiles)%s2m%q = geoval%vals(1,prof_start:prof_start + nprofiles - 1)
508 write(
message,
'(A)')
'No near-surface specific humidity. Using bottom q level'
511 do iprof = 1, nprofiles
512 profiles(
iprof)%s2m%q = profiles(
iprof)%q(nlevels)
520 profiles(1:nprofiles)%s2m%u = geoval%vals(1,prof_start:prof_start + nprofiles - 1)
526 profiles(1:nprofiles)%s2m%v = geoval%vals(1,prof_start:prof_start + nprofiles - 1)
528 allocate(windsp(nprofiles))
531 windsp(1:nprofiles) = geoval%vals(1,prof_start:prof_start + nprofiles - 1)
535 do iprof = 1, nprofiles
551 profiles(1:nprofiles)%skin%surftype = int(geoval%vals(1,prof_start:prof_start + nprofiles - 1),kind=jpim)
555 profiles(1:nprofiles)%skin%watertype = int(geoval%vals(1,prof_start:prof_start + nprofiles - 1),kind=jpim)
559 profiles(1:nprofiles)%skin%t = geoval%vals(1,prof_start:prof_start + nprofiles - 1)
571 do iprof = 1, nprofiles
573 wfrac = geoval%vals(1,
iprof)
574 if (wfrac >
half)
then
575 profiles(
iprof)%skin%surftype = surftype_sea
577 profiles(
iprof)%skin%t = geoval%vals(1,prof_start +
iprof - 1)
581 profiles(
iprof)%skin%surftype = surftype_land
584 lfrac = geoval%vals(1,prof_start +
iprof - 1)
587 sfrac = geoval%vals(1,prof_start +
iprof - 1)
590 ifrac = geoval%vals(1,prof_start +
iprof - 1)
593 ltmp = geoval%vals(1,prof_start +
iprof - 1)
596 stmp = geoval%vals(1,prof_start +
iprof - 1)
599 itmp = geoval%vals(1,prof_start +
iprof - 1)
602 profiles(
iprof)%skin%t = (lfrac * ltmp + sfrac * stmp + ifrac * itmp) / (lfrac + sfrac + ifrac)
609 profiles(1:nprofiles)%skin%salinity = 35.0_kind_real
612 do iprof = 1,nprofiles
614 profiles(
iprof)%skin%fastem = [0,0,0,0,0]
621 do iprof = 1, nprofiles
622 if(
conf % SatRad_compatibility)
then
629 if(profiles(
iprof)%skin%surftype /= surftype_sea)
then
630 if(profiles(
iprof)%skin%t < 271.4_kind_real .and. &
631 profiles(
iprof)%s2m%p > 950.0_kind_real)
then
633 level_1000hpa = minloc(abs(profiles(
iprof)%p - 1000.0_kind_real),dim=1)
634 level_950hpa = minloc(abs(profiles(
iprof)%p - 950.0_kind_real),dim=1)
636 newt = profiles(
iprof)%t(level_950hpa)
637 if(profiles(
iprof)%s2m%p > 1000.0_kind_real) &
638 newt = max(newt,profiles(
iprof)%t(level_1000hpa))
639 newt = min(newt, 271.4_kind_real)
641 profiles(
iprof)%t(level_1000hpa) = max(profiles(
iprof)%t(level_1000hpa), newt)
642 profiles(
iprof)%s2m%t = max(profiles(
iprof)%s2m%t, newt)
643 tstar = profiles(
iprof)%skin%t
644 profiles(
iprof)%skin%t = max(profiles(
iprof)%skin%t, newt)
662 if(layer_quantities)
then
664 profiles(
iprof)%q(top_level+stride:bottom_level:stride) =
half * (profiles(
iprof)%q(top_level:bottom_level-stride:stride) + &
665 profiles(
iprof)%q(top_level+stride:bottom_level:stride))
667 profiles(
iprof)%q(nlevels) = profiles(
iprof)%q(nlevels-1) -
half * (profiles(
iprof)%q(nlevels-2) - profiles(
iprof)%q(nlevels-1))
669 if (
associated(profiles(1)%o3))
then
670 profiles(
iprof)%o3(top_level+stride:bottom_level:stride) =
half * &
671 (profiles(
iprof)%o3(top_level:bottom_level-stride:stride) + profiles(
iprof)%o3(top_level+stride:bottom_level:stride))
673 profiles(
iprof)%o3(nlevels) = profiles(
iprof)%o3(nlevels-1) - &
674 half * (profiles(
iprof)%o3(nlevels-2) - profiles(
iprof)%o3(nlevels-1))
677 if (
associated(profiles(1)%clw))
then
678 profiles(
iprof)%clw(top_level+stride:bottom_level:stride) =
half * &
679 (profiles(
iprof)%clw(top_level:bottom_level-stride:stride) + profiles(
iprof)%clw(top_level+stride:bottom_level:stride))
680 profiles(
iprof)%clw(1) = profiles(
iprof)%clw(2)
681 profiles(
iprof)%clw(nlevels) = profiles(
iprof)%clw(nlevels-1) - &
682 half * (profiles(
iprof)%clw(nlevels-2) - profiles(
iprof)%clw(nlevels-1))
689 if(
conf % SplitQtotal)
then
691 allocate(qtotal(nlevels), q_temp(nlevels), clw_temp(nlevels), ciw_temp(nlevels))
693 do iprof = 1, nprofiles
696 qtotal(:) = profiles(
iprof) % q(:) + profiles(
iprof) % clw(:)
700 profiles(
iprof) % p(:), &
701 profiles(
iprof) % t(:), &
706 useqtsplitrain =
conf % UseQtSplitRain)
709 profiles(
iprof) % clw(:) = clw_temp(:)
710 profiles(
iprof) % q(:) = q_temp(:)
720 deallocate(qtotal, q_temp, clw_temp, ciw_temp)
724 if(
present(obs_info))
then
732 variable_present = obsspace_has(obss,
"MetaData",
"elevation")
733 if (variable_present)
then
734 call obsspace_get_db(obss,
"MetaData",
"elevation", tmpvar)
735 profiles(1:nprofiles)%elevation = tmpvar(prof_start:prof_start + nprofiles - 1) *
m_to_km
737 variable_present = obsspace_has(obss,
"MetaData",
"surface_height")
738 if (variable_present)
then
739 call obsspace_get_db(obss,
"MetaData",
"surface_height", tmpvar)
740 profiles(1:nprofiles)%elevation = tmpvar(prof_start:prof_start + nprofiles - 1) *
m_to_km
744 profiles(1:nprofiles)%elevation = geoval%vals(1,prof_start:prof_start + nprofiles - 1) *
m_to_km
747 'MetaData elevation not in database: check implicit filtering'
753 variable_present = obsspace_has(obss,
"MetaData",
"latitude")
754 if (variable_present)
then
755 call obsspace_get_db(obss,
"MetaData",
"latitude", tmpvar )
756 profiles(1:nprofiles)%latitude = tmpvar(prof_start:prof_start + nprofiles - 1)
759 'MetaData latitude not in database: check implicit filtering'
763 variable_present = obsspace_has(obss,
"MetaData",
"longitude")
764 if (variable_present)
then
765 call obsspace_get_db(obss,
"MetaData",
"longitude", tmpvar )
766 profiles(1:nprofiles)%longitude = tmpvar(prof_start:prof_start + nprofiles - 1)
769 'MetaData longitude not in database: check implicit filtering'
780 use obsspace_mod,
only : obsspace_get_nlocs, obsspace_get_db
784 type(c_ptr),
value,
intent(in) :: obss
785 type(rttov_profile),
intent(inout) :: profiles(:)
786 integer,
optional,
intent(in) :: prof_start1
787 logical,
optional,
intent(in) :: obs_info
789 real(kind_real),
allocatable :: tmpvar(:)
791 integer :: prof_start
795 if(
present(prof_start1))
then
796 prof_start = prof_start1
801 if(
present(obs_info))
then
813 nprofiles = min(
size(profiles),
nlocs_total - prof_start + 1)
817 nlevels =
size(profiles(1)%p)
820 call obsspace_get_db(obss,
"MetaData",
"sensor_zenith_angle", tmpvar)
821 if (any(tmpvar(prof_start:prof_start + nprofiles - 1) < 0.))
then
822 profiles(1:nprofiles)%zenangle = abs(tmpvar(prof_start:prof_start + nprofiles - 1))
825 profiles(1:nprofiles)%zenangle = abs(tmpvar(prof_start:prof_start + nprofiles - 1))
829 call obsspace_get_db(obss,
"MetaData",
"sensor_azimuth_angle", tmpvar)
830 profiles(1:nprofiles)%azangle = tmpvar(prof_start:prof_start + nprofiles - 1)
832 call obsspace_get_db(obss,
"MetaData",
"solar_zenith_angle", tmpvar)
833 if (any(tmpvar(prof_start:prof_start + nprofiles - 1) < 0.))
then
834 profiles(1:nprofiles)%sunzenangle = abs(tmpvar(prof_start:prof_start + nprofiles - 1))
837 profiles(1:nprofiles)%sunzenangle = abs(tmpvar(prof_start:prof_start + nprofiles - 1))
840 call obsspace_get_db(obss,
"MetaData",
"solar_azimuth_angle", tmpvar)
841 profiles(1:nprofiles)%sunazangle = tmpvar(prof_start:prof_start + nprofiles - 1)
855 type(fckit_configuration),
intent(in) :: f_confOpts
857 include
'rttov_print_opts.interface'
859 call self % set_defaults(self%RTTOV_default_opts)
862 if (f_confopts % has(
"RTTOV_addrefrac"))
then
863 call f_confopts % get_or_die(
"RTTOV_addrefrac", self % rttov_opts % rt_all % addrefrac)
867 if (f_confopts % has(
"RTTOV_switchrad"))
then
868 call f_confopts % get_or_die(
"RTTOV_switchrad", self % rttov_opts % rt_all % switchrad)
872 if (f_confopts % has(
"RTTOV_use_q2m"))
then
873 call f_confopts % get_or_die(
"RTTOV_use_q2m", self % rttov_opts % rt_all % use_q2m)
877 if (f_confopts % has(
"RTTOV_do_lambertian"))
then
878 call f_confopts % get_or_die(
"RTTOV_do_lambertian", self % rttov_opts % rt_all % do_lambertian)
882 if (f_confopts % has(
"RTTOV_lambertian_fixed_angle"))
then
883 call f_confopts % get_or_die(
"RTTOV_lambertian_fixed_angle", self % rttov_opts % rt_all % lambertian_fixed_angle)
887 if (f_confopts % has(
"RTTOV_plane_parallel"))
then
888 call f_confopts % get_or_die(
"RTTOV_plane_parallel", self % rttov_opts % rt_all % plane_parallel)
892 if (f_confopts % has(
"RTTOV_rad_down_lin_tau"))
then
893 call f_confopts % get_or_die(
"RTTOV_rad_down_lin_tau", self % rttov_opts % rt_all % rad_down_lin_tau)
897 if (f_confopts % has(
"RTTOV_dtau_test"))
then
898 call f_confopts % get_or_die(
"RTTOV_dtau_test", self % rttov_opts % rt_all % dtau_test)
902 if (f_confopts % has(
"RTTOV_fastem_version"))
then
903 call f_confopts % get_or_die(
"RTTOV_fastem_version", self % rttov_opts % rt_mw % fastem_version)
907 if (f_confopts % has(
"RTTOV_supply_foam_fraction"))
then
908 call f_confopts % get_or_die(
"RTTOV_supply_foam_fraction", self % rttov_opts % rt_mw % supply_foam_fraction)
912 if (f_confopts % has(
"RTTOV_clw_data"))
then
913 call f_confopts % get_or_die(
"RTTOV_clw_data", self % rttov_opts % rt_mw % clw_data)
917 if (f_confopts % has(
"RTTOV_clw_scheme"))
then
918 call f_confopts % get_or_die(
"RTTOV_clw_scheme", self % rttov_opts % rt_mw % clw_scheme)
922 if (f_confopts % has(
"RTTOV_clw_calc_on_coef_lev"))
then
923 call f_confopts % get_or_die(
"RTTOV_clw_calc_on_coef_lev", self % rttov_opts % rt_mw % clw_calc_on_coef_lev)
927 if (f_confopts % has(
"RTTOV_clw_cloud_top"))
then
928 call f_confopts % get_or_die(
"RTTOV_clw_cloud_top", self % rttov_opts % rt_mw % clw_cloud_top)
932 if (f_confopts % has(
"RTTOV_apply_band_correction"))
then
933 call f_confopts % get_or_die(
"RTTOV_apply_band_correction", self % rttov_opts % rt_mw % apply_band_correction)
937 if (f_confopts % has(
"RTTOV_addinterp"))
then
938 call f_confopts % get_or_die(
"RTTOV_addinterp", self % rttov_opts % interpolation % addinterp)
942 if (f_confopts % has(
"RTTOV_interp_mode"))
then
943 call f_confopts % get_or_die(
"RTTOV_interp_mode", self % rttov_opts % interpolation % interp_mode)
947 if (f_confopts % has(
"RTTOV_lgradp"))
then
948 call f_confopts % get_or_die(
"RTTOV_lgradp", self % rttov_opts % interpolation % lgradp)
952 if (f_confopts % has(
"RTTOV_spacetop"))
then
953 call f_confopts % get_or_die(
"RTTOV_spacetop", self % rttov_opts % interpolation % spacetop)
957 if (f_confopts % has(
"RTTOV_reg_limit_extrap"))
then
958 call f_confopts % get_or_die(
"RTTOV_reg_limit_extrap", self % rttov_opts % interpolation % reg_limit_extrap)
961 if (f_confopts % has(
"RTTOV_fix_hgpl"))
then
962 call f_confopts % get_or_die(
"RTTOV_fix_hgpl", self % rttov_opts % config % fix_hgpl)
965 if (f_confopts % has(
"RTTOV_verbose"))
then
966 call f_confopts % get_or_die(
"RTTOV_verbose", self % rttov_opts % config % verbose)
969 if (f_confopts % has(
"RTTOV_do_checkinput"))
then
970 call f_confopts % get_or_die(
"RTTOV_do_checkinput", self % rttov_opts % config % do_checkinput)
973 if (f_confopts % has(
"RTTOV_apply_reg_limits"))
then
974 call f_confopts % get_or_die(
"RTTOV_apply_reg_limits", self % rttov_opts % config % apply_reg_limits)
978 if (f_confopts % has(
"RTTOV_solar_sea_brdf_model"))
then
979 call f_confopts % get_or_die(
"RTTOV_solar_sea_brdf_model", self % rttov_opts % rt_ir % solar_sea_brdf_model)
983 if (f_confopts % has(
"RTTOV_ir_sea_emis_model"))
then
984 call f_confopts % get_or_die(
"RTTOV_ir_sea_emis_model", self % rttov_opts % rt_ir % ir_sea_emis_model)
988 if (f_confopts % has(
"RTTOV_addsolar"))
then
989 call f_confopts % get_or_die(
"RTTOV_addsolar", self % rttov_opts % rt_ir % addsolar)
993 if (f_confopts % has(
"RTTOV_rayleigh_single_scatt"))
then
994 call f_confopts % get_or_die(
"RTTOV_rayleigh_single_scatt", self % rttov_opts % rt_ir % rayleigh_single_scatt)
998 if (f_confopts % has(
"RTTOV_do_nlte_correction"))
then
999 call f_confopts % get_or_die(
"RTTOV_do_nlte_correction", self % rttov_opts % rt_ir % do_nlte_correction)
1003 if (f_confopts % has(
"RTTOV_addaerosl"))
then
1004 call f_confopts % get_or_die(
"RTTOV_addaerosl", self % rttov_opts % rt_ir % addaerosl)
1008 if (f_confopts % has(
"RTTOV_user_aer_opt_param"))
then
1009 call f_confopts % get_or_die(
"RTTOV_user_aer_opt_param", self % rttov_opts % rt_ir % user_aer_opt_param)
1013 if (f_confopts % has(
"RTTOV_addclouds"))
then
1014 call f_confopts % get_or_die(
"RTTOV_addclouds", self % rttov_opts % rt_ir % addclouds)
1018 if (f_confopts % has(
"RTTOV_user_cld_opt_param"))
then
1019 call f_confopts % get_or_die(
"RTTOV_", self % rttov_opts % rt_ir % user_cld_opt_param)
1023 if (f_confopts % has(
"RTTOV_grid_box_avg_cloud"))
then
1024 call f_confopts % get_or_die(
"RTTOV_grid_box_avg_cloud", self % rttov_opts % rt_ir % grid_box_avg_cloud)
1029 if (f_confopts % has(
"RTTOV_cldstr_threshold"))
then
1030 call f_confopts % get_or_die(
"RTTOV_cldstr_threshold", self % rttov_opts % rt_ir % cldstr_threshold)
1034 if (f_confopts % has(
"RTTOV_cldstr_simple"))
then
1035 call f_confopts % get_or_die(
"RTTOV_cldstr_simple", self % rttov_opts % rt_ir % cldstr_simple)
1039 if (f_confopts % has(
"RTTOV_cldstr_low_cloud_top"))
then
1040 call f_confopts % get_or_die(
"RTTOV_cldstr_low_cloud_top", self % rttov_opts % rt_ir % cldstr_low_cloud_top)
1044 if (f_confopts % has(
"RTTOV_ir_scatt_model"))
then
1045 call f_confopts % get_or_die(
"RTTOV_ir_scatt_model", self % rttov_opts % rt_ir % ir_scatt_model)
1049 if (f_confopts % has(
"RTTOV_vis_scatt_model"))
then
1050 call f_confopts % get_or_die(
"RTTOV_vis_scatt_model", self % rttov_opts % rt_ir % vis_scatt_model)
1054 if (f_confopts % has(
"RTTOV_dom_nstreams"))
then
1055 call f_confopts % get_or_die(
"RTTOV_dom_nstreams", self % rttov_opts % rt_ir % dom_nstreams)
1059 if (f_confopts % has(
"RTTOV_dom_accuracy"))
then
1060 call f_confopts % get_or_die(
"RTTOV_dom_accuracy", self % rttov_opts % rt_ir % dom_accuracy)
1064 if (f_confopts % has(
"RTTOV_dom_opdep_threshold"))
then
1065 call f_confopts % get_or_die(
"RTTOV_dom_opdep_threshold", self % rttov_opts % rt_ir % dom_opdep_threshold)
1069 if (f_confopts % has(
"RTTOV_ozone_data"))
then
1070 call f_confopts % get_or_die(
"RTTOV_ozone_data", self % rttov_opts % rt_ir % ozone_data)
1073 if (f_confopts % has(
"RTTOV_co2_data"))
then
1074 call f_confopts % get_or_die(
"RTTOV_co2_data", self % rttov_opts % rt_ir % co2_data)
1078 if (f_confopts % has(
"RTTOV_n2o_data"))
then
1079 call f_confopts % get_or_die(
"RTTOV_n2o_data", self % rttov_opts % rt_ir % n2o_data)
1083 if (f_confopts % has(
"RTTOV_co_data"))
then
1084 call f_confopts % get_or_die(
"RTTOV_co_data", self % rttov_opts % rt_ir % co_data)
1088 if (f_confopts % has(
"RTTOV_ch4_data"))
then
1089 call f_confopts % get_or_die(
"RTTOV_ch4_data", self % rttov_opts % rt_ir % ch4_data)
1093 if (f_confopts % has(
"RTTOV_so2_data"))
then
1094 call f_confopts % get_or_die(
"RTTOV_so2_data", self % rttov_opts % rt_ir % so2_data)
1106 type(fckit_configuration),
intent(in) :: f_confOpts
1107 integer,
intent(in) :: asw
1109 character(len=255) :: coef_filename
1110 character(len=4) :: coef_ext
1113 include
'rttov_read_coefs.interface'
1123 call self % set_options(f_confopts)
1128 allocate(self % rttov_coef_array(self % nSensors))
1130 do i_inst = 1, self%nSensors
1132 trim(self % COEFFICIENT_PATH) //
'rtcoef_' // trim(self%SENSOR_ID(i_inst)) // trim(coef_ext)
1135 self % rttov_coef_array(i_inst), &
1136 self % rttov_opts, &
1137 file_coef = coef_filename)
1140 write(*,*)
'fatal error reading coefficients'
1142 write(*,*)
'successfully read' // coef_filename
1147 self % rttov_is_setup =.true.
1149 deallocate(self % rttov_coef_array)
1150 self%rttov_is_setup =.false.
1159 integer,
intent(in) :: n
1160 character(len=*),
intent(out) :: varname
1162 character(len=6) :: chan
1164 write(chan,
'(I0)') n
1165 varname =
'brightness_temperature_' // trim(chan)
1170 subroutine alloc_rttov(self, errorstatus, conf, nprofiles, nchannels, nlevels, init, asw)
1176 integer,
intent(out) :: errorstatus
1177 integer,
intent(in) :: asw
1178 logical,
optional,
intent(in) :: init
1179 integer ,
intent(in) :: nchannels
1180 integer ,
intent(in) :: nprofiles
1181 integer ,
intent(in) :: nlevels
1184 integer :: asw_direct, asw_k
1186 integer,
save :: called_from
1188 include
'rttov_alloc_direct.interface'
1189 include
'rttov_alloc_k.interface'
1203 if (
present(init))
then
1209 if(asw_direct /= -1 .and. called_from == 1)
then
1211 call rttov_alloc_direct( &
1218 conf % rttov_opts, &
1220 conf % rttov_coef_array(1), &
1221 self % transmission, &
1223 calcemis = self % calcemis, &
1224 emissivity = self % emissivity, &
1227 if (errorstatus /= errorstatus_success)
then
1228 write(
message,
'(A, I6)')
'after rttov_alloc_direct error = ', errorstatus
1234 if (asw_k /= -1 .and. called_from == 2)
then
1236 call rttov_alloc_k( &
1243 conf % rttov_opts, &
1245 self % profiles_k, &
1246 conf % rttov_coef_array(1), &
1247 self % transmission, &
1248 self % transmission_k, &
1250 self % radiance_k, &
1251 calcemis = self % calcemis, &
1252 emissivity = self % emissivity, &
1253 emissivity_k = self % emissivity_k, &
1256 if (errorstatus /= errorstatus_success)
then
1257 write(
message,
'(A, I6)')
'after rttov_alloc_k error = ', errorstatus
1262 if ( asw /= 0 )
then
1263 self % calcemis = .false.
1264 self % emissivity % emis_in = -1.0_kind_real
1265 self % emissivity % emis_out = -1.0_kind_real
1266 self % profiles(:) % skin % surftype = -1_jpim
1279 integer,
intent(in) :: nprofiles, nchannels
1280 type(c_ptr),
value,
intent(in) :: obss
1281 integer(c_int),
intent(in) :: channels(:)
1282 logical,
intent(inout) :: skip_profiles(:)
1284 integer :: jprofile, jchannel
1285 character(len=MAXVARLEN) :: varname
1286 real(kind_real) :: obsval(nprofiles,nchannels)
1297 do jchannel = 1, nchannels
1299 call obsspace_get_db(obss,
"ObsValue", varname, obsval(:,jchannel))
1305 do jprofile = 1, nprofiles
1306 skip_profiles(jprofile) = all(obsval(jprofile,:) ==
missing) .or. all(obsval(jprofile,:) > 400)
1317 integer :: prof, ichan
1319 self % emissivity(:) % emis_in = -1.0_kind_real
1320 self % emissivity(:) % emis_out = -1.0_kind_real
1321 self % calcemis(:) = .false.
1325 if (
conf % rttov_coef_array(1) % coef % id_sensor == sensor_id_mw)
then
1327 prof = self % chanprof(ichan)%prof
1328 if (self % profiles(prof) % skin % surftype == surftype_sea)
then
1330 self % emissivity(ichan:ichan +
nchan_inst - 1) % emis_in = 0.0_kind_real
1331 self % calcemis(ichan:ichan +
nchan_inst - 1) = .true.
1336 if (self % profiles(prof) % skin % surftype == surftype_land)
then
1339 self % emissivity(ichan:ichan +
nchan_inst - 1) % emis_in = 0.95_kind_real
1340 elseif (self % profiles(prof) % skin % surftype == surftype_seaice)
then
1343 self % emissivity(ichan:ichan +
nchan_inst - 1) % emis_in = 0.92_kind_real
1348 elseif (
conf % rttov_coef_array(1) % coef % id_sensor == sensor_id_ir .or. &
1349 conf % rttov_coef_array(1) % coef % id_sensor == sensor_id_hi)
then
1351 do ichan = 1,
size (self % chanprof(:)),
nchan_inst
1352 prof = self % chanprof(ichan)%prof
1353 if (self % profiles(prof) % skin % surftype == surftype_sea)
then
1355 self % emissivity(ichan:ichan +
nchan_inst - 1) % emis_in = 0.0_kind_real
1356 self % calcemis(ichan:ichan +
nchan_inst - 1) = .true.
1360 if (self % profiles(prof) % skin % surftype == surftype_land)
then
1361 self % emissivity(ichan:ichan +
nchan_inst - 1) % emis_in = 0.95_kind_real
1362 elseif (self % profiles(prof) % skin % surftype == surftype_seaice)
then
1364 self % emissivity(ichan:ichan +
nchan_inst - 1) % emis_in = 0.92_kind_real
1376 character(8),
intent(in) :: default_opts_set
1378 write(
message,
'(A, A)')
'Setting RTTOV default options to ', default_opts_set
1381 select case (trim(default_opts_set))
1383 self % rttov_opts % rt_all % addrefrac = .false.
1384 self % rttov_opts % rt_all % switchrad = .false.
1385 self % rttov_opts % rt_all % use_q2m = .true.
1386 self % rttov_opts % rt_all % do_lambertian = .false.
1387 self % rttov_opts % rt_all % lambertian_fixed_angle = .true.
1388 self % rttov_opts % rt_all % plane_parallel = .false.
1389 self % rttov_opts % rt_all % rad_down_lin_tau = .true.
1390 self % rttov_opts % rt_all % dtau_test = .true.
1392 self % rttov_opts % rt_ir % solar_sea_brdf_model = 1
1393 self % rttov_opts % rt_ir % ir_sea_emis_model = 2
1394 self % rttov_opts % rt_ir % addsolar = .false.
1395 self % rttov_opts % rt_ir % rayleigh_single_scatt = .true.
1396 self % rttov_opts % rt_ir % do_nlte_correction = .false.
1397 self % rttov_opts % rt_ir % addaerosl = .false.
1398 self % rttov_opts % rt_ir % user_aer_opt_param = .false.
1399 self % rttov_opts % rt_ir % addclouds = .false.
1400 self % rttov_opts % rt_ir % user_cld_opt_param = .false.
1401 self % rttov_opts % rt_ir % grid_box_avg_cloud = .false.
1403 self % rttov_opts % rt_ir % cldstr_threshold = -1.0_kind_real
1404 self % rttov_opts % rt_ir % cldstr_simple = .false.
1405 self % rttov_opts % rt_ir % cldstr_low_cloud_top = 750._kind_real
1406 self % rttov_opts % rt_ir % ir_scatt_model = ir_scatt_chou
1407 self % rttov_opts % rt_ir % vis_scatt_model = vis_scatt_dom
1408 self % rttov_opts % rt_ir % dom_nstreams = 8
1409 self % rttov_opts % rt_ir % dom_accuracy = 0._kind_real
1410 self % rttov_opts % rt_ir % dom_opdep_threshold = 0._kind_real
1412 self % rttov_opts % rt_ir % ozone_data = .false.
1413 self % rttov_opts % rt_ir % co2_data = .false.
1414 self % rttov_opts % rt_ir % n2o_data = .false.
1415 self % rttov_opts % rt_ir % co_data = .false.
1416 self % rttov_opts % rt_ir % ch4_data = .false.
1417 self % rttov_opts % rt_ir % so2_data = .false.
1419 self % rttov_opts % rt_ir % pc % addpc = .false.
1420 self % rttov_opts % rt_ir % pc % ipcbnd = -1
1421 self % rttov_opts % rt_ir % pc % ipcreg = -1
1422 self % rttov_opts % rt_ir % pc % npcscores = -1
1424 self % rttov_opts % rt_ir % pc % addradrec = .false.
1427 self % rttov_opts % rt_mw % fastem_version = 6
1428 self % rttov_opts % rt_mw % supply_foam_fraction = .false.
1429 self % rttov_opts % rt_mw % clw_data = .false.
1430 self % rttov_opts % rt_mw % clw_scheme = 1
1431 self % rttov_opts % rt_mw % clw_calc_on_coef_lev = .true.
1432 self % rttov_opts % rt_mw % clw_cloud_top = 322
1433 self % rttov_opts % rt_mw % apply_band_correction = .true.
1435 self % rttov_opts % interpolation % addinterp = .false.
1436 self % rttov_opts % interpolation % interp_mode = interp_rochon
1437 self % rttov_opts % interpolation % lgradp = .false.
1438 self % rttov_opts % interpolation % spacetop = .true.
1439 self % rttov_opts % interpolation % reg_limit_extrap = .false.
1442 self % rttov_opts % htfrtc_opts % htfrtc = .false.
1443 self % rttov_opts % htfrtc_opts % n_pc_in = -1
1444 self % rttov_opts % htfrtc_opts % reconstruct = .false.
1445 self % rttov_opts % htfrtc_opts % simple_cloud = .false.
1446 self % rttov_opts % htfrtc_opts % overcast = .false.
1449 self % rttov_opts % config % apply_reg_limits = .true.
1450 self % rttov_opts % config % fix_hgpl = .false.
1451 self % rttov_opts % config % verbose = .false.
1452 self % rttov_opts % config % do_checkinput = .false.
1456 self % rttov_opts % rt_all % rad_down_lin_tau = .true.
1457 self % rttov_opts % rt_all % dtau_test = .true.
1459 if(trim(default_opts_set) ==
'OPS')
then
1460 self % rttov_opts % rt_all % addrefrac = .false.
1462 self % rttov_opts % rt_all % addrefrac = .true.
1465 self % rttov_opts % rt_all % switchrad = .true.
1466 if(trim(default_opts_set) ==
'OPS')
then
1467 self % rttov_opts % rt_all % use_q2m = .false.
1469 self % rttov_opts % rt_all % do_lambertian = .false.
1472 self % rttov_opts % interpolation % addinterp = .true.
1473 self % rttov_opts % interpolation % interp_mode = 4
1475 if(trim(default_opts_set) ==
'OPS')
then
1476 self % rttov_opts % interpolation % spacetop = .false.
1477 self % rttov_opts % interpolation % reg_limit_extrap = .false.
1479 self % rttov_opts % interpolation % reg_limit_extrap = .true.
1484 self % rttov_opts % rt_ir % ir_sea_emis_model = 1
1489 self % rttov_opts % rt_ir % grid_box_avg_cloud = .true.
1491 self % rttov_opts % rt_ir % ozone_data = .true.
1492 self % rttov_opts % rt_ir % co2_data = .false.
1493 self % rttov_opts % rt_ir % n2o_data = .false.
1494 self % rttov_opts % rt_ir % ch4_data = .false.
1495 self % rttov_opts % rt_ir % co_data = .false.
1496 self % rttov_opts % rt_ir % so2_data = .false.
1500 self % rttov_opts % rt_mw % clw_calc_on_coef_lev = .true.
1501 self % rttov_opts % rt_mw % clw_data = .true.
1502 if(trim(default_opts_set) ==
'OPS')
then
1503 self % rttov_opts % rt_mw % fastem_version = 2
1518 self % rttov_opts % rt_ir % addsolar = .false.
1519 self % rttov_opts % interpolation % addinterp = .true.
1520 self % rttov_opts % interpolation % interp_mode = 4
1521 self % rttov_opts % interpolation % reg_limit_extrap = .true.
1522 self % rttov_opts % rt_all % addrefrac = .true.
1523 self % rttov_opts % rt_all % switchrad = .true.
1524 self % rttov_opts % rt_all % dtau_test = .false.
1525 self % rttov_opts % rt_ir % addclouds = .false.
1526 self % rttov_opts % rt_ir % addaerosl = .false.
1528 self % rttov_opts % rt_ir % ozone_data = .false.
1529 self % rttov_opts % rt_ir % co2_data = .false.
1530 self % rttov_opts % rt_ir % n2o_data = .false.
1531 self % rttov_opts % rt_ir % ch4_data = .false.
1532 self % rttov_opts % rt_ir % co_data = .false.
1533 self % rttov_opts % rt_ir % so2_data = .false.
1534 self % rttov_opts % rt_mw % clw_data = .false.
1536 self % rttov_opts % config % verbose = .true.
1537 self % rttov_opts % config % apply_reg_limits = .true.
1538 self % rttov_opts % config % do_checkinput = .false.
1539 self % rttov_opts % config % fix_hgpl = .false.
1548 type(rttov_chanprof),
intent(in) :: chanprof(:)
1551 integer :: jvar, chan, prof, ichan
1552 integer :: nlayers, nchanprof, nlevels, nprofiles
1553 real(kind_real),
allocatable :: od_level(:), wfunc(:)
1555 include
'rttov_calc_weighting_fn.interface'
1557 allocate(od_level(
size(rtprof % transmission%tau_levels(:,1))))
1558 allocate(wfunc(
size(rtprof % transmission%tau_levels(:,1))))
1562 nchanprof =
size(chanprof)
1563 nlevels =
size(rtprof % profiles(1) % p)
1564 nprofiles = maxval(chanprof(:)%prof)
1566 do jvar = 1, hofxdiags%nvar
1567 if (len(trim(hofxdiags%variables(jvar))) < 1) cycle
1582 nlayers = nlevels - 1
1583 hofxdiags%geovals(jvar)%nval = nlayers
1584 allocate(hofxdiags%geovals(jvar)%vals(hofxdiags%geovals(jvar)%nval,nprofiles))
1585 hofxdiags%geovals(jvar)%vals =
missing
1587 do ichan = 1, nchanprof
1588 chan = chanprof(ichan)%chan
1589 prof = chanprof(ichan)%prof
1594 od_level(:) = log(rtprof % transmission%tau_levels(:,chan))
1595 hofxdiags%geovals(jvar)%vals(:,prof) = od_level(1:nlevels-1) - od_level(2:nlevels)
1597 hofxdiags%geovals(jvar)%vals(:,prof) = rtprof % transmission % tau_levels(1:nlevels-1,chan) - rtprof % transmission%tau_levels(2:,chan)
1599 od_level(:) = log(rtprof % transmission%tau_levels(:,chan))
1600 call rttov_calc_weighting_fn(
rttov_errorstatus, rtprof % profiles(prof)%p, od_level(:), &
1601 hofxdiags%geovals(jvar)%vals(:,prof))
1613 hofxdiags%geovals(jvar)%nval = 1
1614 allocate(hofxdiags%geovals(jvar)%vals(hofxdiags%geovals(jvar)%nval,nprofiles))
1615 hofxdiags%geovals(jvar)%vals =
missing
1617 do ichan = 1, nchanprof
1618 chan = chanprof(ichan)%chan
1619 prof = chanprof(ichan)%prof
1623 hofxdiags%geovals(jvar)%vals(1,prof) = rtprof % radiance % total(ichan)
1625 hofxdiags%geovals(jvar)%vals(1,prof) = rtprof % radiance % bt_clear(ichan)
1627 hofxdiags%geovals(jvar)%vals(1,prof) = rtprof % radiance % bt(ichan)
1629 call rttov_calc_weighting_fn(
rttov_errorstatus, rtprof % profiles(prof)%p, od_level(:), &
1631 hofxdiags%geovals(jvar)%vals(1,prof) = maxloc(wfunc(:), dim=1)
1637 write(
message,*)
'ufo_radiancerttov_simobs: //&
1638 & ObsDiagnostic is unsupported, ', &
1639 & hofxdiags%variables(jvar)
1648 nlayers = nlevels - 1
1649 hofxdiags%geovals(jvar)%nval = nlayers
1650 allocate(hofxdiags%geovals(jvar)%vals(hofxdiags%geovals(jvar)%nval,nprofiles))
1651 hofxdiags%geovals(jvar)%vals =
missing
1653 do ichan = 1, nchanprof
1654 chan = chanprof(ichan)%chan
1655 prof = chanprof(ichan)%prof
1659 hofxdiags%geovals(jvar)%vals(:,prof) = &
1660 rtprof % profiles_k(ichan) % t(:)
1662 hofxdiags%geovals(jvar)%vals(:,prof) = &
1663 rtprof % profiles_k(ichan) % q(:)
1665 hofxdiags%geovals(jvar)%vals(:,prof) = &
1666 rtprof % profiles_k(ichan) % clw(:)
1672 hofxdiags%geovals(jvar)%nval = 1
1673 allocate(hofxdiags%geovals(jvar)%vals(hofxdiags%geovals(jvar)%nval,nprofiles))
1674 hofxdiags%geovals(jvar)%vals =
missing
1676 do ichan = 1, nchanprof
1677 chan = chanprof(ichan)%chan
1678 prof = chanprof(ichan)%prof
1682 hofxdiags%geovals(jvar)%vals(1,prof) = &
1683 rtprof % profiles_k(ichan) % skin % t
1685 hofxdiags%geovals(jvar)%vals(1,prof) = &
1686 rtprof % profiles_k(ichan) % s2m % t
1688 hofxdiags%geovals(jvar)%vals(1,prof) = &
1689 rtprof % profiles_k(ichan) % s2m % p
1691 hofxdiags%geovals(jvar)%vals(1,prof) = &
1692 rtprof % profiles_k(ichan) % s2m % q
1694 hofxdiags%geovals(jvar)%vals(1,prof) = &
1695 rtprof % profiles_k(ichan) % s2m % u
1697 hofxdiags%geovals(jvar)%vals(1,prof) = &
1698 rtprof % profiles_k(ichan) % s2m % v
1700 hofxdiags%geovals(jvar)%vals(1,prof) = &
1701 rtprof % emissivity_k(ichan) % emis_in
1707 write(
message,*)
'ufo_radiancerttov_simobs: //&
1708 & ObsDiagnostic is unsupported, ', &
1709 & hofxdiags%variables(jvar)
1713 write(
message,*)
'ufo_radiancerttov_simobs: //&
1714 & ObsDiagnostic is unsupported, ', &
1715 & hofxdiags%variables(jvar)
1721 deallocate(od_level,wfunc)
1729 logical,
intent(out) :: jacobian_needed
1730 character(10),
parameter :: jacobianstr =
"_jacobian_"
1732 integer :: str_pos(4)
1733 character(len=MAXVARLEN) :: varstr
1735 character(len=max_string) :: err_msg
1737 jacobian_needed = .false.
1739 if(hofxdiags%nvar > 0)
then
1746 do jvar = 1, hofxdiags%nvar
1747 varstr = hofxdiags%variables(jvar)
1749 str_pos(4) = len_trim(varstr)
1750 if (str_pos(4) < 1) cycle
1751 str_pos(3) = index(varstr,
"_",back=.true.)
1752 read(varstr(str_pos(3)+1:str_pos(4)),*, err=999)
ch_diags(jvar)
1753 999 str_pos(1) = index(varstr,jacobianstr) - 1
1754 if (str_pos(1) == 0)
then
1755 write(err_msg,*)
'parse_hofxdiags: _jacobian_ must be // &
1756 & preceded by dependent variable in config: ', &
1757 & hofxdiags%variables(jvar)
1758 call abor1_ftn(err_msg)
1759 else if (str_pos(1) > 0)
then
1762 str_pos(2) = str_pos(1) + len(jacobianstr) + 1
1763 jacobian_needed = .true.
1764 str_pos(4) = str_pos(3) - str_pos(2)
1765 xstr_diags(jvar)(1:str_pos(4)) = varstr(str_pos(2):str_pos(3)-1)
1771 ystr_diags(jvar)(1:str_pos(3)-1) = varstr(1:str_pos(3)-1)
1816 integer,
intent(in) :: output_type
1817 real(kind_real),
intent(in) :: p(:)
1818 real(kind_real),
intent(in) :: t(:)
1819 real(kind_real),
intent(in) :: qtotal(:)
1820 real(kind_real),
intent(out) :: q(size(qtotal))
1821 real(kind_real),
intent(out) :: ql(size(qtotal))
1822 real(kind_real),
intent(out) :: qi(size(qtotal))
1823 logical,
intent(in) :: UseQtSplitRain
1827 real(kind_real),
parameter :: lower_rh = 0.95
1828 real(kind_real),
parameter :: upper_rh = 1.05
1829 real(kind_real),
parameter :: Split_Factor = 0.5
1830 real(kind_real),
parameter :: MinTempQl = 233.15
1831 real(kind_real) :: qsaturated(size(qtotal))
1832 real(kind_real) :: RH_qtotal(size(qtotal))
1833 real(kind_real) :: qnv(size(qtotal))
1834 real(kind_real) :: qc(size(qtotal))
1835 real(kind_real) :: V1(size(qtotal))
1836 real(kind_real) :: V2(size(qtotal))
1837 real(kind_real) :: V1zero
1838 real(kind_real) :: V2zero
1839 real(kind_real) :: W(size(qtotal))
1840 real(kind_real) :: Y1,Y2,Y3,Y4
1841 real(kind_real) :: IntConst
1842 real(kind_real) :: Aconst
1843 real(kind_real) :: Bconst
1844 real(kind_real) :: Cconst
1845 real(kind_real) :: Dconst
1846 real(kind_real) :: Denom
1847 real(kind_real) :: SmallValue
1848 real(kind_real) :: LF(size(qtotal))
1849 character(len=*),
parameter :: RoutineName =
"Ops_SatRad_Qsplit"
1851 real(kind_real) :: QsplitRainParamA
1852 real(kind_real) :: QsplitRainParamB
1853 real(kind_real) :: QsplitRainParamC
1856 qsplitrainparama = 0.15_kind_real
1857 qsplitrainparamb = 0.09_kind_real
1858 qsplitrainparamc = 50.0_kind_real
1867 smallvalue = 1.0_kind_real / 8.5_kind_real
1868 denom = smallvalue * (upper_rh - lower_rh)
1871 rh_qtotal(:) = min(qtotal(:) / qsaturated(:), 2.0_kind_real)
1873 v1(:) = (rh_qtotal(:) - lower_rh) / denom
1874 v2(:) = (rh_qtotal(:) - upper_rh) / denom
1881 aconst = (y2 - y1) / 2.0_kind_real
1882 bconst = -(y4 - y3) / 2.0_kind_real
1883 cconst = (y2 + y1) / 2.0_kind_real
1884 dconst = -(y4 + y3) / 2.0_kind_real
1888 where (t(:) -
zerodegc >= -0.01_kind_real)
1891 lf(:) = 1.0_kind_real
1895 where (t(:) <= mintempql)
1898 lf(:) = 0.0_kind_real
1902 where (t(:) > mintempql .and. t(:) -
zerodegc < -0.01_kind_real)
1905 lf(:) = sqrt(-1.0_kind_real * log(-0.025_kind_real * (t(:) -
zerodegc)) / 70.0_kind_real)
1912 v1zero = -1.0_kind_real * lower_rh / denom
1913 v2zero = -1.0_kind_real * upper_rh / denom
1914 intconst = -(aconst * denom * log(cosh(v1zero)) + bconst * denom * log(cosh(v2zero)))
1915 w(:) = aconst * denom * log(cosh(v1(:))) + bconst * denom * log(cosh(v2(:))) + &
1916 (cconst + dconst) * rh_qtotal(:) + intconst
1921 if (useqtsplitrain)
then
1928 do i = 1,
size(qtotal)
1930 q(i) = max(w(i) * qsaturated(i),
min_q)
1931 qnv(i) = max(qtotal(i) - q(i), 0.0_kind_real)
1935 qc(i) = max(qsplitrainparama * (qsplitrainparamb - (qsplitrainparamb / ((qsplitrainparamc * qnv(i)) + 1))), 0.0_kind_real)
1939 ql(i) = max(lf(i) * qc(i), 0.0_kind_real)
1940 qi(i) = max((1.0_kind_real - lf(i)) * (qc(i)), 0.0_kind_real)
1945 do i = 1,
size(qtotal)
1947 q(i) = max(w(i) * qsaturated(i),
min_q)
1948 ql(i) = max(lf(i) * (qtotal(i) - q(i)), 0.0_kind_real)
1949 qi(i) = max((1.0_kind_real - lf(i)) * (qtotal(i) - q(i)), 0.0_kind_real)
1958 if (output_type /= 1)
then
1963 q(:) = aconst * tanh(v1(:)) + cconst + bconst * tanh(v2(:)) + dconst
1965 if (useqtsplitrain)
then
1967 ql(:) = lf(:) * qsplitrainparama * qsplitrainparamb * qsplitrainparamc * (1.0_kind_real - q(:)) / &
1968 ((qsplitrainparamc * qnv(:)) + 1.0_kind_real) ** 2
1969 qi(:) = (1.0_kind_real - lf(:)) * qsplitrainparama * qsplitrainparamb * qsplitrainparamc * (1.0_kind_real - q(:)) / &
1970 ((qsplitrainparamc * qnv(:)) + 1.0_kind_real) ** 2
1974 ql(:) = lf(:) * (1.0_kind_real - q(:))
1975 qi(:) = (1.0_kind_real - lf(:)) * (1.0_kind_real - q(:))