10 use fckit_log_module,
only : fckit_log
13 use oops_variables_mod
65 real(kind_real),
intent(out) :: prof_x(:)
68 character(len=*),
parameter :: routinename =
"ufo_rttovonedvarcheck_GeoVaLs2ProfVec"
69 character(len=max_string) :: varname
74 real(kind_real),
allocatable :: humidity_total(:)
75 real(kind_real),
allocatable :: emiss_pc(:)
76 real(kind_real) :: u, v
81 nlevels = profindex % nlevels
94 if (profindex % t(1) > 0)
then
96 prof_x(profindex % t(1):profindex % t(2)) = geoval%vals(nlevels:1:-1, 1)
101 if (profindex % q(1) > 0)
then
103 prof_x(profindex % q(1):profindex % q(2)) = &
104 log(geoval%vals(nlevels:1:-1, 1) * 1000.0_kind_real)
111 if (profindex % qt(1) > 0)
then
112 allocate(humidity_total(nlevels))
113 humidity_total(:) =
zero
117 humidity_total(:) = humidity_total(:) + geoval%vals(nlevels:1:-1, 1)
119 humidity_total(:) = humidity_total(:) + geoval%vals(nlevels:1:-1, 1)
121 humidity_total(:) = humidity_total(:) + geoval%vals(nlevels:1:-1, 1)
124 prof_x(profindex % qt(1):profindex % qt(2)) = log(humidity_total * 1000.0_kind_real)
126 deallocate(humidity_total)
134 if (profindex % t2 > 0)
then
136 prof_x(profindex % t2) = geoval%vals(1, 1)
141 if (profindex % q2 > 0)
then
143 prof_x(profindex % q2) = log(geoval%vals(1, 1) * 1000.0_kind_real)
147 if (profindex % pstar > 0)
then
149 prof_x(profindex % pstar) = geoval%vals(1, 1) / 100.0_kind_real
153 if (profindex % tstar > 0)
then
155 prof_x(profindex % tstar) = geoval%vals(1, 1)
173 if (profindex % windspeed > 0)
then
175 u = geoval % vals(1, 1)
177 v = geoval % vals(1, 1)
178 prof_x(profindex % windspeed) = sqrt(u ** 2 + v ** 2)
231 real(kind_real),
intent(in) :: prof_x(:)
232 logical,
intent(in) :: useqtsplitrain
235 character(len=*),
parameter :: routinename =
"ufo_rttovonedvarcheck_ProfVec2GeoVaLs"
236 character(len=max_string) :: varname
237 integer :: gv_index, i, ii
239 integer :: emisselement
241 real(kind_real),
allocatable :: pressure(:)
242 real(kind_real),
allocatable :: humidity_total(:)
243 real(kind_real),
allocatable :: q(:)
244 real(kind_real),
allocatable :: ql(:)
245 real(kind_real),
allocatable :: qi(:)
246 real(kind_real),
allocatable :: emiss_pc(:)
247 real(kind_real) :: u, v, windsp
251 nlevels = profindex % nlevels
264 if (profindex % t(1) > 0)
then
269 geovals%geovals(gv_index)%vals(nlevels:1:-1,1) = prof_x(profindex % t(1):profindex % t(2))
274 if (profindex % q(1) > 0)
then
279 geovals%geovals(gv_index)%vals(nlevels:1:-1,1) = exp(prof_x(profindex % q(1):profindex % q(2))) / &
287 if (profindex % qt(1) > 0)
then
288 nlevels = profindex % nlevels
289 allocate(pressure(nlevels))
290 allocate(humidity_total(nlevels))
292 allocate(ql(nlevels))
293 allocate(qi(nlevels))
296 humidity_total(nlevels:1:-1) = exp(prof_x(profindex % qt(1):profindex % qt(2))) / &
301 pressure(:) = geoval%vals(:, 1)
306 ob % background_T(:), &
318 geovals%geovals(gv_index)%vals(:,1) = q(:)
324 geovals%geovals(gv_index)%vals(:,1) = ql(:)
330 geovals%geovals(gv_index)%vals(:,1) = qi(:)
333 deallocate(humidity_total)
345 if (profindex % t2 > 0)
then
350 geovals%geovals(gv_index)%vals(1,1) = prof_x(profindex % t2)
355 if (profindex % q2 > 0)
then
360 geovals%geovals(gv_index)%vals(1,1) = exp(prof_x(profindex % q2)) / 1000.0_kind_real
364 if (profindex % pstar > 0)
then
369 geovals%geovals(gv_index)%vals(1,1) = prof_x(profindex % pstar) * 100.0_kind_real
373 if (profindex % tstar > 0)
then
378 geovals%geovals(gv_index)%vals(1,1) = prof_x(profindex % tstar)
394 if (profindex % windspeed > 0)
then
396 u = geoval % vals(1, 1)
398 v = geoval % vals(1, 1)
399 windsp = sqrt(u ** 2 + v ** 2)
403 if (windsp >
zero)
then
404 u = u * (prof_x(profindex % windspeed) / windsp)
405 v = v * (prof_x(profindex % windspeed) / windsp)
414 if (trim(
var_sfc_u10) == trim(geovals%variables(i))) gv_index = i
416 geovals%geovals(gv_index)%vals(1,1) = u
421 if (trim(
var_sfc_v10) == trim(geovals%variables(i))) gv_index = i
423 geovals%geovals(gv_index)%vals(1,1) = v
472 integer,
intent(in) :: surface_type
474 character(len=*),
parameter :: routinename =
"ufo_rttovonedvarcheck_check_geovals"
475 character(len=max_string) :: varname
477 integer :: gv_index, i
479 real(kind_real),
allocatable :: temperature(:)
480 real(kind_real),
allocatable :: pressure(:)
481 real(kind_real),
allocatable :: qsaturated(:)
482 real(kind_real),
allocatable :: humidity_total(:)
483 real(kind_real),
allocatable :: q(:)
484 real(kind_real),
allocatable :: ql(:)
485 real(kind_real),
allocatable :: qi(:)
486 real(kind_real) :: skin_t, pressure_2m, temperature_2m, newt
487 integer :: level_1000hpa, level_950hpa
489 write(
message, *) routinename,
" : started"
490 call fckit_log % debug(
message)
496 nlevels = profindex % nlevels
497 allocate(temperature(nlevels))
498 allocate(pressure(nlevels))
500 temperature(:) = geoval%vals(:, 1)
502 pressure(:) = geoval%vals(:, 1)
507 if (profindex % q(1) > 0 .or. profindex % qt(1) > 0)
then
509 allocate(qsaturated(nlevels))
512 varname = trim(
var_q)
514 q(:) = geoval%vals(:, 1)
517 if (self % UseRHwaterForQC)
then
530 where (q > qsaturated)
540 if (
cmp_strings(varname, geovals%variables(i))) gv_index = i
542 geovals%geovals(gv_index) % vals(:,1) = q(:)
545 deallocate(qsaturated)
548 if (profindex % q2 > 0)
then
550 allocate(qsaturated(1))
555 q(1) = geoval%vals(1, 1)
558 if (self % UseRHwaterForQC)
then
571 if (q(1) > qsaturated(1)) q(1) = qsaturated(1)
577 if (
cmp_strings(varname, geovals%variables(i))) gv_index = i
579 geovals%geovals(gv_index) % vals(1,1) = q(1)
582 deallocate(qsaturated)
589 if (profindex % qt(1) > 0)
then
591 allocate(humidity_total(nlevels))
593 allocate(ql(nlevels))
594 allocate(qi(nlevels))
596 humidity_total(:) = 0.0
599 humidity_total(:) = humidity_total(:) + geoval%vals(:, 1)
603 where (geoval%vals(:, 1) < 0.0) geoval%vals(:, 1) = 0.0
604 humidity_total(:) = humidity_total(:) + geoval%vals(:, 1)
614 self % UseQtsplitRain)
617 varname = trim(
var_q)
620 if (
cmp_strings(varname, geovals%variables(i))) gv_index = i
622 geovals%geovals(gv_index) % vals(:,1) = q(:)
628 if (
cmp_strings(varname, geovals%variables(i))) gv_index = i
630 geovals%geovals(gv_index) % vals(:,1) = ql(:)
636 if (
cmp_strings(varname, geovals%variables(i))) gv_index = i
638 geovals%geovals(gv_index)%vals(:,1) = qi(:)
640 deallocate(humidity_total)
652 if(surface_type /=
rtsea .and. self % UseColdSurfaceCheck)
then
656 skin_t = geoval%vals(1, 1)
660 pressure_2m = geoval%vals(1, 1)
664 temperature_2m = geoval%vals(1, 1)
666 if(skin_t < 271.4_kind_real .and. &
667 pressure_2m > 95000.0_kind_real)
then
669 level_1000hpa = minloc(abs(pressure - 100000.0_kind_real),dim=1)
670 level_950hpa = minloc(abs(pressure - 95000.0_kind_real),dim=1)
672 newt = temperature(level_950hpa)
673 if(pressure_2m > 100000.0_kind_real)
then
674 newt = max(newt, temperature(level_1000hpa))
676 newt = min(newt, 271.4_kind_real)
678 temperature(level_1000hpa) = max(temperature(level_1000hpa), newt)
679 temperature_2m = max(temperature_2m, newt)
680 skin_t = max(skin_t, newt)
687 if (
cmp_strings(varname, geovals%variables(i))) gv_index = i
689 geovals%geovals(gv_index) % vals(level_1000hpa,1) = temperature(level_1000hpa)
695 if (
cmp_strings(varname, geovals%variables(i))) gv_index = i
697 geovals%geovals(gv_index) % vals(1,1) = temperature_2m
703 if (
cmp_strings(varname, geovals%variables(i))) gv_index = i
705 geovals%geovals(gv_index) % vals(1,1) = skin_t
712 if (
allocated(temperature))
deallocate(temperature)
713 if (
allocated(pressure))
deallocate(pressure)
714 if (
allocated(qsaturated))
deallocate(qsaturated)
715 if (
allocated(humidity_total))
deallocate(humidity_total)
716 if (
allocated(q))
deallocate(q)
717 if (
allocated(ql))
deallocate(ql)
718 if (
allocated(qi))
deallocate(qi)
720 write(
message, *) routinename,
" : ended"
721 call fckit_log % debug(
message)
738 DeltaObs, r_matrix, &
744 real(kind_real),
intent(in) :: deltaprof(:)
745 real(kind_real),
intent(in) :: b_inv(:,:)
746 real(kind_real),
intent(in) :: deltaobs(:)
748 real(kind_real),
intent(out) :: jcost(3)
751 character(len=*),
parameter :: routinename =
"ufo_rttovonedvarcheck_CostFunction"
753 real(kind_real) :: jb, jo, jcurrent
754 real(kind_real),
allocatable :: rinvdeltay(:)
758 allocate(rinvdeltay, source=deltaobs)
760 y_size =
size(deltaobs)
762 call r_matrix % multiply_inverse_vector(deltaobs, rinvdeltay)
764 jo =
half * dot_product(deltaobs, rinvdeltay)
765 jb =
half * dot_product(deltaprof, (matmul(b_inv, deltaprof)))
768 jcost(1) = (jo + jb) *
two / real(y_size, kind_real)
769 jcost(2) = jb *
two / real(y_size, kind_real)
770 jcost(3) = jo *
two / real(y_size, kind_real)
772 write(
message,*)
"Jo, Jb, Jcurrent = ", jo, jb, jcost(1)
773 call fckit_log % debug(
message)
775 deallocate(rinvdeltay)
802 real(kind_real),
intent(inout) :: profile(:)
803 logical,
intent(out) :: outofrange
806 real(kind_real),
allocatable :: qsaturated(:)
807 real(kind_real),
allocatable :: scaled_qsaturated(:)
808 real(kind_real) :: q2_sat(1)
809 real(kind_real),
allocatable :: plevels_1dvar(:)
810 real(kind_real) :: pstar_pa(1)
811 real(kind_real),
allocatable :: temp(:)
812 real(kind_real) :: temp2(1)
813 real(kind_real) :: rtbase
815 integer :: toplevel_q
816 character(len=*),
parameter :: routinename =
"ufo_rttovonedvarcheck_CheckIteration"
818 character(len=max_string) :: varname
820 integer :: nlevels_1dvar
824 nlevels_1dvar = self % nlevels
825 allocate(temp(nlevels_1dvar))
835 if (profindex % t(1) > 0)
then
836 temp = profile(profindex % t(1):profindex % t(2))
844 temp = geoval%vals(nlevels_1dvar:1:-1, 1)
851 if (profindex % t2 > 0)
then
852 temp2 = profile(profindex % t2)
859 temp2 = geoval%vals(1, 1)
866 if (profindex % tstar > 0)
then
877 constrain:
if (.not. outofrange)
then
881 if (profindex % q(1) > 0)
then
882 nlevels_q = profindex % q(2) - profindex % q(1) + 1
883 else if (profindex % qt(1) > 0)
then
884 nlevels_q = profindex % qt(2) - profindex % qt(1) + 1
885 allocate (scaled_qsaturated(nlevels_q))
887 nlevels_q = nlevels_1dvar
889 toplevel_q = nlevels_1dvar - nlevels_q + 1
890 allocate (qsaturated(nlevels_q))
896 if (.not.
allocated(plevels_1dvar))
allocate(plevels_1dvar(nlevels_q))
898 plevels_1dvar(:) = geoval%vals(nlevels_1dvar:1:-1, 1)
908 if (profindex % q(1) > 0)
then
910 if (self % useRHwaterForQC)
then
913 plevels_1dvar(1:nlevels_q), &
916 call ops_qsat(qsaturated(1:nlevels_q), &
918 plevels_1dvar(1:nlevels_q), &
922 qsaturated(1:nlevels_q) = log(qsaturated(1:nlevels_q) * 1000.0_kind_real)
923 where (profile(profindex % q(1):profindex % q(2)) > qsaturated(1:nlevels_q))
924 profile(profindex % q(1):profindex % q(2)) = qsaturated(1:nlevels_q)
929 if (profindex % qt(1) > 0)
then
932 call ops_qsat (qsaturated(1:nlevels_q), &
934 plevels_1dvar(1:nlevels_q), &
939 scaled_qsaturated(1:nlevels_q) = log(
two * qsaturated(1:nlevels_q) * 1000.0_kind_real)
940 where (profile(profindex % qt(1):profindex % qt(2)) > scaled_qsaturated(1:nlevels_q))
941 profile(profindex % qt(1):profindex % qt(2)) = scaled_qsaturated(1:nlevels_q)
950 if (profindex % q2 > 0)
then
953 pstar_pa(1) = geoval%vals(1, 1)
954 if (self % useRHwaterForQC)
then
965 q2_sat(1) = log(q2_sat(1) * 1000.0_kind_real)
966 if (profile(profindex % q2) > q2_sat(1))
then
967 profile(profindex % q2) = q2_sat(1)
1033 if (
allocated(qsaturated))
deallocate(qsaturated)
1034 if (
allocated(scaled_qsaturated))
deallocate(scaled_qsaturated)
1035 if (
allocated(plevels_1dvar))
deallocate(plevels_1dvar)
1036 if (
allocated(temp))
deallocate(temp)
1056 nlevels_1dvar, & ! in
1064 integer,
intent(in) :: nlevels_1dvar
1065 logical,
intent(out) :: outofrange
1066 real(kind_real),
optional,
intent(out) :: outlwp
1069 real(kind_real) :: lwp
1070 real(kind_real) :: iwp
1071 real(kind_real) :: dp
1072 real(kind_real) :: meanql
1073 real(kind_real) :: meanqi
1075 integer :: nlevels_q, toplevel_q
1076 character(len=*),
parameter :: routinename =
"ufo_rttovonedvarcheck_CheckCloudyIteration"
1078 real(kind_real),
parameter :: maxlwp =
two
1079 real(kind_real),
parameter :: maxiwp = 3.0_kind_real
1080 real(kind_real) :: plevels_1dvar(nlevels_1dvar)
1082 real(kind_real) :: clw(nlevels_1dvar)
1083 real(kind_real) :: ciw(nlevels_1dvar)
1084 character(len=max_string) :: varname
1089 outofrange = .false.
1096 plevels_1dvar(:) = geoval%vals(:, 1)
1101 clw = geoval%vals(:, 1)
1106 ciw = geoval%vals(:, 1)
1109 if ( profindex % q(1) > 0 )
then
1110 nlevels_q = profindex % q(2) - profindex % q(1) + 1
1111 else if ( profindex % qt(1) > 0 )
then
1112 nlevels_q = profindex % qt(2) - profindex % qt(1) + 1
1113 else if ( profindex % ql(1) > 0 )
then
1114 nlevels_q = profindex % ql(2) - profindex % ql(1) + 1
1115 else if ( profindex % qi(1) > 0 )
then
1116 nlevels_q = profindex % qi(2) - profindex % qi(1) + 1
1118 nlevels_q = nlevels_1dvar
1120 toplevel_q = nlevels_1dvar - nlevels_q + 1
1125 if (any(ciw(:) >
zero) .or. &
1126 any(clw(:) >
zero))
then
1130 do i=1, nlevels_1dvar-1
1132 dp = plevels_1dvar(i) - plevels_1dvar(i+1)
1137 if (meanqi >
zero)
then
1138 iwp = iwp + dp * meanqi
1142 meanql =
half * (clw(i) + clw(i+1))
1143 if (meanql >
zero)
then
1144 lwp = lwp + dp * meanql
1155 if ((iwp > maxiwp) .or. (lwp > maxlwp))
then
1156 call fckit_log % debug(
"lwp or iwp exceeds thresholds")
1158 write(
message,*)
"lwp and iwp = ",lwp,iwp
1159 call fckit_log % debug(
message)
1161 call fckit_log % debug(
"lwp and iwp less than thresholds")
1162 write(
message,*)
"lwp and iwp = ",lwp,iwp
1163 call fckit_log % debug(
message)
1168 if (
present(outlwp)) outlwp = lwp
1180 guessprofile, backprofile, &
1181 diffprofile, binv, hmatrix)
1185 real(kind_real),
intent(in) :: yob(:)
1186 real(kind_real),
intent(in) :: hofx(:)
1187 integer,
intent(in) :: channels(:)
1188 real(kind_real),
intent(in) :: guessprofile(:)
1189 real(kind_real),
intent(in) :: backprofile(:)
1190 real(kind_real),
intent(in) :: diffprofile(:)
1191 real(kind_real),
intent(in) :: binv(:,:)
1192 real(kind_real),
intent(in) :: hmatrix(:,:)
1194 integer :: obs_size, profile_size, ii, jj
1195 character(len=12) :: chans_fmt, prof_fmt
1196 character(len=3) :: txt_nchans, txt_nprof
1197 character(len=10) :: int_fmt
1199 obs_size =
size(yob)
1200 write( unit=txt_nchans,fmt=
'(i3)' ) obs_size
1201 write( unit=chans_fmt,fmt=
'(a)' )
'(' // trim(txt_nchans) //
'E30.16)'
1202 write( unit=int_fmt,fmt=
'(a)' )
'(' // trim(txt_nchans) //
'I30)'
1204 profile_size =
size(guessprofile)
1205 write( unit=txt_nprof,fmt=
'(i3)' ) profile_size
1206 write( unit=prof_fmt,fmt=
'(a)' )
'(' // trim(txt_nprof) //
'E30.16)'
1208 write(*,*)
"Start print iter info"
1211 write(*,
"(2A30)")
"yob",
"hofx"
1213 write(*,
"(2E30.16)") yob(ii),hofx(ii)
1217 write(*,
"(3A30)")
"guessprofile",
"backprofile",
"diffprofile"
1218 do ii = 1, profile_size
1219 write(*,
"(3E30.16)") guessprofile(ii),backprofile(ii), diffprofile(ii)
1223 write(*,
"(2A30)")
"B inverse"
1224 do ii = 1, profile_size
1225 write(*,prof_fmt) binv(:,ii)
1229 write(*,
"(2A30)")
"hmatrix"
1230 write(*, int_fmt) channels(:)
1231 do ii = 1, profile_size
1232 write(*,chans_fmt) hmatrix(:,ii)
1235 write(*,*)
"Finished print iter info"
1245 type(oops_variables),
intent(in) :: retrieval_vars
1246 integer,
intent(in) :: nlevels
1247 integer(c_size_t),
intent(inout) :: ret_nlevs(:)
1249 character(MAXVARLEN),
allocatable :: varlist(:)
1250 character(MAXVARLEN) :: varname,
message
1251 integer :: i, ss, ee
1254 varlist = retrieval_vars % varlist()
1255 do i = 1,
size(varlist)
1256 ss = index(varlist(i),
"jacobian_", .false.) + 9
1257 ee = index(varlist(i),
"_", .true.) - 1
1258 varname = varlist(i)(ss:ee)
1259 if (trim(varname) == trim(
var_ts) .or. &
1260 trim(varname) == trim(
var_q) .or. &
1261 trim(varname) == trim(
var_clw) .or. &
1262 trim(varname) == trim(
var_cli))
then
1263 ret_nlevs(i) = nlevels
1264 else if (trim(varname) == trim(
var_sfc_t2m) .or. &
1272 write(
message, *) trim(varlist(i)),
" not setup for retrieval yet: aborting"
real(kind_real), parameter, public min_q
real(kind_real), parameter, public one
real(kind_real), parameter, public grav
real(kind_real), parameter, public t0c
real(kind_real), parameter, public zero
real(kind_real), parameter, public two
real(kind_real), parameter, public half
subroutine, public ufo_geovals_get_var(self, varname, geoval)
Fortran module constants used throughout the rttovonedvarcheck filter.
integer, parameter, public rtsea
integer for sea surface type
real(kind_real), parameter, public maxtemperature
Maximum temperature ( K )
real(kind_real), parameter, public mintemperature
Minimum temperature ( K )
Fortran module containing subroutines used by both minimizers.
subroutine, public ufo_rttovonedvarcheck_geovals2profvec(geovals, profindex, ob, prof_x)
Copy geovals data (and ob) to profile.
subroutine, public ufo_rttovonedvarcheck_check_geovals(self, geovals, profindex, surface_type)
Check the geovals are ready for the first iteration.
subroutine, public ufo_rttovonedvarcheck_checkiteration(self, geovals, profindex, profile, OutOfRange)
Constrain profile humidity and check temperature values are okay.
subroutine, public ufo_rttovonedvarcheck_profvec2geovals(geovals, profindex, ob, prof_x, UseQtsplitRain)
Copy profile data to geovals (and ob).
subroutine, public ufo_rttovonedvarcheck_printiterinfo(yob, hofx, channels, guessprofile, backprofile, diffprofile, binv, hmatrix)
Print detailed information for each iteration for diagnostics.
subroutine, public ufo_rttovonedvarcheck_checkcloudyiteration(geovals, profindex, nlevels_1dvar, OutOfRange, OutLWP)
Check cloud during iteration.
character(len=max_string) message
subroutine, public ufo_rttovonedvarcheck_costfunction(DeltaProf, b_inv, DeltaObs, r_matrix, Jcost)
Calculate the cost function.
subroutine, public ufo_rttovonedvarcheck_hofxdiags_levels(retrieval_vars, nlevels, ret_nlevs)
Fortran module which contains the observation metadata for a single observation.
Fortran module containing profile index.
Fortran derived type to hold data for the observation covariance.
Fortran module containing main type, setup and utilities for the main rttovonedvarcheck object.
Fortran module with various useful routines.
subroutine, public ops_satrad_qsplit(output_type, p, t, qtotal, q, ql, qi, UseQtSplitRain)
Split the humidity into water vapour, liquid water and ice.
subroutine, public ops_qsat(QS, T, P, npnts)
Calculate the Saturation Specific Humidity Scheme (Qsat): Vapour to Liquid/Ice.
subroutine, public ops_qsatwat(QS, T, P, npnts)
Saturation Specific Humidity Scheme: Vapour to Liquid.
logical function, public cmp_strings(str1, str2)
character(len=maxvarlen), parameter, public var_clw
character(len=maxvarlen), parameter, public var_sfc_v10
character(len=maxvarlen), parameter, public var_prs
character(len=maxvarlen), parameter, public var_q
character(len=maxvarlen), parameter, public var_sfc_u10
character(len=maxvarlen), parameter, public var_sfc_q2m
character(len=maxvarlen), parameter, public var_sfc_tskin
character(len=maxvarlen), parameter, public var_sfc_p2m
character(len=maxvarlen), parameter, public var_ts
character(len=maxvarlen), parameter, public var_cli
character(len=maxvarlen), parameter, public var_sfc_t2m
type to hold interpolated field for one variable, one observation
type to hold interpolated fields required by the obs operators