11 !------------------------------------------------------------------------------
13 SUBROUTINE recover_pressure_from_height (max_number_of_obs , obs , &
14 number_of_obs, print_hp_recover)
15 !------------------------------------------------------------------------------
17 ! Since the data merging is based on the observed pressure (see
18 ! module_obs_merge.F90/subroutine link_level), the observed pressure
19 ! is not allowed to be missing.
21 ! The pressure missing from the decoded OBS sounding (SOUND, AIREP) data
23 ! (1) from the observed heights available with the hydrostatic assumption
24 ! (dP/dH)_hydr if possible,
25 ! (2) or from the observed heights available with the model reference
26 ! state (dP/dH)_ref when hydrostatic interpolation is impossible.
28 ! There are two steps to do this:
30 ! (1) To guarantee the original pressure and height are correct, first,
31 ! a sequence check, i.e.
32 ! height at the next level > height at the current level and
33 ! pressure at the next level < pressure at the current level,
34 ! is completed (subroutine hp_sequence_check).
36 ! (2) second, a consistency check between the observed pressure and
37 ! height agaist the model reference state is completed
38 ! (subroutine pressure_recover, FUNCTION hp_consist).
40 ! (3) To fill the missing pressure by using the observed pressure and
41 ! heights that passed the above checks (subroutine recover_p_from_h).
46 !------------------------------------------------------------------------------
50 INTEGER, INTENT ( IN ) :: max_number_of_obs
51 TYPE (report), DIMENSION (max_number_of_obs):: obs
52 INTEGER , INTENT ( IN ) :: number_of_obs
53 LOGICAL , INTENT (IN) :: print_hp_recover
55 TYPE (measurement), POINTER :: current
59 CHARACTER (LEN=80) :: filename
60 LOGICAL :: connected, consistent
61 INTEGER :: iunit, io_error
62 CHARACTER (LEN = 32) :: proc_name = &
63 "recover_pressure_from_height"
65 INCLUDE 'platform_interface.inc'
67 !------------------------------------------------------------------------------!
70 '------------------------------------------------------------------------------'
71 WRITE (UNIT = 0, FMT = '(A,/)') 'PRESSURE RECOVERED FROM HEIGHTS:'
73 IF (print_hp_recover) THEN
75 filename = 'obs_recover_pressure.diag'
78 INQUIRE (UNIT = iunit, OPENED = connected )
80 IF (connected) CLOSE (iunit)
82 OPEN (UNIT = iunit , FILE = filename , FORM = 'FORMATTED' , &
83 ACTION = 'WRITE' , STATUS = 'REPLACE', IOSTAT = io_error )
85 IF (io_error .NE. 0) THEN
86 CALL error_handler (proc_name, &
87 "Unable to open output diagnostic file. " , filename, .TRUE.)
89 WRITE (UNIT = 0, FMT = '(A,A,/)') &
90 "Diagnostics in file ", TRIM (filename)
99 ! 2.1 Print parameters
102 IF (print_hp_recover) THEN
104 WRITE (UNIT = IUNIT, FMT = '(A,/)') 'PRESSURE RECOVERED FROM HEIGHTS:'
106 WRITE(UNIT = iunit , FMT = '(A,/,3(A,F10.2,A),/,3(A,F10.2,A),/)') &
107 "REFERENCE STATE: ", &
108 " HTOP = ", htop,"m, ", &
109 " PTOP = ", ptop,"Pa, ", &
110 " PS0 = ", ps0 ,"Pa, ", &
111 " TS0 = ", ts0 ,"K, ", &
112 " TLP = ", tlp ,"K, ",&
113 " DIS = ", DIS(idd),"m."
121 DO i = 1, number_of_obs
123 IF ((obs (i) % info % discard) .OR. .NOT. ASSOCIATED &
124 (obs (i) % surface)) THEN
130 ! 3. SINGLE LEVEL OBS
131 ! ====================
134 IF (obs (i) % info % bogus .OR. (.NOT. obs (i) % info % is_sound)) THEN
136 ! IF pressure is missing, height should be present
139 (obs (i) % surface % meas % pressure % data, missing_r, 1.))THEN
140 obs (i) % surface % meas % pressure % data = floor (ref_pres &
141 (obs (i) % surface % meas % height % data))
142 obs (i) % surface % meas % pressure % qc = &
144 ELSE IF (obs (i) % surface % meas % pressure % qc == 0 .and. &
145 obs (i) % surface % meas % height % qc == 0 .and. &
147 (obs (i) % surface % meas % height % data, 0., 1.)) then
149 !hcl-note: obsproc should not check for qc on input file
150 !hcl-note: qc should be assigned by obsproc
151 ! When both h and p have qc = 0 and h = 0. (at sea level
152 ! because the pressure is MSLP for surface data, check
153 ! the consistency between h and p
155 consistent = hp_consist ( &
156 obs (i) % surface % meas % height % data, &
157 obs (i) % surface % meas % pressure % data, &
158 print_hp_recover, iunit)
159 if (.not.consistent) obs (i) % info % discard = .true.
168 ! 3.1 Height and pressure sequence check
169 ! ----------------------------------
171 CALL hp_sequence_check (obs (i), i, nlevel, print_hp_recover, iunit)
173 CALL hp_missing_check (obs(i), i, nlevel)
175 ! 3.2 Single level sounding are removed
176 ! ---------------------------------
178 IF ((nlevel == 1) .AND. eps_equal &
179 (obs (i) % surface % meas % pressure% data, missing_r, 1.0)) THEN
181 obs (i) % info % discard = .TRUE.
183 IF (print_hp_recover) THEN
185 WRITE (UNIT = iunit, FMT = '(A,A,I5,A,A)') &
186 "In recover_pressure_from_height: ","I = ", I," ID = ", &
187 obs (i) % location % id (1:5)
189 WRITE (UNIT = iunit, FMT = '(A,I5,A,F9.0,A,F9.0)') &
190 "nlevel = ", nlevel, &
191 "height = ", obs (i) % surface % meas % height % data, &
192 "pressure = ",obs (i) % surface % meas % pressure % data
200 ! 3.2 If the actual number of valid levels differs from expected, print it
201 ! --------------------------------------------------------------------
203 IF (nlevel /= obs (i) % info % levels) THEN
205 IF (print_hp_recover) THEN
207 WRITE (UNIT = iunit, FMT = '(3A,I4,A,I4)') &
208 "ID = ", obs(i)%location%id(1:5), ", expect ", &
209 obs (i) % info % levels, " levels, get ", nlevel
215 ! 3.3 Pressure is recovered based on height if the pressure is missing
216 ! ----------------------------------------------------------------
218 CALL recover_p_from_h (obs (i), i, nlevel, print_hp_recover, iunit)
224 IF (print_hp_recover) CLOSE (iunit)
226 END SUBROUTINE recover_pressure_from_height
228 !------------------------------------------------------------------------------!
230 SUBROUTINE hp_sequence_check (obs, i, nlevel, print_hp_recover, iunit)
231 !------------------------------------------------------------------------------!
233 INTEGER, INTENT (in) :: i, iunit
234 INTEGER, INTENT (out) :: nlevel
235 LOGICAL, INTENT (in) :: print_hp_recover
236 TYPE (report), INTENT (inout) :: obs
238 TYPE (measurement), POINTER :: current
239 REAL :: height1, height2, &
241 LOGICAL :: first_h, first_p
242 !------------------------------------------------------------------------------
244 current => obs % surface
250 DO WHILE (ASSOCIATED (current))
257 IF (.NOT. eps_equal (current%meas%height%data, missing_r, 1.0)) then
259 IF (.NOT. first_h) then
261 height1 = current%meas%height%data
266 height2 = current%meas%height%data
268 IF (height2 <= height1) then
270 current%meas%height%qc = missing
271 current%meas%height%data = missing_r
273 IF (print_hp_recover) THEN
275 WRITE (UNIT = iunit, FMT = '(A,/,4A,A,I3,2(A,f12.2))') &
276 "HEIGHT VIOLATION: ", &
277 " FM = ", obs % info % platform (4:6), &
278 " ID = ", obs % location % id, &
279 " LEVEL = ", nlevel, &
298 IF (.NOT.eps_equal(current%meas%pressure%data, missing_r, 1.0)) then
300 IF (.NOT.first_p) THEN
301 press1 = current%meas%pressure%data
304 PRESS2 = current%meas%pressure%data
306 IF (press2 >= press1) THEN
307 current%meas%pressure%data = missing_r
308 current%meas%pressure%qc = missing
310 IF (print_hp_recover) THEN
312 WRITE (UNIT = iunit, FMT = '(A,/,4A,A,I3,2(A,f12.2))') &
313 "PRESSURE VIOLATION: ", &
314 " FM = ", obs % info % platform (4:6), &
315 " ID = ", obs % location % id, &
316 " LEVEL = ", nlevel, &
334 current => current%next
338 END subroutine hp_sequence_check
339 !------------------------------------------------------------------------------!
341 SUBROUTINE recover_p_from_h(obs, i, nlevel, print_hp_recover, iunit)
342 !------------------------------------------------------------------------------!
346 INTEGER, INTENT (in) :: i, iunit, nlevel
347 LOGICAL, INTENT (in) :: print_hp_recover
348 TYPE (report), INTENT (inout) :: obs
350 TYPE (measurement), POINTER :: current
351 TYPE (field) , dimension(nlevel) :: pp, hh
355 !------------------------------------------------------------------------------!
357 ! 1. GET THE P/H PROFILE
358 ! =======================
361 current => obs % surface
364 DO WHILE (ASSOCIATED (current))
367 hh (k) = current % meas % height
368 pp (k) = current % meas % pressure
369 current => current % next
373 ! 2. PRESSURE FILED BASED ON THE HEIGHT IF THE PRESSURE IS MISSING
374 ! =================================================================
376 ! 2.1 Recover pressure
379 CALL pressure_recover (nlevel, pp, hh, iunit, LB, LE, do_it, print_hp_recover)
386 IF (print_hp_recover) THEN
388 WRITE(UNIT = iunit,FMT = '(5A)', ADVANCE = 'no') &
389 "== PRESSURE RECOVER DONE: ", &
390 " for FM=", obs % info % platform (4:6), &
391 " ID=", obs % location % id
395 IF (print_hp_recover) THEN
397 IF (LB > 1 .OR. LE < nlevel) THEN
398 WRITE(UNIT = iunit,FMT = '(A)') &
399 " Reference pressure may have been used."
401 WRITE(UNIT = iunit,FMT = '(A)') " "
408 ! 2. SEND BACK TO OBS
409 ! ====================
411 current => obs % surface
416 DO WHILE (ASSOCIATED (current))
419 ! current % meas % height % data = CEILING (hh (k) % data)
420 current % meas % height % data = hh (k) % data
421 current % meas % height % qc = hh (k) % qc
422 current % meas % pressure % data = FLOOR (pp (k) % data)
423 current % meas % pressure % qc = pp (k) % qc
424 current => current % next
430 END SUBROUTINE recover_p_from_h
431 !------------------------------------------------------------------------------!
433 FUNCTION hp_consist (hin,pin,print_out,iunit) RESULT (hout)
434 !------------------------------------------------------------------------------!
438 REAL, INTENT (in) :: hin, pin
439 LOGICAL, INTENT (in) :: print_out
440 INTEGER, INTENT (in) :: iunit
443 REAL, parameter :: hmax = 1000. ! a tolerance apart from
444 ! the model reference state
448 !------------------------------------------------------------------------------!
450 write(unit=0, fmt='(A,f12.2)') &
451 "In function hp_consist, Pressure voilation: P=",pin
458 h_ref = Ref_height(pin)
460 hdiff = ABS (hin - h_ref)
462 IF (hdiff > (50000/pin)*hmax) THEN
465 WRITE (UNIT = iunit, FMT = '(/,A,/,3(A,F12.3,/))') &
466 " Pressure / height inconsistency: ", &
467 " Pressure = ", pin, &
469 " ref_height = ", h_ref
476 END FUNCTION hp_consist
477 !------------------------------------------------------------------------------!
478 subroutine pressure_recover(level, pp, hh, iunit, LB, LE, do_it, print_hp_recover)
482 INTEGER, INTENT(in) :: level, iunit
483 TYPE (field), dimension(level), INTENT(inout) :: hh, pp
484 INTEGER, INTENT(out) :: LB, LE
485 LOGICAL, INTENT(out) :: do_it
486 LOGICAL, INTENT (in) :: print_hp_recover
488 INTEGER :: k, L, L1, L2, Lstart
489 REAL :: height1, height2, &
490 press1 , press2 , bb, diff_pr
491 LOGICAL :: first_L, second_L, &
493 ! -----------------------------------------------------------------
506 ! if there is ONLY one level OBS:
512 loop_level: do k = 1,level
514 if (.NOT.first_L) then
516 ! To find the first level with both height and pressure
518 if (.NOT.eps_equal (pp(k)%data, missing_r, 1.0) .and. &
519 .NOT.eps_equal (hh(k)%data, missing_r, 1.0) ) then
527 ! To find the second level with both height and pressure
530 if (.NOT.eps_equal (pp(k)%data, missing_r, 1.0) .and. &
531 .NOT.eps_equal (hh(k)%data, missing_r, 1.0) ) then
538 height1 = hh(L1) % data
539 press1 = pp(L1) % data
543 ! If the first level is not the level 1 and pp(1) is missing
544 if (eps_equal(pp(1)%data, missing_r, 1.0)) then
549 height1 = hh(L1) % data
550 ! Set the correction from reference pressure (h1,h2) plus p2
551 press1 = Ref_pres(height1)
552 press2 = Ref_pres(hh(L2)%data)
553 diff_pr = press1 - press2
554 press1 = pp(L2)%data + diff_pr
556 pp(L1)%qc = reference_atmosphere
559 ! There are pressure missing below the level where both p and h available:
560 if (eps_equal(pp(L)%data, missing_r, 1.0)) then
561 pp(L)%data = Ref_pres(hh(L)%data)
562 pp(L)%qc = reference_atmosphere
569 ! height/pressure consistency check
570 consist1 = hp_consist (height1,press1,print_hp_recover,iunit)
571 if (.NOT.consist1) then
572 WRITE(UNIT=IUNIT, FMT='(A,2F12.2)') &
573 "FAILED IN H/P CONSISTENCY CHECK: H1,P1:",height1,press1
575 hh(L1) % data = missing_r
576 hh(L1) % qc = missing
584 height2 = hh(L2) % data
585 press2 = pp(L2) % data
587 consist2 = hp_consist (height2,press2,print_hp_recover,iunit)
588 if (.NOT.consist2) then
589 WRITE(UNIT=IUNIT, FMT='(A,I4,2F12.2)') &
590 "FAILED IN H/P CONSISTENCY CHECK: L2,H2,P2:",L2,height2,press2
592 hh(L2) % data = missing_r
593 hh(L2) % qc = missing
598 ! If L1 and L2 are consecutive
600 if (L2 <= (L1 + 1)) then
605 ! If L1 and L2 are not consecutive
607 BB = (height2 - height1)/ALOG(press2/press1)
609 ! .. get the interpolated pressure from the height if pressure is missing:
610 if (eps_equal(pp(L)%data, missing_r, 1.0)) then
611 if (eps_equal(hh(L)%data, missing_r, 1.0)) then
613 "Both pressure and height are missing, ", &
614 "this should never be happened???"
617 pp(L)%data = press1*EXP((hh(L)%data - height1)/BB)
629 ! If L2 is not equal to level
634 if (eps_equal(pp(k)%data, missing_r, 1.0)) then
635 ! Set the reference pressure
637 press1 = Ref_pres(hh(L2)%data)
638 press2 = Ref_pres(hh(k )%data)
639 diff_pr = press1 - press2
640 pp(k)%data = pp(L2)%data - diff_pr
642 pp(k)%data = Ref_pres(hh(k )%data)
644 pp(k)%qc = reference_atmosphere
650 end subroutine pressure_recover
652 SUBROUTINE hp_missing_check (obs, i, nlevel)
653 !------------------------------------------------------------------------------!
655 INTEGER, INTENT (in) :: i
656 INTEGER, INTENT (out) :: nlevel
657 TYPE (report), INTENT (inout) :: obs
659 TYPE (measurement), POINTER :: current, tmp, new, pre
661 !------------------------------------------------------------------------------
662 current => obs % surface
663 new => current % next
667 DO WHILE (ASSOCIATED (new))
673 ! If both P and H missing at the next level?
674 IF (eps_equal (new % meas % pressure % data, missing_r, 1.) .and. &
675 eps_equal (new % meas % height % data, missing_r, 1.) ) THEN
677 write(0,'("==> Missing P and H:",i3,2f15.6)') nn, &
678 new%meas%pressure%data, new%meas%height%data
679 nullify(current % next)
681 current % next => tmp
687 ! If both P and H missing at the next next level?
688 if (associated (current%next) .and. &
689 eps_equal (current%next%meas%pressure% data, missing_r, 1.) .and.&
690 eps_equal (current%next%meas% height % data, missing_r, 1.) ) THEN
692 nullify(current % next)
693 current % next => tmp
698 current => current % next
702 current => current % next
705 new => current % next
709 ! To count the total number of levels:
711 current => obs % surface
713 do while (associated(current))
715 ! write(0,'(I3," P,H:",2f15.5)') nn, &
716 ! current%meas%pressure%data, current%meas%height%data
717 current => current%next
721 if (obs%info%levels /= nlevel ) then
722 obs%info%levels = nlevel
723 write(0, fmt='(a, i3, 2x, 2a, 2x, a, 2f10.3/)') &
724 'After missing check: Number of levels = ', obs%info%levels, &
725 'OBS=', obs%info%platform(1:12), &
726 'LOC=', obs%location%latitude, obs%location%longitude
729 END SUBROUTINE hp_missing_check
731 END MODULE module_recoverp