[2060] | 1 | ! |
---|
| 2 | ! |
---|
| 3 | ! |
---|
[2101] | 4 | SUBROUTINE thermcell_flux(ngrid,nlay,ptimestep,masse, & |
---|
[2132] | 5 | lmin,lmax,entr_star,detr_star, & |
---|
[2143] | 6 | f,rhobarz,zlev,zw2,fm,entr,detr) |
---|
[2060] | 7 | |
---|
| 8 | |
---|
[2127] | 9 | !=============================================================================== |
---|
[2143] | 10 | ! Purpose: deduction des flux |
---|
[2127] | 11 | ! |
---|
| 12 | ! Modif 2019/04 (AB alexandre.boissinot@lmd.jussieu.fr) |
---|
| 13 | ! |
---|
| 14 | !=============================================================================== |
---|
[2060] | 15 | |
---|
| 16 | USE print_control_mod, ONLY: prt_level |
---|
[2132] | 17 | USE thermcell_mod, ONLY: fomass_max, alpha_max |
---|
[2060] | 18 | |
---|
| 19 | IMPLICIT NONE |
---|
| 20 | |
---|
| 21 | |
---|
[2127] | 22 | !=============================================================================== |
---|
[2060] | 23 | ! Declaration |
---|
[2127] | 24 | !=============================================================================== |
---|
[2060] | 25 | |
---|
[2127] | 26 | ! Inputs: |
---|
| 27 | ! ------- |
---|
[2060] | 28 | |
---|
[2127] | 29 | INTEGER ngrid, nlay |
---|
[2060] | 30 | INTEGER lmin(ngrid) |
---|
| 31 | INTEGER lmax(ngrid) |
---|
| 32 | |
---|
[2101] | 33 | REAL entr_star(ngrid,nlay) |
---|
| 34 | REAL detr_star(ngrid,nlay) |
---|
| 35 | REAL zw2(ngrid,nlay+1) |
---|
| 36 | REAL zlev(ngrid,nlay+1) |
---|
| 37 | REAL masse(ngrid,nlay) |
---|
[2060] | 38 | REAL ptimestep |
---|
[2101] | 39 | REAL rhobarz(ngrid,nlay) |
---|
[2060] | 40 | REAL f(ngrid) |
---|
| 41 | |
---|
[2127] | 42 | ! Outputs: |
---|
| 43 | ! -------- |
---|
[2060] | 44 | |
---|
[2101] | 45 | REAL entr(ngrid,nlay) |
---|
| 46 | REAL detr(ngrid,nlay) |
---|
| 47 | REAL fm(ngrid,nlay+1) |
---|
[2060] | 48 | |
---|
[2127] | 49 | ! Local: |
---|
| 50 | ! ------ |
---|
[2060] | 51 | |
---|
[2127] | 52 | INTEGER ig, l, k |
---|
[2143] | 53 | INTEGER igout, lout ! Error grid point and level |
---|
[2060] | 54 | |
---|
[2132] | 55 | REAL zfm ! Mass flux such as updraft fraction is equal to its maximal authorized value alpha_max |
---|
[2127] | 56 | REAL f_old ! Save initial value of mass flux |
---|
| 57 | REAL eee0 ! Save initial value of entrainment |
---|
| 58 | REAL ddd0 ! Save initial value of detrainment |
---|
[2060] | 59 | REAL eee ! eee0 - layer mass * maximal authorized mass fraction / dt |
---|
| 60 | REAL ddd ! ddd0 - eee |
---|
[2127] | 61 | REAL zzz ! Temporary variable set to mass flux |
---|
[2143] | 62 | REAL fact |
---|
| 63 | REAL test |
---|
[2060] | 64 | |
---|
[2143] | 65 | INTEGER ncorecentr |
---|
| 66 | INTEGER ncorecdetr |
---|
| 67 | INTEGER nerrorequa |
---|
| 68 | INTEGER ncorecfact |
---|
| 69 | INTEGER ncorecalpha |
---|
[2060] | 70 | |
---|
| 71 | LOGICAL labort_physic |
---|
| 72 | |
---|
[2127] | 73 | !=============================================================================== |
---|
[2060] | 74 | ! Initialization |
---|
[2127] | 75 | !=============================================================================== |
---|
[2060] | 76 | |
---|
[2143] | 77 | nerrorequa = 0 |
---|
| 78 | ncorecentr = 0 |
---|
| 79 | ncorecdetr = 0 |
---|
| 80 | ncorecfact = 0 |
---|
[2060] | 81 | ncorecalpha = 0 |
---|
| 82 | |
---|
| 83 | entr(:,:) = 0. |
---|
| 84 | detr(:,:) = 0. |
---|
| 85 | fm(:,:) = 0. |
---|
| 86 | |
---|
[2143] | 87 | labort_physic = .false. |
---|
| 88 | |
---|
| 89 | fact = 0. |
---|
| 90 | |
---|
[2127] | 91 | !=============================================================================== |
---|
[2143] | 92 | ! Calcul de l'entrainement, du detrainement et du flux de masse |
---|
[2127] | 93 | !=============================================================================== |
---|
[2060] | 94 | |
---|
[2127] | 95 | !------------------------------------------------------------------------------- |
---|
[2060] | 96 | ! Multiplication par la norme issue de la relation de fermeture |
---|
[2127] | 97 | !------------------------------------------------------------------------------- |
---|
[2060] | 98 | |
---|
[2101] | 99 | DO l=1,nlay |
---|
[2127] | 100 | entr(:,l) = f(:) * entr_star(:,l) |
---|
[2060] | 101 | detr(:,l) = f(:) * detr_star(:,l) |
---|
| 102 | ENDDO |
---|
| 103 | |
---|
[2127] | 104 | !------------------------------------------------------------------------------- |
---|
[2143] | 105 | ! Calcul du flux de masse |
---|
[2127] | 106 | !------------------------------------------------------------------------------- |
---|
[2060] | 107 | |
---|
[2101] | 108 | DO l=1,nlay |
---|
[2060] | 109 | DO ig=1,ngrid |
---|
[2143] | 110 | IF (l < lmax(ig) .and. l >= lmin(ig)) THEN |
---|
[2060] | 111 | fm(ig,l+1) = fm(ig,l) + entr(ig,l) - detr(ig,l) |
---|
[2143] | 112 | ELSEIF (l == lmax(ig)) THEN |
---|
[2060] | 113 | fm(ig,l+1) = 0. |
---|
| 114 | detr(ig,l) = fm(ig,l) + entr(ig,l) |
---|
| 115 | ELSE |
---|
| 116 | fm(ig,l+1) = 0. |
---|
| 117 | entr(ig,l) = 0. |
---|
| 118 | detr(ig,l) = 0. |
---|
| 119 | ENDIF |
---|
| 120 | ENDDO |
---|
| 121 | ENDDO |
---|
| 122 | |
---|
[2127] | 123 | !=============================================================================== |
---|
[2143] | 124 | ! Checking |
---|
[2127] | 125 | !=============================================================================== |
---|
[2060] | 126 | |
---|
[2101] | 127 | DO l=1,nlay |
---|
[2060] | 128 | |
---|
[2127] | 129 | !------------------------------------------------------------------------------- |
---|
[2132] | 130 | ! Is incoming mass flux positive ? |
---|
[2127] | 131 | !------------------------------------------------------------------------------- |
---|
[2060] | 132 | |
---|
| 133 | DO ig=1,ngrid |
---|
[2143] | 134 | IF (fm(ig,l) < 0.) THEN |
---|
[2060] | 135 | labort_physic = .true. |
---|
| 136 | igout = ig |
---|
| 137 | lout = l |
---|
| 138 | ENDIF |
---|
| 139 | ENDDO |
---|
| 140 | |
---|
[2127] | 141 | !------------------------------------------------------------------------------- |
---|
[2132] | 142 | ! Is entrainment positive ? |
---|
[2127] | 143 | !------------------------------------------------------------------------------- |
---|
[2101] | 144 | |
---|
[2060] | 145 | DO ig=1,ngrid |
---|
[2143] | 146 | IF (entr(ig,l) < 0.) THEN |
---|
[2060] | 147 | labort_physic = .true. |
---|
| 148 | igout = ig |
---|
| 149 | lout = l |
---|
| 150 | ENDIF |
---|
| 151 | ENDDO |
---|
| 152 | |
---|
[2127] | 153 | !------------------------------------------------------------------------------- |
---|
[2132] | 154 | ! Is detrainment positive ? |
---|
[2127] | 155 | !------------------------------------------------------------------------------- |
---|
[2103] | 156 | |
---|
[2060] | 157 | DO ig=1,ngrid |
---|
[2143] | 158 | IF (detr(ig,l) < 0.) THEN |
---|
[2060] | 159 | labort_physic = .true. |
---|
| 160 | igout = ig |
---|
| 161 | lout = l |
---|
| 162 | ENDIF |
---|
| 163 | ENDDO |
---|
| 164 | |
---|
[2143] | 165 | !------------------------------------------------------------------------------- |
---|
| 166 | ! Abort |
---|
| 167 | !------------------------------------------------------------------------------- |
---|
| 168 | |
---|
[2060] | 169 | IF (labort_physic) THEN |
---|
[2143] | 170 | print *, '---------------------------------------------------------' |
---|
| 171 | print *, 'ERROR: mass flux has negative value(s)!' |
---|
| 172 | print *, 'ig,l,entr', igout, lout, entr(igout,lout) |
---|
[2103] | 173 | print *, 'lmin,lmax', lmin(igout), lmax(igout) |
---|
[2143] | 174 | print *, '- - - - - - - - - - - - - - - - - - - - - - - - - - - - -' |
---|
[2127] | 175 | DO k=nlay,1,-1 |
---|
| 176 | print *, 'fm ', fm(igout,k+1) |
---|
| 177 | print *, 'entr,detr', entr(igout,k), detr(igout,k) |
---|
| 178 | ENDDO |
---|
[2132] | 179 | print *, 'fm ', fm(igout,1) |
---|
[2143] | 180 | print *, '---------------------------------------------------------' |
---|
| 181 | CALL abort |
---|
[2060] | 182 | ENDIF |
---|
| 183 | |
---|
[2127] | 184 | !------------------------------------------------------------------------------- |
---|
[2143] | 185 | ! Is detrainment lessser than incoming mass flux ? |
---|
[2127] | 186 | !------------------------------------------------------------------------------- |
---|
[2103] | 187 | |
---|
[2127] | 188 | !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
---|
[2060] | 189 | ! AB : Even if fm has no negative value, it can be lesser than detr. |
---|
| 190 | ! That's not suitable because when we will mix the plume with the |
---|
| 191 | ! environment, it will detrain more mass than it is physically able to do. |
---|
| 192 | ! When it occures, that imply that entr + fm is greater than detr, |
---|
| 193 | ! otherwise we get a negative outgoing mass flux (cf. above). |
---|
| 194 | ! That is why we correct the detrainment as follows. |
---|
[2127] | 195 | !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
---|
[2060] | 196 | |
---|
| 197 | DO ig=1,ngrid |
---|
| 198 | IF (detr(ig,l).gt.fm(ig,l)) THEN |
---|
| 199 | detr(ig,l) = fm(ig,l) |
---|
| 200 | entr(ig,l) = fm(ig,l+1) |
---|
[2132] | 201 | ncorecdetr = ncorecdetr + 1 |
---|
[2060] | 202 | ENDIF |
---|
| 203 | ENDDO |
---|
| 204 | |
---|
[2127] | 205 | !------------------------------------------------------------------------------- |
---|
[2143] | 206 | ! Is entrained mass lesser than fomass_max ? |
---|
[2127] | 207 | !------------------------------------------------------------------------------- |
---|
[2060] | 208 | |
---|
[2127] | 209 | !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
---|
[2060] | 210 | ! AB : Entrainment is bigger than the maximal authorized value. |
---|
| 211 | ! If we consider that the excess entrainement is in fact plume air which |
---|
| 212 | ! is not detrained then we compensate it by decreasing detr. |
---|
| 213 | ! If it's not enough, we can increase entr in the layer above and decrease |
---|
| 214 | ! the outgoing mass flux in the current layer. |
---|
[2103] | 215 | ! If it's still unsufficient, code will abort (now commented). |
---|
| 216 | ! Else we reset entr to its intial value and we renormalize entrainment, |
---|
| 217 | ! detrainment and mass flux profiles such as we do not exceed the maximal |
---|
| 218 | ! authorized entrained mass. |
---|
[2127] | 219 | !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
---|
[2060] | 220 | |
---|
| 221 | DO ig=1,ngrid |
---|
| 222 | eee0 = entr(ig,l) |
---|
| 223 | ddd0 = detr(ig,l) |
---|
| 224 | eee = entr(ig,l) - masse(ig,l) * fomass_max / ptimestep |
---|
| 225 | ddd = detr(ig,l) - eee |
---|
[2143] | 226 | IF (eee > 0.) THEN |
---|
[2060] | 227 | entr(ig,l) = entr(ig,l) - eee |
---|
[2132] | 228 | ncorecentr = ncorecentr + 1 |
---|
[2143] | 229 | IF (ddd > 0.) THEN |
---|
[2060] | 230 | detr(ig,l) = ddd |
---|
[2143] | 231 | ELSEIF (l == lmax(ig)) THEN |
---|
[2103] | 232 | detr(ig,l) = fm(ig,l) + entr(ig,l) |
---|
[2143] | 233 | ELSEIF (entr(ig,l+1) > ABS(ddd)) THEN |
---|
[2103] | 234 | detr(ig,l) = 0. |
---|
| 235 | fm(ig,l+1) = fm(ig,l) + entr(ig,l) |
---|
| 236 | entr(ig,l+1) = entr(ig,l+1) + ddd |
---|
| 237 | ! ELSE |
---|
| 238 | ! entr(ig,l) = entr(ig,l) + eee |
---|
[2143] | 239 | ! igout = ig |
---|
| 240 | ! lout = l |
---|
| 241 | ! labort_physic = .true. |
---|
[2060] | 242 | ELSE |
---|
[2143] | 243 | fact = max(fact, eee0 / (eee0 - eee)) |
---|
[2103] | 244 | entr(ig,l) = eee0 |
---|
[2143] | 245 | ncorecfact = ncorecfact + 1 |
---|
[2060] | 246 | ENDIF |
---|
| 247 | ENDIF |
---|
| 248 | ENDDO |
---|
| 249 | |
---|
[2143] | 250 | IF (labort_physic) THEN |
---|
| 251 | print *, '---------------------------------------------------------' |
---|
| 252 | print *, 'ERROR: Entrainment is greater than maximal authorized value!' |
---|
| 253 | print *, ' Nor detrainment neither entrainment can compensate it!' |
---|
| 254 | print *, 'ig,l,entr', igout, lout, entr(igout,lout) |
---|
| 255 | print *, 'lmin,lmax', lmin(igout), lmax(igout) |
---|
| 256 | print *, '- - - - - - - - - - - - - - - - - - - - - - - - - - - - -' |
---|
| 257 | print *, 'e_max :', masse(igout,lout)*fomass_max/ptimestep |
---|
| 258 | print *, ' fomass_max :', fomass_max |
---|
| 259 | print *, ' masse :', masse(igout,lout) |
---|
| 260 | print *, ' ptimestep :', ptimestep |
---|
| 261 | print *, 'norm :', f(igout) |
---|
| 262 | print *, 'entr* :', entr_star(igout,lout) |
---|
| 263 | print *, '- - - - - - - - - - - - - - - - - - - - - - - - - - - - -' |
---|
| 264 | DO k=nlay,1,-1 |
---|
| 265 | print *, 'fm ', fm(igout,k+1) |
---|
| 266 | print *, 'entr,detr', entr(igout,k), detr(igout,k) |
---|
| 267 | ENDDO |
---|
| 268 | print *, 'fm ', fm(igout,1) |
---|
| 269 | print *, '---------------------------------------------------------' |
---|
| 270 | CALL abort |
---|
| 271 | ENDIF |
---|
[2060] | 272 | |
---|
[2127] | 273 | !------------------------------------------------------------------------------- |
---|
[2143] | 274 | ! Is Updraft fraction lesser than alpha_max ? |
---|
[2127] | 275 | !------------------------------------------------------------------------------- |
---|
[2060] | 276 | |
---|
| 277 | DO ig=1,ngrid |
---|
[2132] | 278 | zfm = rhobarz(ig,l+1) * zw2(ig,l+1) * alpha_max |
---|
[2127] | 279 | |
---|
[2143] | 280 | IF (fm(ig,l+1) > zfm) THEN |
---|
[2060] | 281 | f_old = fm(ig,l+1) |
---|
| 282 | fm(ig,l+1) = zfm |
---|
| 283 | detr(ig,l) = detr(ig,l) + f_old - fm(ig,l+1) |
---|
[2143] | 284 | ncorecalpha = ncorecalpha + 1 |
---|
[2127] | 285 | !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
---|
[2060] | 286 | ! AB : The previous change doesn't observe the equation df/dz = e - d. |
---|
[2127] | 287 | !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
---|
[2143] | 288 | entr(ig,l+1) = entr(ig,l+1) + f_old - fm(ig,l+1) |
---|
[2060] | 289 | ENDIF |
---|
| 290 | ENDDO |
---|
| 291 | |
---|
| 292 | ENDDO |
---|
| 293 | |
---|
[2143] | 294 | IF (fact > 0.) THEN |
---|
| 295 | entr(:,:) = entr(:,:) / fact |
---|
[2146] | 296 | detr(:,:) = detr(:,:) / fact |
---|
| 297 | fm(:,:) = fm(:,:) / fact |
---|
[2143] | 298 | ENDIF |
---|
| 299 | |
---|
[2127] | 300 | !------------------------------------------------------------------------------- |
---|
[2143] | 301 | ! Is equation df/dz = e - d still verified ? |
---|
[2127] | 302 | !------------------------------------------------------------------------------- |
---|
[2060] | 303 | |
---|
[2143] | 304 | ! DO l=1,nlay |
---|
| 305 | ! DO ig=1,ngrid |
---|
| 306 | ! test = abs(fm(ig,l) + entr(ig,l) - detr(ig,l) - fm(ig,l+1)) |
---|
| 307 | ! IF (test > 1.e-10) THEN |
---|
| 308 | ! nerrorequa = nerrorequa + 1 |
---|
| 309 | ! ENDIF |
---|
| 310 | ! ENDDO |
---|
| 311 | ! ENDDO |
---|
| 312 | |
---|
| 313 | !------------------------------------------------------------------------------- |
---|
| 314 | ! Reset top boundary conditions |
---|
| 315 | !------------------------------------------------------------------------------- |
---|
| 316 | |
---|
[2103] | 317 | DO ig=1,ngrid |
---|
[2143] | 318 | IF (lmax(ig).GT.0) THEN |
---|
[2060] | 319 | detr(ig,lmax(ig)) = fm(ig,lmax(ig)) + entr(ig,lmax(ig)) |
---|
| 320 | fm(ig,lmax(ig)+1) = 0. |
---|
| 321 | entr(ig,lmax(ig)) = 0. |
---|
[2103] | 322 | ENDIF |
---|
| 323 | ENDDO |
---|
[2060] | 324 | |
---|
[2143] | 325 | !=============================================================================== |
---|
| 326 | ! Outputs |
---|
| 327 | !=============================================================================== |
---|
[2060] | 328 | |
---|
[2143] | 329 | IF (prt_level > 0) THEN |
---|
| 330 | |
---|
| 331 | IF (ncorecdetr.ge.1) THEN |
---|
[2060] | 332 | print *, 'WARNING: Detrainment is greater than mass flux!' |
---|
[2143] | 333 | print *, 'In', ncorecdetr, 'grid point(s) over', nlay, 'x', ngrid |
---|
[2060] | 334 | ENDIF |
---|
| 335 | |
---|
[2143] | 336 | IF (ncorecentr.ge.1) THEN |
---|
[2103] | 337 | print *, 'WARNING: Entrained mass is greater than maximal authorized value!' |
---|
[2143] | 338 | print *, 'in', ncorecentr, 'grid point(s) over', nlay, 'x', ngrid |
---|
[2060] | 339 | ENDIF |
---|
| 340 | |
---|
[2143] | 341 | IF (ncorecfact.ge.1) THEN |
---|
| 342 | print *, 'WARNING: Entrained mass needs renormalization to be ok!' |
---|
| 343 | print *, 'in', ncorecfact, 'grid point(s) over', nlay, 'x', ngrid |
---|
| 344 | ENDIF |
---|
| 345 | |
---|
| 346 | ! IF (nerrorequa.ge.1) THEN |
---|
| 347 | ! print *, 'WARNING: !' |
---|
| 348 | ! print *, 'in', nerrorequa, 'grid point(s) over', nlay, 'x', ngrid |
---|
| 349 | ! ENDIF |
---|
| 350 | |
---|
| 351 | IF (ncorecalpha.ge.1) THEN |
---|
[2103] | 352 | print *, 'WARNING: Updraft fraction is greater than maximal authorized value!' |
---|
[2143] | 353 | print *, 'in', ncorecalpha, 'grid point(s) over', nlay, 'x', ngrid |
---|
[2060] | 354 | ENDIF |
---|
| 355 | |
---|
| 356 | ENDIF |
---|
| 357 | |
---|
| 358 | |
---|
| 359 | RETURN |
---|
| 360 | END |
---|