UFO
ufo_refractivity_utils_mod.F90
Go to the documentation of this file.
1 !-------------------------------------------------------------------------------
2 ! (C) British Crown Copyright 2020 Met Office
3 !
4 ! This software is licensed under the terms of the Apache Licence Version 2.0
5 ! which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6 !-------------------------------------------------------------------------------
7 
9 
10 
11 !use iso_c_binding
12 use fckit_log_module, only: fckit_log
13 use kinds, only: kind_real
14 
15 ! Generic routines from elsewhere in jedi
16 use missing_values_mod
17 use ufo_constants_mod, only: &
18  rd, & ! Gas constant for dry air
19  cp, & ! Heat capacity at constant pressure for air
20  rd_over_cp, & ! Ratio of gas constant to heat capacity
21  pref, & ! Reference pressure for calculating exner
22  grav, & ! Gravitational field strength
23  n_alpha, & ! Refractivity constant a
24  n_beta, & ! Refractivity constant b
25  mw_ratio, & ! Ratio of molecular weights of water and dry air
26  c_virtual ! Related to mw ratio
27 
28 implicit none
29 
30 public :: ufo_refractivity
31 private
32 
33 contains
34 
35 
36 SUBROUTINE ufo_refractivity(nlevq, &
37  nlevP, &
38  za, &
39  zb, &
40  x, &
41  pN, &
42  refracerr, &
43  refrac)
44 
45 IMPLICIT NONE
46 
47 ! Subroutine arguments:
48 
49 INTEGER, INTENT(IN) :: nlevq ! no. of levels of wet refractivity required
50 INTEGER, INTENT(IN) :: nlevp ! no. of levels of dry refractivity required
51 REAL(kind_real), INTENT(IN) :: za(:) ! heights of pressure levels
52 
53 REAL(kind_real), INTENT(IN) :: zb(:) ! Heights of theta levels
54 REAL(kind_real), INTENT(IN) :: x(:) ! state vector
55 REAL(kind_real), INTENT(INOUT) :: pn(:) ! pressure on refractivity (theta) levels
56 LOGICAL, INTENT(OUT) :: refracerr ! errors in refractivity calculation
57 REAL(kind_real), INTENT(INOUT) :: refrac(:) ! refrac on refractivity (theta) levels
58 
59 
60 ! Local declarations:
61 CHARACTER(len=*), PARAMETER :: routinename = "ufo_refractivity"
62 INTEGER :: i
63 INTEGER :: level
64 REAL, ALLOCATABLE :: exnern(:) ! Exner on refractivity (theta) levels
65 REAL, ALLOCATABLE :: exner(:) ! Exner on pressure (rho) levels
66 REAL(kind_real) :: t(nlevq) ! Temp. on theta levs
67 REAL :: tv ! Tv on refractivity (theta) level
68 REAL :: ndry ! Dry refractivity
69 REAL :: nwet ! Wet refractivity
70 
71 INTEGER :: numplevs ! Number of levels of pInter
72 INTEGER :: numqlevs ! Numbers of levels of qN
73 LOGICAL :: nonmon ! non-monotonic pressure warning
74 LOGICAL :: unphys ! zero or negative pressure warning
75 LOGICAL :: levelerr ! nlevq greater than nlevp error
76 integer, parameter :: max_string = 800
77 CHARACTER(len=max_string) :: message
78 
79 REAL(kind_real) :: p(nlevp)
80 REAL(kind_real) :: q(nlevq)
81 REAL(kind_real) :: pwt1
82 REAL(kind_real) :: pwt2
83 INTEGER :: nstate
84 
85 
86 ! Get constants into right units
87 
88 nstate = nlevp + nlevq
89 p(:) = x(1:nlevp)
90 q(:) = x(nlevp + 1:nstate)
91 
92 ALLOCATE (exnern(nlevq))
93 ALLOCATE (exner(nlevp))
94 
95 refrac(:) = missing_value(refrac(1))
96 t(:) = missing_value(t(1))
97 nonmon = .false.
98 unphys = .false.
99 levelerr = .false.
100 refracerr = .false.
101 
102 DO i = 1, nlevp
103  IF (p(i) == missing_value(p(i))) THEN !pressure missing
104  refracerr = .true.
105  WRITE(message, *) routinename, "Missing value P", i
106  CALL fckit_log % warning(message)
107  EXIT
108  END IF
109 END DO
110 
111 
112 DO i = 1, nlevp-1
113  IF (p(i) - p(i + 1) < 0.0) THEN !or non-monotonic pressure
114  refracerr = .true.
115  nonmon = .true.
116  WRITE(message,*) "Non monotonic", i, p(i), p(i+1)
117  CALL fckit_log % warning(message)
118  EXIT
119  END IF
120 END DO
121 
122 IF (any(p(:) <= 0.0)) THEN !pressure zero or negative
123  refracerr = .true.
124  unphys = .true.
125 END IF
126 
127 IF (nlevq >= nlevp) THEN ! nlevq must be < than nlevP
128  refracerr = .true.
129  levelerr = .true.
130 END IF
131 
132 ! only proceed if pressure is valid
133 IF (refracerr) THEN
134  IF (nonmon) THEN
135  CALL fckit_log%warning (routinename // ": Pressure non-monotonic")
136  ELSE IF (unphys) THEN
137  CALL fckit_log%warning (routinename // ": Pressure <= zero")
138  ELSE
139  CALL fckit_log%warning (routinename // ": Pressure missing")
140  END IF
141  IF (levelerr) THEN
142  CALL fckit_log%warning (routinename // ": Too many wet levels")
143  END IF
144 
145 ELSE
146 
147  ! Calculate exner on rho(pressure) levels.
148 
149  exner(:) = (p(:) / pref) ** rd_over_cp
150 
151  ! Calculate the refractivity on the b levels
152 
153 
154  DO level = 1, nlevp - 1
155 
156  pwt1 = (za(level + 1) - zb(level)) / (za(level + 1) - za(level))
157  pwt2 = 1.0 - pwt1
158 
159  pn(level) = exp(pwt1 * log(p(level)) + pwt2 * log(p(level + 1)))
160 
161  END DO
162 
163  DO i = 1, nlevq
164 
165  ! Calculate Exner on the refractivity level.
166  exnern(i) = (pn(i) / pref) ** rd_over_cp
167 
168  ! Calculate mean layer Tv using ND definition
169 
170  tv = grav * (za(i + 1) - za(i)) * exnern(i) / &
171  (cp * (exner(i) - exner(i + 1)))
172 
173  IF (i > nlevq) THEN
174 
175  t(i) = tv
176 
177  ! No wet component
178 
179  nwet = 0.0
180 
181  ELSE
182 
183  t(i) = tv / (1.0 + c_virtual * q(i))
184 
185  ! Wet component
186 
187  nwet = n_beta * pn(i) * q(i) / (t(i) ** 2 * (mw_ratio + (1.0 - mw_ratio) * q(i)))
188 
189 
190  END IF
191 
192  IF (i > nlevp ) THEN
193  ! No dry component
194 
195  ndry = 0.0
196 
197  ELSE
198  ! Dry component
199 
200  ndry = n_alpha * pn(i) / t(i)
201 
202  END IF
203 
204  refrac(i) = ndry + nwet
205 
206  END DO
207 
208 END IF
209 
210 END SUBROUTINE ufo_refractivity
211 
ufo_avgkernel_mod::max_string
integer, parameter max_string
Definition: ufo_avgkernel_mod.F90:17
ufo_refractivity_utils_mod
Definition: ufo_refractivity_utils_mod.F90:8
ufo_refractivity_utils_mod::ufo_refractivity
subroutine, public ufo_refractivity(nlevq, nlevP, za, zb, x, pN, refracerr, refrac)
Definition: ufo_refractivity_utils_mod.F90:44
ufo_constants_mod
Definition: ufo_constants_mod.F90:2
ufo_constants_mod::rd
real(kind_real), parameter, public rd
Definition: ufo_constants_mod.F90:12