| 1 | !! Fortran version of different diagnostics |
|---|
| 2 | ! L. Fita. LMD May 2016 |
|---|
| 3 | ! gfortran module_generic.o module_ForDiagnosticsVars.o -c module_ForDiagnostics.F90 |
|---|
| 4 | ! |
|---|
| 5 | ! f2py -m module_ForDiagnostics --f90exec=/usr/bin/gfortran-4.7 -c module_generic.F90 module_ForDiagnosticsVars.F90 module_ForDiagnostics.F90 |
|---|
| 6 | |
|---|
| 7 | MODULE module_ForDiagnostics |
|---|
| 8 | |
|---|
| 9 | USE module_definitions |
|---|
| 10 | USE module_generic |
|---|
| 11 | USE module_ForDiagnosticsVars |
|---|
| 12 | |
|---|
| 13 | CONTAINS |
|---|
| 14 | |
|---|
| 15 | !!!!!!! Calculations |
|---|
| 16 | ! compute_cllmh4D3: Computation of low, medium and high cloudiness from a 4D CLDFRA and pressure being |
|---|
| 17 | ! 3rd dimension the z-dim |
|---|
| 18 | ! compute_cllmh3D3: Computation of low, medium and high cloudiness from a 3D CLDFRA and pressure being |
|---|
| 19 | ! 3rd dimension the z-dim |
|---|
| 20 | ! compute_cllmh: Computation of low, medium and high cloudiness |
|---|
| 21 | ! compute_clt4D3: Computation of total cloudiness from a 4D CLDFRA being 3rd dimension the z-dim |
|---|
| 22 | ! compute_clt3D3: Computation of total cloudiness from a 3D CLDFRA being 3rd dimension the z-dim |
|---|
| 23 | ! compute_clt: Computation of total cloudiness |
|---|
| 24 | ! compute_psl_ptarget4d2: Compute sea level pressure using a target pressure. Similar to the Benjamin |
|---|
| 25 | ! and Miller (1990). Method found in p_interp.F90 |
|---|
| 26 | ! compute_tv4d: 4D calculation of virtual temperaure |
|---|
| 27 | ! VirtualTemp1D: Function for 1D calculation of virtual temperaure |
|---|
| 28 | |
|---|
| 29 | !!! |
|---|
| 30 | ! Calculations |
|---|
| 31 | !!! |
|---|
| 32 | |
|---|
| 33 | SUBROUTINE compute_cllmh4D2(cldfra4D, pres4D, cllmh4D2, d1, d2, d3, d4) |
|---|
| 34 | ! Subroutine to compute the low, medium and high cloudiness following 'newmicro.F90' from LMDZ from a 4D CLDFRA and pressure |
|---|
| 35 | ! where zdim is the 2nd dimension (thus, cldfra4D(d1,d2,d3,d4) --> cllmh(3,d1,d3,d4) 1: low, 2: medium, 3: high |
|---|
| 36 | ! It should be properly done via an 'INTERFACE', but... |
|---|
| 37 | |
|---|
| 38 | IMPLICIT NONE |
|---|
| 39 | |
|---|
| 40 | INTEGER, INTENT(in) :: d1, d2, d3, d4 |
|---|
| 41 | REAL(r_k), DIMENSION(d1,d2,d3,d4), INTENT(in) :: cldfra4D, pres4D |
|---|
| 42 | REAL(r_k), DIMENSION(3,d1,d3,d4), INTENT(out) :: cllmh4D2 |
|---|
| 43 | |
|---|
| 44 | ! Local |
|---|
| 45 | INTEGER :: i,j,k, zdim, Ndim |
|---|
| 46 | |
|---|
| 47 | !!!!!!! Variables |
|---|
| 48 | ! cldfra4D: 4D cloud fraction values [1] |
|---|
| 49 | ! pres4D: 4D pressure values [Pa] |
|---|
| 50 | ! Ndim: number of dimensions of the input data |
|---|
| 51 | ! d[1-4]: dimensions of 'cldfra4D' |
|---|
| 52 | ! zdim: number of the vertical-dimension within the matrix |
|---|
| 53 | ! cltlmh4D2: low, medium, high cloudiness for the 4D cldfra and d2 being 'zdim' |
|---|
| 54 | |
|---|
| 55 | fname = 'compute_cllmh4D2' |
|---|
| 56 | zdim = 2 |
|---|
| 57 | Ndim = 4 |
|---|
| 58 | |
|---|
| 59 | DO i=1, d1 |
|---|
| 60 | DO j=1, d3 |
|---|
| 61 | DO k=1, d4 |
|---|
| 62 | cllmh4D2(:,i,j,k) = var_cllmh(cldfra4D(i,:,j,k), pres4D(i,:,j,k), d2) |
|---|
| 63 | END DO |
|---|
| 64 | END DO |
|---|
| 65 | END DO |
|---|
| 66 | |
|---|
| 67 | RETURN |
|---|
| 68 | |
|---|
| 69 | END SUBROUTINE compute_cllmh4D2 |
|---|
| 70 | |
|---|
| 71 | SUBROUTINE compute_cllmh3D1(cldfra3D, pres3D, cllmh3D1, d1, d2, d3) |
|---|
| 72 | ! Subroutine to compute the low, medium and high cloudiness following 'newmicro.F90' from LMDZ from a 3D CLDFRA and pressure |
|---|
| 73 | ! where zdim is the 1st dimension (thus, cldfra3D(d1,d2,d3) --> cllmh(3,d2,d3) 1: low, 2: medium, 3: high |
|---|
| 74 | ! It should be properly done via an 'INTERFACE', but... |
|---|
| 75 | |
|---|
| 76 | IMPLICIT NONE |
|---|
| 77 | |
|---|
| 78 | INTEGER, INTENT(in) :: d1, d2, d3 |
|---|
| 79 | REAL(r_k), DIMENSION(d1,d2,d3), INTENT(in) :: cldfra3D, pres3D |
|---|
| 80 | REAL(r_k), DIMENSION(3,d2,d3), INTENT(out) :: cllmh3D1 |
|---|
| 81 | |
|---|
| 82 | ! Local |
|---|
| 83 | INTEGER :: i,j,k, zdim, Ndim |
|---|
| 84 | |
|---|
| 85 | !!!!!!! Variables |
|---|
| 86 | ! cldfra3D: 3D cloud fraction values [1] |
|---|
| 87 | ! pres3D: 3D pressure values [Pa] |
|---|
| 88 | ! Ndim: number of dimensions of the input data |
|---|
| 89 | ! d[1-3]: dimensions of 'cldfra3D' |
|---|
| 90 | ! zdim: number of the vertical-dimension within the matrix |
|---|
| 91 | ! cltlmh3D1: low, medium, high cloudiness for the 3D cldfra and d1 being 'zdim' |
|---|
| 92 | |
|---|
| 93 | fname = 'compute_cllmh3D1' |
|---|
| 94 | zdim = 1 |
|---|
| 95 | Ndim = 3 |
|---|
| 96 | |
|---|
| 97 | DO i=1, d1 |
|---|
| 98 | DO j=1, d2 |
|---|
| 99 | cllmh3D1(:,i,j) = var_cllmh(cldfra3D(:,i,j), pres3D(:,i,j), d1) |
|---|
| 100 | END DO |
|---|
| 101 | END DO |
|---|
| 102 | |
|---|
| 103 | RETURN |
|---|
| 104 | |
|---|
| 105 | END SUBROUTINE compute_cllmh3D1 |
|---|
| 106 | |
|---|
| 107 | SUBROUTINE compute_cllmh(cldfra1D, cldfra2D, cldfra3D, cldfra4D, pres1D, pres2D, pres3D, pres4D, & |
|---|
| 108 | Ndim, zdim, cllmh1D, cllmh2D1, cllmh2D2, cllmh3D1, cllmh3D2, cllmh3D3, cllmh4D1, cllmh4D2, & |
|---|
| 109 | cllmh4D3, cllmh4D4, d1, d2, d3, d4) |
|---|
| 110 | ! Subroutine to compute the low, medium and high cloudiness following 'newmicro.F90' from LMDZ |
|---|
| 111 | |
|---|
| 112 | IMPLICIT NONE |
|---|
| 113 | |
|---|
| 114 | INTEGER, INTENT(in) :: Ndim, d1, d2, d3, d4, zdim |
|---|
| 115 | REAL(r_k), DIMENSION(d1), OPTIONAL, INTENT(in) :: cldfra1D, pres1D |
|---|
| 116 | REAL(r_k), DIMENSION(d1,d2), OPTIONAL, INTENT(in) :: cldfra2D, pres2D |
|---|
| 117 | REAL(r_k), DIMENSION(d1,d2,d3), OPTIONAL, INTENT(in) :: cldfra3D, pres3D |
|---|
| 118 | REAL(r_k), DIMENSION(d1,d2,d3,d4), OPTIONAL, & |
|---|
| 119 | INTENT(in) :: cldfra4D, pres4D |
|---|
| 120 | REAL(r_k), DIMENSION(3), OPTIONAL, INTENT(out) :: cllmh1D |
|---|
| 121 | REAL(r_k), DIMENSION(d1,3), OPTIONAL, INTENT(out) :: cllmh2D1 |
|---|
| 122 | REAL(r_k), DIMENSION(d2,3), OPTIONAL, INTENT(out) :: cllmh2D2 |
|---|
| 123 | REAL(r_k), DIMENSION(d2,d3,3), OPTIONAL, INTENT(out) :: cllmh3D1 |
|---|
| 124 | REAL(r_k), DIMENSION(d1,d3,3), OPTIONAL, INTENT(out) :: cllmh3D2 |
|---|
| 125 | REAL(r_k), DIMENSION(d1,d2,3), OPTIONAL, INTENT(out) :: cllmh3D3 |
|---|
| 126 | REAL(r_k), DIMENSION(d2,d3,d4,3), OPTIONAL, & |
|---|
| 127 | INTENT(out) :: cllmh4D1 |
|---|
| 128 | REAL(r_k), DIMENSION(d1,d3,d4,3), OPTIONAL, & |
|---|
| 129 | INTENT(out) :: cllmh4D2 |
|---|
| 130 | REAL(r_k), DIMENSION(d1,d2,d4,3), OPTIONAL, & |
|---|
| 131 | INTENT(out) :: cllmh4D3 |
|---|
| 132 | REAL(r_k), DIMENSION(d1,d2,d3,3), OPTIONAL, & |
|---|
| 133 | INTENT(out) :: cllmh4D4 |
|---|
| 134 | |
|---|
| 135 | ! Local |
|---|
| 136 | INTEGER :: i,j,k |
|---|
| 137 | |
|---|
| 138 | !!!!!!! Variables |
|---|
| 139 | ! cldfra[1-4]D: cloud fraction values [1] |
|---|
| 140 | ! pres[1-4]D: pressure values [Pa] |
|---|
| 141 | ! Ndim: number of dimensions of the input data |
|---|
| 142 | ! d[1-4]: dimensions of 'cldfra' |
|---|
| 143 | ! zdim: number of the vertical-dimension within the matrix |
|---|
| 144 | ! cllmh1D: low, medium and high cloudiness for the 1D cldfra |
|---|
| 145 | ! cllmh2D1: low, medium and high cloudiness for the 2D cldfra and d1 being 'zdim' |
|---|
| 146 | ! cllmh2D2: low, medium and high cloudiness for the 2D cldfra and d2 being 'zdim' |
|---|
| 147 | ! cllmh3D1: low, medium and high cloudiness for the 3D cldfra and d1 being 'zdim' |
|---|
| 148 | ! cllmh3D2: low, medium and high cloudiness for the 3D cldfra and d2 being 'zdim' |
|---|
| 149 | ! cllmh3D3: low, medium and high cloudiness for the 3D cldfra and d3 being 'zdim' |
|---|
| 150 | ! cllmh4D1: low, medium and high cloudiness for the 4D cldfra and d1 being 'zdim' |
|---|
| 151 | ! cllmh4D2: low, medium and high cloudiness for the 4D cldfra and d2 being 'zdim' |
|---|
| 152 | ! cllmh4D3: low, medium and high cloudiness for the 4D cldfra and d3 being 'zdim' |
|---|
| 153 | ! cllmh4D4: low, medium and high cloudiness for the 4D cldfra and d4 being 'zdim' |
|---|
| 154 | |
|---|
| 155 | fname = 'compute_cllmh' |
|---|
| 156 | |
|---|
| 157 | SELECT CASE (Ndim) |
|---|
| 158 | CASE (1) |
|---|
| 159 | cllmh1D = var_cllmh(cldfra1D, pres1D, d1) |
|---|
| 160 | CASE (2) |
|---|
| 161 | IF (zdim == 1) THEN |
|---|
| 162 | DO i=1, d2 |
|---|
| 163 | cllmh2D1(i,:) = var_cllmh(cldfra2D(:,i), pres2D(:,i), d1) |
|---|
| 164 | END DO |
|---|
| 165 | ELSE IF (zdim == 2) THEN |
|---|
| 166 | DO i=1, d1 |
|---|
| 167 | cllmh2D2(i,:) = var_cllmh(cldfra2D(:,i), pres2D(i,:), d2) |
|---|
| 168 | END DO |
|---|
| 169 | ELSE |
|---|
| 170 | PRINT *,TRIM(ErrWarnMsg('err')) |
|---|
| 171 | PRINT *,' ' // TRIM(fname) // ': wrong zdim:', zdim,' for Ndim=', Ndim, ' !!' |
|---|
| 172 | PRINT *,' accepted values: 1,2' |
|---|
| 173 | STOP |
|---|
| 174 | END IF |
|---|
| 175 | CASE (3) |
|---|
| 176 | IF (zdim == 1) THEN |
|---|
| 177 | DO i=1, d2 |
|---|
| 178 | DO j=1, d3 |
|---|
| 179 | cllmh3D1(i,j,:) = var_cllmh(cldfra3D(:,i,j), pres3D(:,i,j), d1) |
|---|
| 180 | END DO |
|---|
| 181 | END DO |
|---|
| 182 | ELSE IF (zdim == 2) THEN |
|---|
| 183 | DO i=1, d1 |
|---|
| 184 | DO j=1, d3 |
|---|
| 185 | cllmh3D2(i,j,:) = var_cllmh(cldfra3D(i,:,j), pres3D(i,:,j), d2) |
|---|
| 186 | END DO |
|---|
| 187 | END DO |
|---|
| 188 | ELSE IF (zdim == 3) THEN |
|---|
| 189 | DO i=1, d1 |
|---|
| 190 | DO j=1, d2 |
|---|
| 191 | cllmh3D3(i,j,:) = var_cllmh(cldfra3D(i,j,:), pres3D(i,j,:), d3) |
|---|
| 192 | END DO |
|---|
| 193 | END DO |
|---|
| 194 | ELSE |
|---|
| 195 | PRINT *,TRIM(ErrWarnMsg('err')) |
|---|
| 196 | PRINT *,' ' // TRIM(fname) // ': wrong zdim:', zdim,' for Ndim=', Ndim, ' !!' |
|---|
| 197 | PRINT *,' accepted values: 1,2,3' |
|---|
| 198 | STOP |
|---|
| 199 | END IF |
|---|
| 200 | CASE (4) |
|---|
| 201 | IF (zdim == 1) THEN |
|---|
| 202 | DO i=1, d2 |
|---|
| 203 | DO j=1, d3 |
|---|
| 204 | DO k=1, d4 |
|---|
| 205 | cllmh4D1(i,j,k,:) = var_cllmh(cldfra4D(:,i,j,k), pres4D(:,i,j,k), d1) |
|---|
| 206 | END DO |
|---|
| 207 | END DO |
|---|
| 208 | END DO |
|---|
| 209 | ELSE IF (zdim == 2) THEN |
|---|
| 210 | DO i=1, d1 |
|---|
| 211 | DO j=1, d3 |
|---|
| 212 | DO k=1, d4 |
|---|
| 213 | cllmh4D2(i,j,k,:) = var_cllmh(cldfra4D(i,:,j,k), pres4D(i,:,j,k), d2) |
|---|
| 214 | END DO |
|---|
| 215 | END DO |
|---|
| 216 | END DO |
|---|
| 217 | ELSE IF (zdim == 3) THEN |
|---|
| 218 | DO i=1, d2 |
|---|
| 219 | DO j=1, d3 |
|---|
| 220 | DO k=1, d4 |
|---|
| 221 | cllmh4D3(i,j,k,:) = var_cllmh(cldfra4D(i,j,:,k), pres4D(i,j,:,k), d3) |
|---|
| 222 | END DO |
|---|
| 223 | END DO |
|---|
| 224 | END DO |
|---|
| 225 | ELSE IF (zdim == 4) THEN |
|---|
| 226 | DO i=1, d1 |
|---|
| 227 | DO j=1, d2 |
|---|
| 228 | DO k=1, d3 |
|---|
| 229 | cllmh4D4(i,j,k,:) = var_cllmh(cldfra4D(i,j,k,:), pres4D(i,j,k,:), d4) |
|---|
| 230 | END DO |
|---|
| 231 | END DO |
|---|
| 232 | END DO |
|---|
| 233 | ELSE |
|---|
| 234 | PRINT *,TRIM(ErrWarnMsg('err')) |
|---|
| 235 | PRINT *,' ' // TRIM(fname) // ': wrong zdim:', zdim,' for Ndim=', Ndim, ' !!' |
|---|
| 236 | PRINT *,' accepted values: 1,2,3,4' |
|---|
| 237 | STOP |
|---|
| 238 | END IF |
|---|
| 239 | CASE DEFAULT |
|---|
| 240 | PRINT *,TRIM(ErrWarnMsg('err')) |
|---|
| 241 | PRINT *,' ' // TRIM(fname) // ': Ndim:', Ndim,' not ready !!' |
|---|
| 242 | STOP |
|---|
| 243 | END SELECT |
|---|
| 244 | |
|---|
| 245 | RETURN |
|---|
| 246 | |
|---|
| 247 | END SUBROUTINE compute_cllmh |
|---|
| 248 | |
|---|
| 249 | SUBROUTINE compute_clt4D2(cldfra4D, clt4D2, d1, d2, d3, d4) |
|---|
| 250 | ! Subroutine to compute the total cloudiness following 'newmicro.F90' from LMDZ from a 4D CLDFRA |
|---|
| 251 | ! where zdim is the 2nd dimension (thus, cldfra4D(d1,d2,d3,d4) --> clt(d1,d3,d4) |
|---|
| 252 | ! It should be properly done via an 'INTERFACE', but... |
|---|
| 253 | |
|---|
| 254 | IMPLICIT NONE |
|---|
| 255 | |
|---|
| 256 | INTEGER, INTENT(in) :: d1, d2, d3, d4 |
|---|
| 257 | REAL(r_k), DIMENSION(d1,d2,d3,d4), INTENT(in) :: cldfra4D |
|---|
| 258 | REAL(r_k), DIMENSION(d1,d3,d4), INTENT(out) :: clt4D2 |
|---|
| 259 | |
|---|
| 260 | ! Local |
|---|
| 261 | INTEGER :: i,j,k, zdim, Ndim |
|---|
| 262 | |
|---|
| 263 | !!!!!!! Variables |
|---|
| 264 | ! cldfra4D: 4D cloud fraction values [1] |
|---|
| 265 | ! Ndim: number of dimensions of the input data |
|---|
| 266 | ! d[1-4]: dimensions of 'cldfra4D' |
|---|
| 267 | ! zdim: number of the vertical-dimension within the matrix |
|---|
| 268 | ! clt4D2: total cloudiness for the 4D cldfra and d2 being 'zdim' |
|---|
| 269 | |
|---|
| 270 | fname = 'compute_clt4D2' |
|---|
| 271 | zdim = 2 |
|---|
| 272 | Ndim = 4 |
|---|
| 273 | |
|---|
| 274 | DO i=1, d1 |
|---|
| 275 | DO j=1, d3 |
|---|
| 276 | DO k=1, d4 |
|---|
| 277 | clt4D2(i,j,k) = var_clt(cldfra4D(i,:,j,k), d2) |
|---|
| 278 | END DO |
|---|
| 279 | END DO |
|---|
| 280 | END DO |
|---|
| 281 | |
|---|
| 282 | RETURN |
|---|
| 283 | |
|---|
| 284 | END SUBROUTINE compute_clt4D2 |
|---|
| 285 | |
|---|
| 286 | SUBROUTINE compute_clt3D1(cldfra3D, clt3D1, d1, d2, d3) |
|---|
| 287 | ! Subroutine to compute the total cloudiness following 'newmicro.F90' from LMDZ from a 3D CLDFRA |
|---|
| 288 | ! where zdim is the 1st dimension (thus, cldfra4D(d1,d2,d3) --> clt(d2,d3) |
|---|
| 289 | ! It should be properly done via an 'INTERFACE', but... |
|---|
| 290 | |
|---|
| 291 | IMPLICIT NONE |
|---|
| 292 | |
|---|
| 293 | INTEGER, INTENT(in) :: d1, d2, d3 |
|---|
| 294 | REAL(r_k), DIMENSION(d1,d2,d3), INTENT(in) :: cldfra3D |
|---|
| 295 | REAL(r_k), DIMENSION(d2,d3), INTENT(out) :: clt3D1 |
|---|
| 296 | |
|---|
| 297 | ! Local |
|---|
| 298 | INTEGER :: i,j,k, zdim, Ndim |
|---|
| 299 | |
|---|
| 300 | !!!!!!! Variables |
|---|
| 301 | ! cldfra3D: 3D cloud fraction values [1] |
|---|
| 302 | ! Ndim: number of dimensions of the input data |
|---|
| 303 | ! d[1-3]: dimensions of 'cldfra3D' |
|---|
| 304 | ! zdim: number of the vertical-dimension within the matrix |
|---|
| 305 | ! clt3D1: total cloudiness for the 3D cldfra and d1 being 'zdim' |
|---|
| 306 | |
|---|
| 307 | fname = 'compute_clt3D1' |
|---|
| 308 | zdim = 1 |
|---|
| 309 | Ndim = 3 |
|---|
| 310 | |
|---|
| 311 | DO i=1, d2 |
|---|
| 312 | DO j=1, d3 |
|---|
| 313 | clt3D1(i,j) = var_clt(cldfra3D(:,i,j), d1) |
|---|
| 314 | END DO |
|---|
| 315 | END DO |
|---|
| 316 | |
|---|
| 317 | RETURN |
|---|
| 318 | |
|---|
| 319 | END SUBROUTINE compute_clt3D1 |
|---|
| 320 | |
|---|
| 321 | SUBROUTINE compute_clt(cldfra1D, cldfra2D, cldfra3D, cldfra4D, Ndim, zdim, clt1D, clt2D1, clt2D2, & |
|---|
| 322 | clt3D1, clt3D2, clt3D3, clt4D1, clt4D2, clt4D3, clt4D4, d1, d2, d3, d4) |
|---|
| 323 | ! Subroutine to compute the total cloudiness following 'newmicro.F90' from LMDZ |
|---|
| 324 | |
|---|
| 325 | IMPLICIT NONE |
|---|
| 326 | |
|---|
| 327 | INTEGER, INTENT(in) :: Ndim, d1, d2, d3, d4, zdim |
|---|
| 328 | REAL(r_k), DIMENSION(d1), OPTIONAL, INTENT(in) :: cldfra1D |
|---|
| 329 | REAL(r_k), DIMENSION(d1,d2), OPTIONAL, INTENT(in) :: cldfra2D |
|---|
| 330 | REAL(r_k), DIMENSION(d1,d2,d3), OPTIONAL, INTENT(in) :: cldfra3D |
|---|
| 331 | REAL(r_k), DIMENSION(d1,d2,d3,d4), OPTIONAL, & |
|---|
| 332 | INTENT(in) :: cldfra4D |
|---|
| 333 | REAL(r_k), OPTIONAL, INTENT(out) :: clt1D |
|---|
| 334 | REAL(r_k), DIMENSION(d1), OPTIONAL, INTENT(out) :: clt2D1 |
|---|
| 335 | REAL(r_k), DIMENSION(d2), OPTIONAL, INTENT(out) :: clt2D2 |
|---|
| 336 | REAL(r_k), DIMENSION(d2,d3), OPTIONAL, INTENT(out) :: clt3D1 |
|---|
| 337 | REAL(r_k), DIMENSION(d1,d3), OPTIONAL, INTENT(out) :: clt3D2 |
|---|
| 338 | REAL(r_k), DIMENSION(d1,d2), OPTIONAL, INTENT(out) :: clt3D3 |
|---|
| 339 | REAL(r_k), DIMENSION(d2,d3,d4), OPTIONAL,INTENT(out) :: clt4D1 |
|---|
| 340 | REAL(r_k), DIMENSION(d1,d3,d4), OPTIONAL,INTENT(out) :: clt4D2 |
|---|
| 341 | REAL(r_k), DIMENSION(d1,d2,d4), OPTIONAL,INTENT(out) :: clt4D3 |
|---|
| 342 | REAL(r_k), DIMENSION(d1,d2,d3), OPTIONAL,INTENT(out) :: clt4D4 |
|---|
| 343 | |
|---|
| 344 | ! Local |
|---|
| 345 | INTEGER :: i,j,k |
|---|
| 346 | |
|---|
| 347 | !!!!!!! Variables |
|---|
| 348 | ! cldfra[1-4]D: cloud fraction values [1] |
|---|
| 349 | ! Ndim: number of dimensions of the input data |
|---|
| 350 | ! d[1-4]: dimensions of 'cldfra' |
|---|
| 351 | ! zdim: number of the vertical-dimension within the matrix |
|---|
| 352 | ! clt1D: total cloudiness for the 1D cldfra |
|---|
| 353 | ! clt2D1: total cloudiness for the 2D cldfra and d1 being 'zdim' |
|---|
| 354 | ! clt2D2: total cloudiness for the 2D cldfra and d2 being 'zdim' |
|---|
| 355 | ! clt3D1: total cloudiness for the 3D cldfra and d1 being 'zdim' |
|---|
| 356 | ! clt3D2: total cloudiness for the 3D cldfra and d2 being 'zdim' |
|---|
| 357 | ! clt3D3: total cloudiness for the 3D cldfra and d3 being 'zdim' |
|---|
| 358 | ! clt4D1: total cloudiness for the 4D cldfra and d1 being 'zdim' |
|---|
| 359 | ! clt4D2: total cloudiness for the 4D cldfra and d2 being 'zdim' |
|---|
| 360 | ! clt4D3: total cloudiness for the 4D cldfra and d3 being 'zdim' |
|---|
| 361 | ! clt4D4: total cloudiness for the 4D cldfra and d4 being 'zdim' |
|---|
| 362 | |
|---|
| 363 | fname = 'compute_clt' |
|---|
| 364 | |
|---|
| 365 | SELECT CASE (Ndim) |
|---|
| 366 | CASE (1) |
|---|
| 367 | clt1D = var_clt(cldfra1D, d1) |
|---|
| 368 | CASE (2) |
|---|
| 369 | IF (zdim == 1) THEN |
|---|
| 370 | DO i=1, d2 |
|---|
| 371 | clt2D1(i) = var_clt(cldfra2D(:,i), d1) |
|---|
| 372 | END DO |
|---|
| 373 | ELSE IF (zdim == 2) THEN |
|---|
| 374 | DO i=1, d1 |
|---|
| 375 | clt2D2(i) = var_clt(cldfra2D(:,i), d2) |
|---|
| 376 | END DO |
|---|
| 377 | ELSE |
|---|
| 378 | PRINT *,TRIM(ErrWarnMsg('err')) |
|---|
| 379 | PRINT *,' ' // TRIM(fname) // ': wrong zdim:', zdim,' for Ndim=', Ndim, ' !!' |
|---|
| 380 | PRINT *,' accepted values: 1,2' |
|---|
| 381 | STOP |
|---|
| 382 | END IF |
|---|
| 383 | CASE (3) |
|---|
| 384 | IF (zdim == 1) THEN |
|---|
| 385 | DO i=1, d2 |
|---|
| 386 | DO j=1, d3 |
|---|
| 387 | clt3D1(i,j) = var_clt(cldfra3D(:,i,j), d1) |
|---|
| 388 | END DO |
|---|
| 389 | END DO |
|---|
| 390 | ELSE IF (zdim == 2) THEN |
|---|
| 391 | DO i=1, d1 |
|---|
| 392 | DO j=1, d3 |
|---|
| 393 | clt3D2(i,j) = var_clt(cldfra3D(i,:,j), d2) |
|---|
| 394 | END DO |
|---|
| 395 | END DO |
|---|
| 396 | ELSE IF (zdim == 3) THEN |
|---|
| 397 | DO i=1, d1 |
|---|
| 398 | DO j=1, d2 |
|---|
| 399 | clt3D3(i,j) = var_clt(cldfra3D(i,j,:), d3) |
|---|
| 400 | END DO |
|---|
| 401 | END DO |
|---|
| 402 | ELSE |
|---|
| 403 | PRINT *,TRIM(ErrWarnMsg('err')) |
|---|
| 404 | PRINT *,' ' // TRIM(fname) // ': wrong zdim:', zdim,' for Ndim=', Ndim, ' !!' |
|---|
| 405 | PRINT *,' accepted values: 1,2,3' |
|---|
| 406 | STOP |
|---|
| 407 | END IF |
|---|
| 408 | CASE (4) |
|---|
| 409 | IF (zdim == 1) THEN |
|---|
| 410 | DO i=1, d2 |
|---|
| 411 | DO j=1, d3 |
|---|
| 412 | DO k=1, d4 |
|---|
| 413 | clt4D1(i,j,k) = var_clt(cldfra4D(:,i,j,k), d1) |
|---|
| 414 | END DO |
|---|
| 415 | END DO |
|---|
| 416 | END DO |
|---|
| 417 | ELSE IF (zdim == 2) THEN |
|---|
| 418 | DO i=1, d1 |
|---|
| 419 | DO j=1, d3 |
|---|
| 420 | DO k=1, d4 |
|---|
| 421 | clt4D2(i,j,k) = var_clt(cldfra4D(i,:,j,k), d2) |
|---|
| 422 | END DO |
|---|
| 423 | END DO |
|---|
| 424 | END DO |
|---|
| 425 | ELSE IF (zdim == 3) THEN |
|---|
| 426 | DO i=1, d2 |
|---|
| 427 | DO j=1, d3 |
|---|
| 428 | DO k=1, d4 |
|---|
| 429 | clt4D3(i,j,k) = var_clt(cldfra4D(i,j,:,k), d3) |
|---|
| 430 | END DO |
|---|
| 431 | END DO |
|---|
| 432 | END DO |
|---|
| 433 | ELSE IF (zdim == 4) THEN |
|---|
| 434 | DO i=1, d1 |
|---|
| 435 | DO j=1, d2 |
|---|
| 436 | DO k=1, d3 |
|---|
| 437 | clt4D4(i,j,k) = var_clt(cldfra4D(i,j,k,:), d4) |
|---|
| 438 | END DO |
|---|
| 439 | END DO |
|---|
| 440 | END DO |
|---|
| 441 | ELSE |
|---|
| 442 | PRINT *,TRIM(ErrWarnMsg('err')) |
|---|
| 443 | PRINT *,' ' // TRIM(fname) // ': wrong zdim:', zdim,' for Ndim=', Ndim, ' !!' |
|---|
| 444 | PRINT *,' accepted values: 1,2,3,4' |
|---|
| 445 | STOP |
|---|
| 446 | END IF |
|---|
| 447 | CASE DEFAULT |
|---|
| 448 | PRINT *,TRIM(ErrWarnMsg('err')) |
|---|
| 449 | PRINT *,' ' // TRIM(fname) // ': Ndim:', Ndim,' not ready !!' |
|---|
| 450 | STOP |
|---|
| 451 | END SELECT |
|---|
| 452 | |
|---|
| 453 | RETURN |
|---|
| 454 | |
|---|
| 455 | END SUBROUTINE compute_clt |
|---|
| 456 | |
|---|
| 457 | SUBROUTINE compute_psl_ptarget4d2(press, ps, hgt, ta, qv, ptarget, psl, d1, d2, d3, d4) |
|---|
| 458 | ! Subroutine to compute sea level pressure using a target pressure. Similar to the Benjamin |
|---|
| 459 | ! and Miller (1990). Method found in p_interp.F90 |
|---|
| 460 | |
|---|
| 461 | IMPLICIT NONE |
|---|
| 462 | |
|---|
| 463 | INTEGER, INTENT(in) :: d1, d2, d3, d4 |
|---|
| 464 | REAL(r_k), DIMENSION(d1,d2,d3,d4), INTENT(in) :: press, ta, qv |
|---|
| 465 | REAL(r_k), DIMENSION(d1,d2,d4), INTENT(in) :: ps |
|---|
| 466 | REAL(r_k), DIMENSION(d1,d2), INTENT(in) :: hgt |
|---|
| 467 | REAL(r_k), INTENT(in) :: ptarget |
|---|
| 468 | REAL(r_k), DIMENSION(d1,d2,d4), INTENT(out) :: psl |
|---|
| 469 | |
|---|
| 470 | ! Local |
|---|
| 471 | INTEGER :: i, j, it |
|---|
| 472 | INTEGER :: kin |
|---|
| 473 | INTEGER :: kupper |
|---|
| 474 | REAL(r_k) :: dpmin, dp, tbotextrap, & |
|---|
| 475 | tvbotextrap, virtual |
|---|
| 476 | ! Exponential related to standard atmosphere lapse rate r_d*gammav/g |
|---|
| 477 | REAL(r_k), PARAMETER :: expon=r_d*gammav/grav |
|---|
| 478 | |
|---|
| 479 | !!!!!!! Variables |
|---|
| 480 | ! press: Atmospheric pressure [Pa] |
|---|
| 481 | ! ps: surface pressure [Pa] |
|---|
| 482 | ! hgt: surface height |
|---|
| 483 | ! ta: temperature [K] |
|---|
| 484 | ! qv: water vapor mixing ratio |
|---|
| 485 | ! dz: number of vertical levels |
|---|
| 486 | ! psl: sea-level pressure |
|---|
| 487 | |
|---|
| 488 | fname = 'compute_psl_ptarget4d2' |
|---|
| 489 | |
|---|
| 490 | ! Minimal distance between pressures [Pa] |
|---|
| 491 | dpmin=1.e4 |
|---|
| 492 | psl=0. |
|---|
| 493 | |
|---|
| 494 | DO i=1,d1 |
|---|
| 495 | DO j=1,d2 |
|---|
| 496 | IF (hgt(i,j) /= 0.) THEN |
|---|
| 497 | DO it=1,d4 |
|---|
| 498 | |
|---|
| 499 | ! target pressure to be used for the extrapolation [Pa] (defined in namelist.input) |
|---|
| 500 | ! ptarget = 70000. default value |
|---|
| 501 | |
|---|
| 502 | ! We are below both the ground and the lowest data level. |
|---|
| 503 | |
|---|
| 504 | ! First, find the model level that is closest to a "target" pressure |
|---|
| 505 | ! level, where the "target" pressure is delta-p less that the local |
|---|
| 506 | ! value of a horizontally smoothed surface pressure field. We use |
|---|
| 507 | ! delta-p = 150 hPa here. A standard lapse rate temperature profile |
|---|
| 508 | ! passing through the temperature at this model level will be used |
|---|
| 509 | ! to define the temperature profile below ground. This is similar |
|---|
| 510 | ! to the Benjamin and Miller (1990) method, using |
|---|
| 511 | ! 700 hPa everywhere for the "target" pressure. |
|---|
| 512 | |
|---|
| 513 | kupper = 0 |
|---|
| 514 | loop_kIN: DO kin=d3,1,-1 |
|---|
| 515 | kupper = kin |
|---|
| 516 | dp=abs( press(i,j,kin,it) - ptarget ) |
|---|
| 517 | IF (dp .GT. dpmin) EXIT loop_kIN |
|---|
| 518 | dpmin=min(dpmin,dp) |
|---|
| 519 | ENDDO loop_kIN |
|---|
| 520 | |
|---|
| 521 | tbotextrap=ta(i,j,kupper,it)*(ps(i,j,it)/ptarget)**expon |
|---|
| 522 | tvbotextrap=virtualTemp1D(tbotextrap,qv(i,j,kupper,it)) |
|---|
| 523 | |
|---|
| 524 | psl(i,j,it) = ps(i,j,it)*((tvbotextrap+gammav*hgt(i,j))/tvbotextrap)**(1/expon) |
|---|
| 525 | END DO |
|---|
| 526 | ELSE |
|---|
| 527 | psl(i,j,:) = ps(i,j,:) |
|---|
| 528 | END IF |
|---|
| 529 | END DO |
|---|
| 530 | END DO |
|---|
| 531 | |
|---|
| 532 | RETURN |
|---|
| 533 | |
|---|
| 534 | END SUBROUTINE compute_psl_ptarget4d2 |
|---|
| 535 | |
|---|
| 536 | SUBROUTINE compute_massvertint1D(var, mutot, dz, deta, integral) |
|---|
| 537 | ! Subroutine to vertically integrate a 1D variable in eta vertical coordinates |
|---|
| 538 | |
|---|
| 539 | IMPLICIT NONE |
|---|
| 540 | |
|---|
| 541 | INTEGER, INTENT(in) :: dz |
|---|
| 542 | REAL(r_k), INTENT(in) :: mutot |
|---|
| 543 | REAL(r_k), DIMENSION(dz), INTENT(in) :: var, deta |
|---|
| 544 | REAL(r_k), INTENT(out) :: integral |
|---|
| 545 | |
|---|
| 546 | ! Local |
|---|
| 547 | INTEGER :: k |
|---|
| 548 | |
|---|
| 549 | !!!!!!! Variables |
|---|
| 550 | ! var: vertical variable to integrate (assuming kgkg-1) |
|---|
| 551 | ! mutot: total dry-air mass in column |
|---|
| 552 | ! dz: vertical dimension |
|---|
| 553 | ! deta: eta-levels difference between full eta-layers |
|---|
| 554 | |
|---|
| 555 | fname = 'compute_massvertint1D' |
|---|
| 556 | |
|---|
| 557 | ! integral=0. |
|---|
| 558 | ! DO k=1,dz |
|---|
| 559 | ! integral = integral + var(k)*deta(k) |
|---|
| 560 | ! END DO |
|---|
| 561 | integral = SUM(var*deta) |
|---|
| 562 | |
|---|
| 563 | integral=integral*mutot/g |
|---|
| 564 | |
|---|
| 565 | RETURN |
|---|
| 566 | |
|---|
| 567 | END SUBROUTINE compute_massvertint1D |
|---|
| 568 | |
|---|
| 569 | SUBROUTINE compute_zint4D(var4D, dlev, zweight, d1, d2, d3, d4, int3D) |
|---|
| 570 | ! Subroutine to vertically integrate a 4D variable in any vertical coordinates |
|---|
| 571 | |
|---|
| 572 | IMPLICIT NONE |
|---|
| 573 | |
|---|
| 574 | INTEGER, INTENT(in) :: d1,d2,d3,d4 |
|---|
| 575 | REAL(r_k), DIMENSION(d1,d2,d3,d4), INTENT(in) :: var4D, dlev, zweight |
|---|
| 576 | REAL(r_k), DIMENSION(d1,d2,d4), INTENT(out) :: int3D |
|---|
| 577 | |
|---|
| 578 | ! Local |
|---|
| 579 | INTEGER :: i,j,l |
|---|
| 580 | |
|---|
| 581 | !!!!!!! Variables |
|---|
| 582 | ! var4D: vertical variable to integrate |
|---|
| 583 | ! dlev: height of layers |
|---|
| 584 | ! zweight: weight for each level to be applied (=1. for no effect) |
|---|
| 585 | |
|---|
| 586 | fname = 'compute_zint4D' |
|---|
| 587 | |
|---|
| 588 | DO i=1,d1 |
|---|
| 589 | DO j=1,d2 |
|---|
| 590 | DO l=1,d4 |
|---|
| 591 | CALL compute_vertint1D(var4D(i,j,:,l),d3, dlev(i,j,:,l), zweight(i,j,:,l), & |
|---|
| 592 | int3D(i,j,l)) |
|---|
| 593 | END DO |
|---|
| 594 | END DO |
|---|
| 595 | END DO |
|---|
| 596 | |
|---|
| 597 | RETURN |
|---|
| 598 | |
|---|
| 599 | END SUBROUTINE compute_zint4D |
|---|
| 600 | |
|---|
| 601 | SUBROUTINE compute_vertint1D(var, dz, deta, zweight, integral) |
|---|
| 602 | ! Subroutine to vertically integrate a 1D variable in any vertical coordinates |
|---|
| 603 | |
|---|
| 604 | IMPLICIT NONE |
|---|
| 605 | |
|---|
| 606 | INTEGER, INTENT(in) :: dz |
|---|
| 607 | REAL(r_k), DIMENSION(dz), INTENT(in) :: var, deta, zweight |
|---|
| 608 | REAL(r_k), INTENT(out) :: integral |
|---|
| 609 | |
|---|
| 610 | ! Local |
|---|
| 611 | INTEGER :: k |
|---|
| 612 | |
|---|
| 613 | !!!!!!! Variables |
|---|
| 614 | ! var: vertical variable to integrate |
|---|
| 615 | ! dz: vertical dimension |
|---|
| 616 | ! deta: eta-levels difference between layers |
|---|
| 617 | ! zweight: weight for each level to be applied (=1. for no effect) |
|---|
| 618 | |
|---|
| 619 | fname = 'compute_vertint1D' |
|---|
| 620 | |
|---|
| 621 | ! integral=0. |
|---|
| 622 | ! DO k=1,dz |
|---|
| 623 | ! integral = integral + var(k)*deta(k) |
|---|
| 624 | ! END DO |
|---|
| 625 | integral = SUM(var*deta*zweight) |
|---|
| 626 | |
|---|
| 627 | RETURN |
|---|
| 628 | |
|---|
| 629 | END SUBROUTINE compute_vertint1D |
|---|
| 630 | |
|---|
| 631 | SUBROUTINE compute_tv4d(ta,qv,tv,d1,d2,d3,d4) |
|---|
| 632 | ! 4D calculation of virtual temperaure |
|---|
| 633 | |
|---|
| 634 | IMPLICIT NONE |
|---|
| 635 | |
|---|
| 636 | INTEGER, INTENT(in) :: d1, d2, d3, d4 |
|---|
| 637 | REAL(r_k), DIMENSION(d1,d2,d3,d4), INTENT(in) :: ta, qv |
|---|
| 638 | REAL(r_k), DIMENSION(d1,d2,d3,d4), INTENT(out) :: tv |
|---|
| 639 | |
|---|
| 640 | ! Variables |
|---|
| 641 | ! ta: temperature [K] |
|---|
| 642 | ! qv: mixing ratio [kgkg-1] |
|---|
| 643 | ! tv: virtual temperature |
|---|
| 644 | |
|---|
| 645 | tv = ta*(oneRK+(qv/epsilonv))/(oneRK+qv) |
|---|
| 646 | |
|---|
| 647 | END SUBROUTINE compute_tv4d |
|---|
| 648 | |
|---|
| 649 | FUNCTION VirtualTemp1D (ta,qv) result (tv) |
|---|
| 650 | ! 1D calculation of virtual temperaure |
|---|
| 651 | |
|---|
| 652 | IMPLICIT NONE |
|---|
| 653 | |
|---|
| 654 | REAL(r_k), INTENT(in) :: ta, qv |
|---|
| 655 | REAL(r_k) :: tv |
|---|
| 656 | |
|---|
| 657 | ! Variables |
|---|
| 658 | ! ta: temperature [K] |
|---|
| 659 | ! qv: mixing ratio [kgkg-1] |
|---|
| 660 | |
|---|
| 661 | tv = ta*(oneRK+(qv/epsilonv))/(oneRK+qv) |
|---|
| 662 | |
|---|
| 663 | END FUNCTION VirtualTemp1D |
|---|
| 664 | |
|---|
| 665 | ! ---- BEGIN modified from module_diag_afwa.F ---- ! |
|---|
| 666 | |
|---|
| 667 | !!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!!! |
|---|
| 668 | !~ |
|---|
| 669 | !~ Name: |
|---|
| 670 | !~ Theta |
|---|
| 671 | !~ |
|---|
| 672 | !~ Description: |
|---|
| 673 | !~ This function calculates potential temperature as defined by |
|---|
| 674 | !~ Poisson's equation, given temperature and pressure ( hPa ). |
|---|
| 675 | !~ |
|---|
| 676 | !!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!!! |
|---|
| 677 | FUNCTION Theta ( t, p ) |
|---|
| 678 | |
|---|
| 679 | IMPLICIT NONE |
|---|
| 680 | |
|---|
| 681 | !~ Variable declaration |
|---|
| 682 | ! -------------------- |
|---|
| 683 | REAL(r_k), INTENT ( IN ) :: t |
|---|
| 684 | REAL(r_k), INTENT ( IN ) :: p |
|---|
| 685 | REAL(r_k) :: theta |
|---|
| 686 | |
|---|
| 687 | ! Using WRF values |
|---|
| 688 | !REAL :: Rd ! Dry gas constant |
|---|
| 689 | !REAL :: Cp ! Specific heat of dry air at constant pressure |
|---|
| 690 | !REAL :: p00 ! Standard pressure ( 1000 hPa ) |
|---|
| 691 | REAL(r_k) :: Rd, p00 |
|---|
| 692 | |
|---|
| 693 | !Rd = 287.04 |
|---|
| 694 | !Cp = 1004.67 |
|---|
| 695 | !p00 = 1000.00 |
|---|
| 696 | |
|---|
| 697 | Rd = r_d |
|---|
| 698 | p00 = p1000mb/100. |
|---|
| 699 | |
|---|
| 700 | !~ Poisson's equation |
|---|
| 701 | ! ------------------ |
|---|
| 702 | theta = t * ( (p00/p)**(Rd/Cp) ) |
|---|
| 703 | |
|---|
| 704 | END FUNCTION Theta |
|---|
| 705 | |
|---|
| 706 | !!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!!! |
|---|
| 707 | !~ |
|---|
| 708 | !~ Name: |
|---|
| 709 | !~ Thetae |
|---|
| 710 | !~ |
|---|
| 711 | !~ Description: |
|---|
| 712 | !~ This function returns equivalent potential temperature using the |
|---|
| 713 | !~ method described in Bolton 1980, Monthly Weather Review, equation 43. |
|---|
| 714 | !~ |
|---|
| 715 | !!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!!! |
|---|
| 716 | FUNCTION Thetae ( tK, p, rh, mixr ) |
|---|
| 717 | |
|---|
| 718 | IMPLICIT NONE |
|---|
| 719 | |
|---|
| 720 | !~ Variable Declarations |
|---|
| 721 | ! --------------------- |
|---|
| 722 | REAL(r_k) :: tK ! Temperature ( K ) |
|---|
| 723 | REAL(r_k) :: p ! Pressure ( hPa ) |
|---|
| 724 | REAL(r_k) :: rh ! Relative humidity |
|---|
| 725 | REAL(r_k) :: mixr ! Mixing Ratio ( kg kg^-1) |
|---|
| 726 | REAL(r_k) :: te ! Equivalent temperature ( K ) |
|---|
| 727 | REAL(r_k) :: thetae ! Equivalent potential temperature |
|---|
| 728 | |
|---|
| 729 | ! Using WRF values |
|---|
| 730 | !REAL, PARAMETER :: R = 287.04 ! Universal gas constant (J/deg kg) |
|---|
| 731 | !REAL, PARAMETER :: P0 = 1000.0 ! Standard pressure at surface (hPa) |
|---|
| 732 | REAL(r_k) :: R, p00, Lv |
|---|
| 733 | !REAL, PARAMETER :: lv = 2.54*(10**6) ! Latent heat of vaporization |
|---|
| 734 | ! (J kg^-1) |
|---|
| 735 | !REAL, PARAMETER :: cp = 1004.67 ! Specific heat of dry air constant |
|---|
| 736 | ! at pressure (J/deg kg) |
|---|
| 737 | REAL(r_k) :: tlc ! LCL temperature |
|---|
| 738 | |
|---|
| 739 | R = r_d |
|---|
| 740 | p00 = p1000mb/100. |
|---|
| 741 | lv = XLV |
|---|
| 742 | |
|---|
| 743 | !~ Calculate the temperature of the LCL |
|---|
| 744 | ! ------------------------------------ |
|---|
| 745 | tlc = TLCL ( tK, rh ) |
|---|
| 746 | |
|---|
| 747 | !~ Calculate theta-e |
|---|
| 748 | ! ----------------- |
|---|
| 749 | thetae = (tK * (p00/p)**( (R/Cp)*(1.- ( (.28E-3)*mixr*1000.) ) ) )* & |
|---|
| 750 | exp( (((3.376/tlc)-.00254))*& |
|---|
| 751 | (mixr*1000.*(1.+(.81E-3)*mixr*1000.)) ) |
|---|
| 752 | |
|---|
| 753 | END FUNCTION Thetae |
|---|
| 754 | |
|---|
| 755 | !!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!!! |
|---|
| 756 | !~ |
|---|
| 757 | !~ Name: |
|---|
| 758 | !~ The2T.f90 |
|---|
| 759 | !~ |
|---|
| 760 | !~ Description: |
|---|
| 761 | !~ This function returns the temperature at any pressure level along a |
|---|
| 762 | !~ saturation adiabat by iteratively solving for it from the parcel |
|---|
| 763 | !~ thetae. |
|---|
| 764 | !~ |
|---|
| 765 | !~ Dependencies: |
|---|
| 766 | !~ function thetae.f90 |
|---|
| 767 | !~ |
|---|
| 768 | !!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!!! |
|---|
| 769 | FUNCTION The2T ( thetaeK, pres, flag ) result ( tparcel ) |
|---|
| 770 | |
|---|
| 771 | IMPLICIT NONE |
|---|
| 772 | |
|---|
| 773 | !~ Variable Declaration |
|---|
| 774 | ! -------------------- |
|---|
| 775 | REAL(r_k), INTENT ( IN ) :: thetaeK |
|---|
| 776 | REAL(r_k), INTENT ( IN ) :: pres |
|---|
| 777 | LOGICAL, INTENT ( INOUT ) :: flag |
|---|
| 778 | REAL(r_k) :: tparcel |
|---|
| 779 | |
|---|
| 780 | REAL(r_k) :: thetaK |
|---|
| 781 | REAL(r_k) :: tovtheta |
|---|
| 782 | REAL(r_k) :: tcheck |
|---|
| 783 | REAL(r_k) :: svpr, svpr2 |
|---|
| 784 | REAL(r_k) :: smixr, smixr2 |
|---|
| 785 | REAL(r_k) :: thetae_check, thetae_check2 |
|---|
| 786 | REAL(r_k) :: tguess_2, correction |
|---|
| 787 | |
|---|
| 788 | LOGICAL :: found |
|---|
| 789 | INTEGER :: iter |
|---|
| 790 | |
|---|
| 791 | ! Using WRF values |
|---|
| 792 | !REAL :: R ! Dry gas constant |
|---|
| 793 | !REAL :: Cp ! Specific heat for dry air |
|---|
| 794 | !REAL :: kappa ! Rd / Cp |
|---|
| 795 | !REAL :: Lv ! Latent heat of vaporization at 0 deg. C |
|---|
| 796 | REAL(r_k) :: R, kappa, Lv |
|---|
| 797 | |
|---|
| 798 | R = r_d |
|---|
| 799 | Lv = XLV |
|---|
| 800 | !R = 287.04 |
|---|
| 801 | !Cp = 1004.67 |
|---|
| 802 | Kappa = R/Cp |
|---|
| 803 | !Lv = 2.500E+6 |
|---|
| 804 | |
|---|
| 805 | !~ Make initial guess for temperature of the parcel |
|---|
| 806 | ! ------------------------------------------------ |
|---|
| 807 | tovtheta = (pres/100000.0)**(r/cp) |
|---|
| 808 | tparcel = thetaeK/exp(lv*.012/(cp*295.))*tovtheta |
|---|
| 809 | |
|---|
| 810 | iter = 1 |
|---|
| 811 | found = .false. |
|---|
| 812 | flag = .false. |
|---|
| 813 | |
|---|
| 814 | DO |
|---|
| 815 | IF ( iter > 105 ) EXIT |
|---|
| 816 | |
|---|
| 817 | tguess_2 = tparcel + REAL ( 1 ) |
|---|
| 818 | |
|---|
| 819 | svpr = 6.122 * exp ( (17.67*(tparcel-273.15)) / (tparcel-29.66) ) |
|---|
| 820 | smixr = ( 0.622*svpr ) / ( (pres/100.0)-svpr ) |
|---|
| 821 | svpr2 = 6.122 * exp ( (17.67*(tguess_2-273.15)) / (tguess_2-29.66) ) |
|---|
| 822 | smixr2 = ( 0.622*svpr2 ) / ( (pres/100.0)-svpr2 ) |
|---|
| 823 | |
|---|
| 824 | ! ------------------------------------------------------------------ ~! |
|---|
| 825 | !~ When this function was orinially written, the final parcel ~! |
|---|
| 826 | !~ temperature check was based off of the parcel temperature and ~! |
|---|
| 827 | !~ not the theta-e it produced. As there are multiple temperature- ~! |
|---|
| 828 | !~ mixing ratio combinations that can produce a single theta-e value, ~! |
|---|
| 829 | !~ we change the check to be based off of the resultant theta-e ~! |
|---|
| 830 | !~ value. This seems to be the most accurate way of backing out ~! |
|---|
| 831 | !~ temperature from theta-e. ~! |
|---|
| 832 | !~ ~! |
|---|
| 833 | !~ Rentschler, April 2010 ~! |
|---|
| 834 | ! ------------------------------------------------------------------ ! |
|---|
| 835 | |
|---|
| 836 | !~ Old way... |
|---|
| 837 | !thetaK = thetaeK / EXP (lv * smixr /(cp*tparcel) ) |
|---|
| 838 | !tcheck = thetaK * tovtheta |
|---|
| 839 | |
|---|
| 840 | !~ New way |
|---|
| 841 | thetae_check = Thetae ( tparcel, pres/100., 100., smixr ) |
|---|
| 842 | thetae_check2 = Thetae ( tguess_2, pres/100., 100., smixr2 ) |
|---|
| 843 | |
|---|
| 844 | !~ Whew doggies - that there is some accuracy... |
|---|
| 845 | !IF ( ABS (tparcel-tcheck) < .05) THEN |
|---|
| 846 | IF ( ABS (thetaeK-thetae_check) < .001) THEN |
|---|
| 847 | found = .true. |
|---|
| 848 | flag = .true. |
|---|
| 849 | EXIT |
|---|
| 850 | END IF |
|---|
| 851 | |
|---|
| 852 | !~ Old |
|---|
| 853 | !tparcel = tparcel + (tcheck - tparcel)*.3 |
|---|
| 854 | |
|---|
| 855 | !~ New |
|---|
| 856 | correction = ( thetaeK-thetae_check ) / ( thetae_check2-thetae_check ) |
|---|
| 857 | tparcel = tparcel + correction |
|---|
| 858 | |
|---|
| 859 | iter = iter + 1 |
|---|
| 860 | END DO |
|---|
| 861 | |
|---|
| 862 | !IF ( .not. found ) THEN |
|---|
| 863 | ! print*, "Warning! Thetae to temperature calculation did not converge!" |
|---|
| 864 | ! print*, "Thetae ", thetaeK, "Pressure ", pres |
|---|
| 865 | !END IF |
|---|
| 866 | |
|---|
| 867 | END FUNCTION The2T |
|---|
| 868 | |
|---|
| 869 | !!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!!! |
|---|
| 870 | !~ |
|---|
| 871 | !~ Name: |
|---|
| 872 | !~ VirtualTemperature |
|---|
| 873 | !~ |
|---|
| 874 | !~ Description: |
|---|
| 875 | !~ This function returns virtual temperature given temperature ( K ) |
|---|
| 876 | !~ and mixing ratio. |
|---|
| 877 | !~ |
|---|
| 878 | !!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!!! |
|---|
| 879 | FUNCTION VirtualTemperature ( tK, w ) result ( Tv ) |
|---|
| 880 | |
|---|
| 881 | IMPLICIT NONE |
|---|
| 882 | |
|---|
| 883 | !~ Variable declaration |
|---|
| 884 | real(r_k), intent ( in ) :: tK !~ Temperature |
|---|
| 885 | real(r_k), intent ( in ) :: w !~ Mixing ratio ( kg kg^-1 ) |
|---|
| 886 | real(r_k) :: Tv !~ Virtual temperature |
|---|
| 887 | |
|---|
| 888 | Tv = tK * ( 1.0 + (w/0.622) ) / ( 1.0 + w ) |
|---|
| 889 | |
|---|
| 890 | END FUNCTION VirtualTemperature |
|---|
| 891 | |
|---|
| 892 | !!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!!! |
|---|
| 893 | !~ |
|---|
| 894 | !~ Name: |
|---|
| 895 | !~ SaturationMixingRatio |
|---|
| 896 | !~ |
|---|
| 897 | !~ Description: |
|---|
| 898 | !~ This function calculates saturation mixing ratio given the |
|---|
| 899 | !~ temperature ( K ) and the ambient pressure ( Pa ). Uses |
|---|
| 900 | !~ approximation of saturation vapor pressure. |
|---|
| 901 | !~ |
|---|
| 902 | !~ References: |
|---|
| 903 | !~ Bolton (1980), Monthly Weather Review, pg. 1047, Eq. 10 |
|---|
| 904 | !~ |
|---|
| 905 | !!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!!! |
|---|
| 906 | FUNCTION SaturationMixingRatio ( tK, p ) result ( ws ) |
|---|
| 907 | |
|---|
| 908 | IMPLICIT NONE |
|---|
| 909 | |
|---|
| 910 | REAL(r_k), INTENT ( IN ) :: tK |
|---|
| 911 | REAL(r_k), INTENT ( IN ) :: p |
|---|
| 912 | REAL(r_k) :: ws |
|---|
| 913 | |
|---|
| 914 | REAL(r_k) :: es |
|---|
| 915 | |
|---|
| 916 | es = 6.122 * exp ( (17.67*(tK-273.15))/ (tK-29.66) ) |
|---|
| 917 | ws = ( 0.622*es ) / ( (p/100.0)-es ) |
|---|
| 918 | |
|---|
| 919 | END FUNCTION SaturationMixingRatio |
|---|
| 920 | |
|---|
| 921 | !!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!!! |
|---|
| 922 | !~ |
|---|
| 923 | !~ Name: |
|---|
| 924 | !~ tlcl |
|---|
| 925 | !~ |
|---|
| 926 | !~ Description: |
|---|
| 927 | !~ This function calculates the temperature of a parcel of air would have |
|---|
| 928 | !~ if lifed dry adiabatically to it's lifting condensation level (lcl). |
|---|
| 929 | !~ |
|---|
| 930 | !~ References: |
|---|
| 931 | !~ Bolton (1980), Monthly Weather Review, pg. 1048, Eq. 22 |
|---|
| 932 | !~ |
|---|
| 933 | !!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!!! |
|---|
| 934 | FUNCTION TLCL ( tk, rh ) |
|---|
| 935 | |
|---|
| 936 | IMPLICIT NONE |
|---|
| 937 | |
|---|
| 938 | REAL(r_k), INTENT ( IN ) :: tK !~ Temperature ( K ) |
|---|
| 939 | REAL(r_k), INTENT ( IN ) :: rh !~ Relative Humidity ( % ) |
|---|
| 940 | REAL(r_k) :: tlcl |
|---|
| 941 | |
|---|
| 942 | REAL(r_k) :: denom, term1, term2 |
|---|
| 943 | |
|---|
| 944 | term1 = 1.0 / ( tK - 55.0 ) |
|---|
| 945 | !! Lluis |
|---|
| 946 | ! IF ( rh > REAL (0) ) THEN |
|---|
| 947 | IF ( rh > zeroRK ) THEN |
|---|
| 948 | term2 = ( LOG (rh/100.0) / 2840.0 ) |
|---|
| 949 | ELSE |
|---|
| 950 | term2 = ( LOG (0.001/oneRK) / 2840.0 ) |
|---|
| 951 | END IF |
|---|
| 952 | denom = term1 - term2 |
|---|
| 953 | !! Lluis |
|---|
| 954 | ! tlcl = ( 1.0 / denom ) + REAL ( 55 ) |
|---|
| 955 | tlcl = ( oneRK / denom ) + 55*oneRK |
|---|
| 956 | |
|---|
| 957 | END FUNCTION TLCL |
|---|
| 958 | |
|---|
| 959 | FUNCTION var_cape_afwa1D(nz, tk, rhv, p, hgt, sfc, cape, cin, zlfc, plfc, lidx, parcel) RESULT (ostat) |
|---|
| 960 | ! Function to compute cape on a 1D column following implementation in phys/module_diag_afwa.F |
|---|
| 961 | |
|---|
| 962 | IMPLICIT NONE |
|---|
| 963 | |
|---|
| 964 | INTEGER, INTENT(in) :: nz, sfc |
|---|
| 965 | REAL(r_k), DIMENSION(nz), INTENT(in) :: tk, rhv, p, hgt |
|---|
| 966 | REAL(r_k), INTENT(out) :: cape, cin, zlfc, plfc, lidx |
|---|
| 967 | INTEGER :: ostat |
|---|
| 968 | INTEGER, INTENT(in) :: parcel |
|---|
| 969 | |
|---|
| 970 | ! Local |
|---|
| 971 | !~ Derived profile variables |
|---|
| 972 | ! ------------------------- |
|---|
| 973 | REAL(r_k), DIMENSION(nz) :: rh, ws, w, dTvK, buoy |
|---|
| 974 | REAL(r_k) :: tlclK, plcl, nbuoy, pbuoy |
|---|
| 975 | |
|---|
| 976 | !~ Source parcel information |
|---|
| 977 | ! ------------------------- |
|---|
| 978 | REAL(r_k) :: srctK, srcrh, srcws, srcw, srcp, & |
|---|
| 979 | srctheta, srcthetaeK |
|---|
| 980 | INTEGER :: srclev |
|---|
| 981 | REAL(r_k) :: spdiff |
|---|
| 982 | |
|---|
| 983 | !~ Parcel variables |
|---|
| 984 | ! ---------------- |
|---|
| 985 | REAL(r_k) :: ptK, ptvK, tvK, pw |
|---|
| 986 | |
|---|
| 987 | !~ Other utility variables |
|---|
| 988 | ! ----------------------- |
|---|
| 989 | INTEGER :: i, j, k |
|---|
| 990 | INTEGER :: lfclev |
|---|
| 991 | INTEGER :: prcl |
|---|
| 992 | INTEGER :: mlev |
|---|
| 993 | INTEGER :: lyrcnt |
|---|
| 994 | LOGICAL :: flag |
|---|
| 995 | LOGICAL :: wflag |
|---|
| 996 | REAL(r_k) :: freeze |
|---|
| 997 | REAL(r_k) :: pdiff |
|---|
| 998 | REAL(r_k) :: pm, pu, pd |
|---|
| 999 | REAL(r_k) :: lidxu |
|---|
| 1000 | REAL(r_k) :: lidxd |
|---|
| 1001 | |
|---|
| 1002 | REAL(r_k), PARAMETER :: Rd = r_d |
|---|
| 1003 | REAL(r_k), PARAMETER :: RUNDEF = -9.999E30 |
|---|
| 1004 | |
|---|
| 1005 | !!!!!!! Variables |
|---|
| 1006 | ! nz: Number of vertical levels |
|---|
| 1007 | ! sfc: Surface level in the profile |
|---|
| 1008 | ! tk: Temperature profile [K] |
|---|
| 1009 | ! rhv: Relative Humidity profile [1] |
|---|
| 1010 | ! rh: Relative Humidity profile [%] |
|---|
| 1011 | ! p: Pressure profile [Pa] |
|---|
| 1012 | ! hgt: Geopotential height profile [gpm] |
|---|
| 1013 | ! cape: CAPE [Jkg-1] |
|---|
| 1014 | ! cin: CIN [Jkg-1] |
|---|
| 1015 | ! zlfc: LFC Height [gpm] |
|---|
| 1016 | ! plfc: LFC Pressure [Pa] |
|---|
| 1017 | ! lidx: Lifted index |
|---|
| 1018 | ! FROM: https://en.wikipedia.org/wiki/Lifted_index |
|---|
| 1019 | ! lidx >= 6: Very Stable Conditions |
|---|
| 1020 | ! 6 > lidx > 1: Stable Conditions, Thunderstorms Not Likely |
|---|
| 1021 | ! 0 > lidx > -2: Slightly Unstable, Thunderstorms Possible, With Lifting Mechanism (i.e., cold front, daytime heating, ...) |
|---|
| 1022 | ! -2 > lidx > -6: Unstable, Thunderstorms Likely, Some Severe With Lifting Mechanism |
|---|
| 1023 | ! -6 > lidx: Very Unstable, Severe Thunderstorms Likely With Lifting Mechanism |
|---|
| 1024 | ! ostat: Function return status (Nonzero is bad) |
|---|
| 1025 | ! parcel: |
|---|
| 1026 | ! Most Unstable = 1 (default) |
|---|
| 1027 | ! Mean layer = 2 |
|---|
| 1028 | ! Surface based = 3 |
|---|
| 1029 | !~ Derived profile variables |
|---|
| 1030 | ! ------------------------- |
|---|
| 1031 | ! ws: Saturation mixing ratio |
|---|
| 1032 | ! w: Mixing ratio |
|---|
| 1033 | ! dTvK: Parcel / ambient Tv difference |
|---|
| 1034 | ! buoy: Buoyancy |
|---|
| 1035 | ! tlclK: LCL temperature [K] |
|---|
| 1036 | ! plcl: LCL pressure [Pa] |
|---|
| 1037 | ! nbuoy: Negative buoyancy |
|---|
| 1038 | ! pbuoy: Positive buoyancy |
|---|
| 1039 | |
|---|
| 1040 | !~ Source parcel information |
|---|
| 1041 | ! ------------------------- |
|---|
| 1042 | ! srctK: Source parcel temperature [K] |
|---|
| 1043 | ! srcrh: Source parcel rh [%] |
|---|
| 1044 | ! srcws: Source parcel sat. mixing ratio |
|---|
| 1045 | ! srcw: Source parcel mixing ratio |
|---|
| 1046 | ! srcp: Source parcel pressure [Pa] |
|---|
| 1047 | ! srctheta: Source parcel theta [K] |
|---|
| 1048 | ! srcthetaeK: Source parcel theta-e [K] |
|---|
| 1049 | ! srclev: Level of the source parcel |
|---|
| 1050 | ! spdiff: Pressure difference |
|---|
| 1051 | |
|---|
| 1052 | !~ Parcel variables |
|---|
| 1053 | ! ---------------- |
|---|
| 1054 | ! ptK: Parcel temperature [K] |
|---|
| 1055 | ! ptvK: Parcel virtual temperature [K] |
|---|
| 1056 | ! tvK: Ambient virtual temperature [K] |
|---|
| 1057 | ! pw: Parcel mixing ratio |
|---|
| 1058 | |
|---|
| 1059 | !~ Other utility variables |
|---|
| 1060 | ! ----------------------- |
|---|
| 1061 | ! lfclev: Level of LFC |
|---|
| 1062 | ! prcl: Internal parcel type indicator |
|---|
| 1063 | ! mlev: Level for ML calculation |
|---|
| 1064 | ! lyrcnt: Number of layers in mean layer |
|---|
| 1065 | ! flag: Dummy flag |
|---|
| 1066 | ! wflag: Saturation flag |
|---|
| 1067 | ! freeze: Water loading multiplier |
|---|
| 1068 | ! pdiff: Pressure difference between levs |
|---|
| 1069 | ! pm, pu, pd: Middle, upper, lower pressures |
|---|
| 1070 | ! lidxu: Lifted index at upper level |
|---|
| 1071 | ! lidxd: Lifted index at lower level |
|---|
| 1072 | |
|---|
| 1073 | fname = 'var_cape_afwa' |
|---|
| 1074 | |
|---|
| 1075 | !~ Initialize variables |
|---|
| 1076 | ! -------------------- |
|---|
| 1077 | rh = rhv*100. |
|---|
| 1078 | ostat = 0 |
|---|
| 1079 | CAPE = zeroRK |
|---|
| 1080 | CIN = zeroRK |
|---|
| 1081 | ZLFC = RUNDEF |
|---|
| 1082 | PLFC = RUNDEF |
|---|
| 1083 | |
|---|
| 1084 | !~ Look for submitted parcel definition |
|---|
| 1085 | !~ 1 = Most unstable |
|---|
| 1086 | !~ 2 = Mean layer |
|---|
| 1087 | !~ 3 = Surface based |
|---|
| 1088 | ! ------------------------------------- |
|---|
| 1089 | IF ( parcel > 3 .or. parcel < 1 ) THEN |
|---|
| 1090 | prcl = 1 |
|---|
| 1091 | ELSE |
|---|
| 1092 | prcl = parcel |
|---|
| 1093 | END IF |
|---|
| 1094 | |
|---|
| 1095 | !~ Initalize our parcel to be (sort of) surface based. Because of |
|---|
| 1096 | !~ issues we've been observing in the WRF model, specifically with |
|---|
| 1097 | !~ excessive surface moisture values at the surface, using a true |
|---|
| 1098 | !~ surface based parcel is resulting a more unstable environment |
|---|
| 1099 | !~ than is actually occuring. To address this, our surface parcel |
|---|
| 1100 | !~ is now going to be defined as the parcel between 25-50 hPa |
|---|
| 1101 | !~ above the surface. UPDATE - now that this routine is in WRF, |
|---|
| 1102 | !~ going to trust surface info. GAC 20140415 |
|---|
| 1103 | ! ---------------------------------------------------------------- |
|---|
| 1104 | |
|---|
| 1105 | !~ Compute mixing ratio values for the layer |
|---|
| 1106 | ! ----------------------------------------- |
|---|
| 1107 | DO k = sfc, nz |
|---|
| 1108 | ws ( k ) = SaturationMixingRatio ( tK(k), p(k) ) |
|---|
| 1109 | w ( k ) = ( rh(k)/100.0 ) * ws ( k ) |
|---|
| 1110 | END DO |
|---|
| 1111 | |
|---|
| 1112 | srclev = sfc |
|---|
| 1113 | srctK = tK ( sfc ) |
|---|
| 1114 | srcrh = rh ( sfc ) |
|---|
| 1115 | srcp = p ( sfc ) |
|---|
| 1116 | srcws = ws ( sfc ) |
|---|
| 1117 | srcw = w ( sfc ) |
|---|
| 1118 | srctheta = Theta ( tK(sfc), p(sfc)/100.0 ) |
|---|
| 1119 | |
|---|
| 1120 | !~ Compute the profile mixing ratio. If the parcel is the MU parcel, |
|---|
| 1121 | !~ define our parcel to be the most unstable parcel within the lowest |
|---|
| 1122 | !~ 180 mb. |
|---|
| 1123 | ! ------------------------------------------------------------------- |
|---|
| 1124 | mlev = sfc + 1 |
|---|
| 1125 | DO k = sfc + 1, nz |
|---|
| 1126 | |
|---|
| 1127 | !~ Identify the last layer within 100 hPa of the surface |
|---|
| 1128 | ! ----------------------------------------------------- |
|---|
| 1129 | pdiff = ( p (sfc) - p (k) ) / REAL ( 100 ) |
|---|
| 1130 | IF ( pdiff <= REAL (100) ) mlev = k |
|---|
| 1131 | |
|---|
| 1132 | !~ If we've made it past the lowest 180 hPa, exit the loop |
|---|
| 1133 | ! ------------------------------------------------------- |
|---|
| 1134 | IF ( pdiff >= REAL (180) ) EXIT |
|---|
| 1135 | |
|---|
| 1136 | IF ( prcl == 1 ) THEN |
|---|
| 1137 | !IF ( (p(k) > 70000.0) .and. (w(k) > srcw) ) THEN |
|---|
| 1138 | IF ( (w(k) > srcw) ) THEN |
|---|
| 1139 | srctheta = Theta ( tK(k), p(k)/100.0 ) |
|---|
| 1140 | srcw = w ( k ) |
|---|
| 1141 | srclev = k |
|---|
| 1142 | srctK = tK ( k ) |
|---|
| 1143 | srcrh = rh ( k ) |
|---|
| 1144 | srcp = p ( k ) |
|---|
| 1145 | END IF |
|---|
| 1146 | END IF |
|---|
| 1147 | |
|---|
| 1148 | END DO |
|---|
| 1149 | |
|---|
| 1150 | !~ If we want the mean layer parcel, compute the mean values in the |
|---|
| 1151 | !~ lowest 100 hPa. |
|---|
| 1152 | ! ---------------------------------------------------------------- |
|---|
| 1153 | lyrcnt = mlev - sfc + 1 |
|---|
| 1154 | IF ( prcl == 2 ) THEN |
|---|
| 1155 | |
|---|
| 1156 | srclev = sfc |
|---|
| 1157 | srctK = SUM ( tK (sfc:mlev) ) / REAL ( lyrcnt ) |
|---|
| 1158 | srcw = SUM ( w (sfc:mlev) ) / REAL ( lyrcnt ) |
|---|
| 1159 | srcrh = SUM ( rh (sfc:mlev) ) / REAL ( lyrcnt ) |
|---|
| 1160 | srcp = SUM ( p (sfc:mlev) ) / REAL ( lyrcnt ) |
|---|
| 1161 | srctheta = Theta ( srctK, srcp/100. ) |
|---|
| 1162 | |
|---|
| 1163 | END IF |
|---|
| 1164 | |
|---|
| 1165 | srcthetaeK = Thetae ( srctK, srcp/100.0, srcrh, srcw ) |
|---|
| 1166 | |
|---|
| 1167 | !~ Calculate temperature and pressure of the LCL |
|---|
| 1168 | ! --------------------------------------------- |
|---|
| 1169 | tlclK = TLCL ( tK(srclev), rh(srclev) ) |
|---|
| 1170 | plcl = p(srclev) * ( (tlclK/tK(srclev))**(Cp/Rd) ) |
|---|
| 1171 | |
|---|
| 1172 | !~ Now lift the parcel |
|---|
| 1173 | ! ------------------- |
|---|
| 1174 | |
|---|
| 1175 | buoy = REAL ( 0 ) |
|---|
| 1176 | pw = srcw |
|---|
| 1177 | wflag = .false. |
|---|
| 1178 | DO k = srclev, nz |
|---|
| 1179 | IF ( p (k) <= plcl ) THEN |
|---|
| 1180 | |
|---|
| 1181 | !~ The first level after we pass the LCL, we're still going to |
|---|
| 1182 | !~ lift the parcel dry adiabatically, as we haven't added the |
|---|
| 1183 | !~ the required code to switch between the dry adiabatic and moist |
|---|
| 1184 | !~ adiabatic cooling. Since the dry version results in a greater |
|---|
| 1185 | !~ temperature loss, doing that for the first step so we don't over |
|---|
| 1186 | !~ guesstimate the instability. |
|---|
| 1187 | ! ---------------------------------------------------------------- |
|---|
| 1188 | |
|---|
| 1189 | IF ( wflag ) THEN |
|---|
| 1190 | flag = .false. |
|---|
| 1191 | |
|---|
| 1192 | !~ Above the LCL, our parcel is now undergoing moist adiabatic |
|---|
| 1193 | !~ cooling. Because of the latent heating being undergone as |
|---|
| 1194 | !~ the parcel rises above the LFC, must iterative solve for the |
|---|
| 1195 | !~ parcel temperature using equivalant potential temperature, |
|---|
| 1196 | !~ which is conserved during both dry adiabatic and |
|---|
| 1197 | !~ pseudoadiabatic displacements. |
|---|
| 1198 | ! -------------------------------------------------------------- |
|---|
| 1199 | ptK = The2T ( srcthetaeK, p(k), flag ) |
|---|
| 1200 | |
|---|
| 1201 | !~ Calculate the parcel mixing ratio, which is now changing |
|---|
| 1202 | !~ as we condense moisture out of the parcel, and is equivalent |
|---|
| 1203 | !~ to the saturation mixing ratio, since we are, in theory, at |
|---|
| 1204 | !~ saturation. |
|---|
| 1205 | ! ------------------------------------------------------------ |
|---|
| 1206 | pw = SaturationMixingRatio ( ptK, p(k) ) |
|---|
| 1207 | |
|---|
| 1208 | !~ Now we can calculate the virtual temperature of the parcel |
|---|
| 1209 | !~ and the surrounding environment to assess the buoyancy. |
|---|
| 1210 | ! ---------------------------------------------------------- |
|---|
| 1211 | ptvK = VirtualTemperature ( ptK, pw ) |
|---|
| 1212 | tvK = VirtualTemperature ( tK (k), w (k) ) |
|---|
| 1213 | |
|---|
| 1214 | !~ Modification to account for water loading |
|---|
| 1215 | ! ----------------------------------------- |
|---|
| 1216 | freeze = 0.033 * ( 263.15 - pTvK ) |
|---|
| 1217 | IF ( freeze > 1.0 ) freeze = 1.0 |
|---|
| 1218 | IF ( freeze < 0.0 ) freeze = 0.0 |
|---|
| 1219 | |
|---|
| 1220 | !~ Approximate how much of the water vapor has condensed out |
|---|
| 1221 | !~ of the parcel at this level |
|---|
| 1222 | ! --------------------------------------------------------- |
|---|
| 1223 | freeze = freeze * 333700.0 * ( srcw - pw ) / 1005.7 |
|---|
| 1224 | |
|---|
| 1225 | pTvK = pTvK - pTvK * ( srcw - pw ) + freeze |
|---|
| 1226 | dTvK ( k ) = ptvK - tvK |
|---|
| 1227 | buoy ( k ) = g * ( dTvK ( k ) / tvK ) |
|---|
| 1228 | |
|---|
| 1229 | ELSE |
|---|
| 1230 | |
|---|
| 1231 | !~ Since the theta remains constant whilst undergoing dry |
|---|
| 1232 | !~ adiabatic processes, can back out the parcel temperature |
|---|
| 1233 | !~ from potential temperature below the LCL |
|---|
| 1234 | ! -------------------------------------------------------- |
|---|
| 1235 | ptK = srctheta / ( 100000.0/p(k) )**(Rd/Cp) |
|---|
| 1236 | |
|---|
| 1237 | !~ Grab the parcel virtual temperture, can use the source |
|---|
| 1238 | !~ mixing ratio since we are undergoing dry adiabatic cooling |
|---|
| 1239 | ! ---------------------------------------------------------- |
|---|
| 1240 | ptvK = VirtualTemperature ( ptK, srcw ) |
|---|
| 1241 | |
|---|
| 1242 | !~ Virtual temperature of the environment |
|---|
| 1243 | ! -------------------------------------- |
|---|
| 1244 | tvK = VirtualTemperature ( tK (k), w (k) ) |
|---|
| 1245 | |
|---|
| 1246 | !~ Buoyancy at this level |
|---|
| 1247 | ! ---------------------- |
|---|
| 1248 | dTvK ( k ) = ptvK - tvK |
|---|
| 1249 | buoy ( k ) = g * ( dtvK ( k ) / tvK ) |
|---|
| 1250 | |
|---|
| 1251 | wflag = .true. |
|---|
| 1252 | |
|---|
| 1253 | END IF |
|---|
| 1254 | |
|---|
| 1255 | ELSE |
|---|
| 1256 | |
|---|
| 1257 | !~ Since the theta remains constant whilst undergoing dry |
|---|
| 1258 | !~ adiabatic processes, can back out the parcel temperature |
|---|
| 1259 | !~ from potential temperature below the LCL |
|---|
| 1260 | ! -------------------------------------------------------- |
|---|
| 1261 | ptK = srctheta / ( 100000.0/p(k) )**(Rd/Cp) |
|---|
| 1262 | |
|---|
| 1263 | !~ Grab the parcel virtual temperture, can use the source |
|---|
| 1264 | !~ mixing ratio since we are undergoing dry adiabatic cooling |
|---|
| 1265 | ! ---------------------------------------------------------- |
|---|
| 1266 | ptvK = VirtualTemperature ( ptK, srcw ) |
|---|
| 1267 | |
|---|
| 1268 | !~ Virtual temperature of the environment |
|---|
| 1269 | ! -------------------------------------- |
|---|
| 1270 | tvK = VirtualTemperature ( tK (k), w (k) ) |
|---|
| 1271 | |
|---|
| 1272 | !~ Buoyancy at this level |
|---|
| 1273 | ! --------------------- |
|---|
| 1274 | dTvK ( k ) = ptvK - tvK |
|---|
| 1275 | buoy ( k ) = g * ( dtvK ( k ) / tvK ) |
|---|
| 1276 | |
|---|
| 1277 | END IF |
|---|
| 1278 | |
|---|
| 1279 | !~ Chirp |
|---|
| 1280 | ! ----- |
|---|
| 1281 | ! WRITE ( *,'(I15,6F15.3)' )k,p(k)/100.,ptK,pw*1000.,ptvK,tvK,buoy(k) |
|---|
| 1282 | |
|---|
| 1283 | END DO |
|---|
| 1284 | |
|---|
| 1285 | !~ Add up the buoyancies, find the LFC |
|---|
| 1286 | ! ----------------------------------- |
|---|
| 1287 | flag = .false. |
|---|
| 1288 | lfclev = -1 |
|---|
| 1289 | nbuoy = REAL ( 0 ) |
|---|
| 1290 | pbuoy = REAL ( 0 ) |
|---|
| 1291 | DO k = sfc + 1, nz |
|---|
| 1292 | IF ( tK (k) < 253.15 ) EXIT |
|---|
| 1293 | CAPE = CAPE + MAX ( buoy (k), 0.0 ) * ( hgt (k) - hgt (k-1) ) |
|---|
| 1294 | CIN = CIN + MIN ( buoy (k), 0.0 ) * ( hgt (k) - hgt (k-1) ) |
|---|
| 1295 | |
|---|
| 1296 | !~ If we've already passed the LFC |
|---|
| 1297 | ! ------------------------------- |
|---|
| 1298 | IF ( flag .and. buoy (k) > REAL (0) ) THEN |
|---|
| 1299 | pbuoy = pbuoy + buoy (k) |
|---|
| 1300 | END IF |
|---|
| 1301 | |
|---|
| 1302 | !~ We are buoyant now - passed the LFC |
|---|
| 1303 | ! ----------------------------------- |
|---|
| 1304 | IF ( .not. flag .and. buoy (k) > REAL (0) .and. p (k) < plcl ) THEN |
|---|
| 1305 | flag = .true. |
|---|
| 1306 | pbuoy = pbuoy + buoy (k) |
|---|
| 1307 | lfclev = k |
|---|
| 1308 | END IF |
|---|
| 1309 | |
|---|
| 1310 | !~ If we think we've passed the LFC, but encounter a negative layer |
|---|
| 1311 | !~ start adding it up. |
|---|
| 1312 | ! ---------------------------------------------------------------- |
|---|
| 1313 | IF ( flag .and. buoy (k) < REAL (0) ) THEN |
|---|
| 1314 | nbuoy = nbuoy + buoy (k) |
|---|
| 1315 | |
|---|
| 1316 | !~ If the accumulated negative buoyancy is greater than the |
|---|
| 1317 | !~ positive buoyancy, then we are capped off. Got to go higher |
|---|
| 1318 | !~ to find the LFC. Reset positive and negative buoyancy summations |
|---|
| 1319 | ! ---------------------------------------------------------------- |
|---|
| 1320 | IF ( ABS (nbuoy) > pbuoy ) THEN |
|---|
| 1321 | flag = .false. |
|---|
| 1322 | nbuoy = REAL ( 0 ) |
|---|
| 1323 | pbuoy = REAL ( 0 ) |
|---|
| 1324 | lfclev = -1 |
|---|
| 1325 | END IF |
|---|
| 1326 | END IF |
|---|
| 1327 | |
|---|
| 1328 | END DO |
|---|
| 1329 | |
|---|
| 1330 | !~ Calculate lifted index by interpolating difference between |
|---|
| 1331 | !~ parcel and ambient Tv to 500mb. |
|---|
| 1332 | ! ---------------------------------------------------------- |
|---|
| 1333 | DO k = sfc + 1, nz |
|---|
| 1334 | |
|---|
| 1335 | pm = 50000. |
|---|
| 1336 | pu = p ( k ) |
|---|
| 1337 | pd = p ( k - 1 ) |
|---|
| 1338 | |
|---|
| 1339 | !~ If we're already above 500mb just set lifted index to 0. |
|---|
| 1340 | !~ -------------------------------------------------------- |
|---|
| 1341 | IF ( pd .le. pm ) THEN |
|---|
| 1342 | lidx = zeroRK |
|---|
| 1343 | EXIT |
|---|
| 1344 | |
|---|
| 1345 | ELSEIF ( pu .le. pm .and. pd .gt. pm) THEN |
|---|
| 1346 | |
|---|
| 1347 | !~ Found trapping pressure: up, middle, down. |
|---|
| 1348 | !~ We are doing first order interpolation. |
|---|
| 1349 | ! ------------------------------------------ |
|---|
| 1350 | lidxu = -dTvK ( k ) * ( pu / 100000. ) ** (Rd/Cp) |
|---|
| 1351 | lidxd = -dTvK ( k-1 ) * ( pd / 100000. ) ** (Rd/Cp) |
|---|
| 1352 | lidx = ( lidxu * (pm-pd) + lidxd * (pu-pm) ) / (pu-pd) |
|---|
| 1353 | EXIT |
|---|
| 1354 | |
|---|
| 1355 | ENDIF |
|---|
| 1356 | |
|---|
| 1357 | END DO |
|---|
| 1358 | |
|---|
| 1359 | !~ Assuming the the LFC is at a pressure level for now |
|---|
| 1360 | ! --------------------------------------------------- |
|---|
| 1361 | IF ( lfclev > zeroRK ) THEN |
|---|
| 1362 | PLFC = p ( lfclev ) |
|---|
| 1363 | ZLFC = hgt ( lfclev ) |
|---|
| 1364 | END IF |
|---|
| 1365 | |
|---|
| 1366 | IF ( PLFC /= PLFC .OR. PLFC < zeroRK ) THEN |
|---|
| 1367 | PLFC = -oneRK |
|---|
| 1368 | ZLFC = -oneRK |
|---|
| 1369 | END IF |
|---|
| 1370 | |
|---|
| 1371 | IF ( CAPE /= CAPE ) cape = zeroRK |
|---|
| 1372 | |
|---|
| 1373 | IF ( CIN /= CIN ) cin = zeroRK |
|---|
| 1374 | |
|---|
| 1375 | !~ Chirp |
|---|
| 1376 | ! ----- |
|---|
| 1377 | ! WRITE ( *,* ) ' CAPE: ', cape, ' CIN: ', cin |
|---|
| 1378 | ! WRITE ( *,* ) ' LFC: ', ZLFC, ' PLFC: ', PLFC |
|---|
| 1379 | ! WRITE ( *,* ) '' |
|---|
| 1380 | ! WRITE ( *,* ) ' Exiting buoyancy.' |
|---|
| 1381 | ! WRITE ( *,* ) ' ==================================== ' |
|---|
| 1382 | ! WRITE ( *,* ) '' |
|---|
| 1383 | |
|---|
| 1384 | RETURN |
|---|
| 1385 | |
|---|
| 1386 | END FUNCTION var_cape_afwa1D |
|---|
| 1387 | |
|---|
| 1388 | ! ---- END modified from module_diag_afwa.F ---- ! |
|---|
| 1389 | |
|---|
| 1390 | SUBROUTINE compute_cape_afwa4D(ta, hur, press, zg, hgt, cape, cin, zlfc, plfc, li, parcelmethod, & |
|---|
| 1391 | d1, d2, d3, d4) |
|---|
| 1392 | ! Subroutine to use WRF phys/module_diag_afwa.F `buyoancy' subroutine to compute CAPE, CIN, ZLFC, PLFC, LI |
|---|
| 1393 | |
|---|
| 1394 | IMPLICIT NONE |
|---|
| 1395 | |
|---|
| 1396 | INTEGER, INTENT(in) :: d1, d2, d3, d4, parcelmethod |
|---|
| 1397 | REAL(r_k), DIMENSION(d1,d2,d3,d4), INTENT(in) :: ta, hur, press, zg |
|---|
| 1398 | REAL(r_k), DIMENSION(d1,d2), INTENT(in) :: hgt |
|---|
| 1399 | REAL(r_k), DIMENSION(d1,d2,d4), INTENT(out) :: cape, cin, zlfc, plfc, li |
|---|
| 1400 | |
|---|
| 1401 | ! Local |
|---|
| 1402 | INTEGER :: i, j, it |
|---|
| 1403 | INTEGER :: ofunc |
|---|
| 1404 | |
|---|
| 1405 | !!!!!!! Variables |
|---|
| 1406 | ! ta: air temperature [K] |
|---|
| 1407 | ! hur: relative humidity [%] |
|---|
| 1408 | ! press: air pressure [Pa] |
|---|
| 1409 | ! zg: geopotential height [gpm] |
|---|
| 1410 | ! hgt: topographical height [m] |
|---|
| 1411 | ! cape: Convective available potential energy [Jkg-1] |
|---|
| 1412 | ! cin: Convective inhibition [Jkg-1] |
|---|
| 1413 | ! zlfc: height at the Level of free convection [m] |
|---|
| 1414 | ! plfc: pressure at the Level of free convection [Pa] |
|---|
| 1415 | ! li: lifted index [1] |
|---|
| 1416 | ! parcelmethod: |
|---|
| 1417 | ! Most Unstable = 1 (default) |
|---|
| 1418 | ! Mean layer = 2 |
|---|
| 1419 | ! Surface based = 3 |
|---|
| 1420 | |
|---|
| 1421 | fname = 'compute_cape_afwa4D' |
|---|
| 1422 | |
|---|
| 1423 | DO i=1, d1 |
|---|
| 1424 | DO j=1, d2 |
|---|
| 1425 | DO it=1, d4 |
|---|
| 1426 | ofunc = var_cape_afwa1D(d3, ta(i,j,:,it), hur(i,j,:,it), press(i,j,:,it), zg(i,j,:,it), & |
|---|
| 1427 | 1, cape(i,j,it), cin(i,j,it), zlfc(i,j,it), plfc(i,j,it), li(i,j,it), parcelmethod) |
|---|
| 1428 | zlfc(i,j,it) = zlfc(i,j,it)/g - hgt(i,j) |
|---|
| 1429 | END DO |
|---|
| 1430 | END DO |
|---|
| 1431 | END DO |
|---|
| 1432 | |
|---|
| 1433 | RETURN |
|---|
| 1434 | |
|---|
| 1435 | END SUBROUTINE compute_cape_afwa4D |
|---|
| 1436 | |
|---|
| 1437 | END MODULE module_ForDiagnostics |
|---|