Ignore:
Timestamp:
Jun 20, 2019, 4:11:54 PM (5 years ago)
Author:
aboissinot
Message:

Update the thermal plume model:

  • check formulae consistency between thermcell_plume and thercell_closure
  • compute correctly thermal plume height
  • fix alimentation computation in the first unstable layer
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/LMDZ.GENERIC/libf/phystd/thermcell_flux.F90

    r2132 r2143  
    44SUBROUTINE thermcell_flux(ngrid,nlay,ptimestep,masse,                         &
    55                          lmin,lmax,entr_star,detr_star,                      &
    6                           f,rhobarz,zlev,zw2,fm,entr,detr,zqla)
    7      
    8      
    9 !===============================================================================
    10 !  Purpose: fluxes deduction
     6                          f,rhobarz,zlev,zw2,fm,entr,detr)
     7     
     8     
     9!===============================================================================
     10!  Purpose: deduction des flux
    1111
    1212!  Modif 2019/04 (AB alexandre.boissinot@lmd.jussieu.fr)
     
    3939      REAL rhobarz(ngrid,nlay)
    4040      REAL f(ngrid)
    41       REAL zqla(ngrid,nlay)
    42       REAL zmax(ngrid)
    4341     
    4442!     Outputs:
     
    5351     
    5452      INTEGER ig, l, k
    55       INTEGER igout, lout                 ! Error grid point number and level
     53      INTEGER igout, lout                 ! Error grid point and level
    5654     
    5755      REAL zfm                            ! Mass flux such as updraft fraction is equal to its maximal authorized value alpha_max
     
    6260      REAL ddd                            ! ddd0 - eee
    6361      REAL zzz                            ! Temporary variable set to mass flux
    64       REAL fact                           ! Factor between old norm and new norm
    65      
    66       INTEGER ncorecdetr                  ! detr > fm-   counter
    67       INTEGER ncorecentr                  ! entr > e_max counter
    68       INTEGER ncorecalpha                 ! fm > zfm     counter
     62      REAL fact
     63      REAL test
     64     
     65      INTEGER ncorecentr
     66      INTEGER ncorecdetr
     67      INTEGER nerrorequa
     68      INTEGER ncorecfact
     69      INTEGER ncorecalpha
    6970     
    7071      LOGICAL labort_physic
    7172     
    72       CHARACTER (len=20) :: modname='thermcell_flux'
    73       CHARACTER (len=80) :: abort_message
    74      
    7573!===============================================================================
    7674! Initialization
    7775!===============================================================================
    7876     
    79       ncorecdetr  = 0
    80       ncorecentr  = 0
     77      nerrorequa = 0
     78      ncorecentr = 0
     79      ncorecdetr = 0
     80      ncorecfact = 0
    8181      ncorecalpha = 0
    8282     
     
    8585      fm(:,:)   = 0.
    8686     
    87 !===============================================================================
    88 ! Mass flux, entrainment and detrainment
     87      labort_physic = .false.
     88     
     89      fact = 0.
     90     
     91!===============================================================================
     92! Calcul de l'entrainement, du detrainement et du flux de masse
    8993!===============================================================================
    9094     
     
    99103     
    100104!-------------------------------------------------------------------------------
    101 ! Mass flux and boundary conditions
     105! Calcul du flux de masse
    102106!-------------------------------------------------------------------------------
    103107     
    104108      DO l=1,nlay
    105109         DO ig=1,ngrid
    106             IF (l.lt.lmax(ig) .and. l.ge.lmin(ig)) THEN
     110            IF (l < lmax(ig) .and. l >= lmin(ig)) THEN
    107111               fm(ig,l+1) = fm(ig,l) + entr(ig,l) - detr(ig,l)
    108             ELSEIF (l.eq.lmax(ig)) THEN
     112            ELSEIF (l == lmax(ig)) THEN
    109113               fm(ig,l+1) = 0.
    110114               detr(ig,l) = fm(ig,l) + entr(ig,l)
     
    118122     
    119123!===============================================================================
    120 ! Validity tests and corrections
     124! Checking
    121125!===============================================================================
    122126     
     
    127131!-------------------------------------------------------------------------------
    128132         
    129 !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    130 ! AB : I remove the correction and replace it by an uncompromising test.
    131 !      According to the previous derivations, we MUST have positive mass flux
    132 !      everywhere! Indeed, as soon as fm becomes negative, the plume stops.
    133 !      Then the only value which can be negative is the mass flux at the top of
    134 !      the plume. However, this value was set to zero a few lines above.
    135 !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    136          
    137          labort_physic=.false.
    138          
    139          DO ig=1,ngrid
    140             IF (fm(ig,l).lt.0.) THEN
     133         DO ig=1,ngrid
     134            IF (fm(ig,l) < 0.) THEN
    141135               labort_physic = .true.
    142136               igout = ig
     
    145139         ENDDO
    146140         
    147          IF (labort_physic) THEN
    148             print *, 'ERROR: mass flux has negative value(s)!'
    149             print *, 'ig,l,fm',igout, lout, fm(igout,lout)
    150             print *, 'lmin,lmax', lmin(igout), lmax(igout)
    151             print *, '-------------------------------'
    152             DO k=nlay,1,-1
    153                print *, 'fm ', fm(igout,k+1)
    154                print *, 'entr,detr', entr(igout,k), detr(igout,k)
    155             ENDDO
    156             print *, 'fm-', fm(igout,1)
    157             print *, '-------------------------------'
    158             abort_message = 'Negative incoming fm in thermcell_flux'
    159             CALL abort_physic(modname,abort_message,1)
    160          ENDIF
    161          
    162141!-------------------------------------------------------------------------------
    163142! Is entrainment positive ?
    164143!-------------------------------------------------------------------------------
    165144         
    166 !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    167 ! AB : According to the previous derivations, we MUST have positive entrainment
    168 !      and detrainment everywhere!
    169 !      Indeed, they are set to max between zero and a computed value.
    170 !      Then tests are uncompromising.
    171 !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    172          
    173          DO ig=1,ngrid
    174             IF (entr(ig,l).lt.0.) THEN
     145         DO ig=1,ngrid
     146            IF (entr(ig,l) < 0.) THEN
    175147               labort_physic = .true.
    176148               igout = ig
     
    179151         ENDDO
    180152         
     153!-------------------------------------------------------------------------------
     154! Is detrainment positive ?
     155!-------------------------------------------------------------------------------
     156         
     157         DO ig=1,ngrid
     158            IF (detr(ig,l) < 0.) THEN
     159               labort_physic = .true.
     160               igout = ig
     161               lout = l
     162            ENDIF
     163         ENDDO
     164         
     165!-------------------------------------------------------------------------------
     166! Abort
     167!-------------------------------------------------------------------------------
     168         
    181169         IF (labort_physic) THEN
    182             print *, 'ERROR: entrainment has negative value(s)!'
     170            print *, '---------------------------------------------------------'
     171            print *, 'ERROR: mass flux has negative value(s)!'
    183172            print *, 'ig,l,entr', igout, lout, entr(igout,lout)
    184173            print *, 'lmin,lmax', lmin(igout), lmax(igout)
    185             print *, '-------------------------------'
     174            print *, '- - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
    186175            DO k=nlay,1,-1
    187176               print *, 'fm ', fm(igout,k+1)
     
    189178            ENDDO
    190179            print *, 'fm ', fm(igout,1)
    191             print *, '-------------------------------'
    192             abort_message = 'Negative entrainment in thermcell_flux'
    193             CALL abort_physic(modname,abort_message,1)
    194          ENDIF
    195          
    196 !-------------------------------------------------------------------------------
    197 ! Is detrainment positive ?
    198 !-------------------------------------------------------------------------------
    199          
    200          DO ig=1,ngrid
    201             IF (detr(ig,l).lt.0.) THEN
    202                labort_physic = .true.
    203                igout = ig
    204                lout = l
    205             ENDIF
    206          ENDDO
    207          
    208          IF (labort_physic) THEN
    209             print *, 'ERROR: detrainment has negative value(s)!'
    210             print *, 'ig,l,detr', igout, lout, detr(igout,lout)
    211             print *, 'lmin,lmax', lmin(igout), lmax(igout)
    212             print *, '-------------------------------'
    213             DO k=nlay,1,-1
    214                print *, 'fm ', fm(igout,k+1)
    215                print *, 'entr,detr', entr(igout,k), detr(igout,k)
    216             ENDDO
    217             print *, 'fm ', fm(igout,1)
    218             print *, '-------------------------------'
    219             abort_message = 'Negative detrainment in thermcell_flux'
    220             CALL abort_physic(modname,abort_message,1)
    221          ENDIF
    222          
    223 !-------------------------------------------------------------------------------
    224 ! Is detrainment lesser than incoming mass flux ?
     180            print *, '---------------------------------------------------------'
     181            CALL abort
     182         ENDIF
     183         
     184!-------------------------------------------------------------------------------
     185! Is detrainment lessser than incoming mass flux ?
    225186!-------------------------------------------------------------------------------
    226187         
     
    238199               detr(ig,l) = fm(ig,l)
    239200               entr(ig,l) = fm(ig,l+1)
    240                
    241                IF (prt_level.ge.10) THEN
    242                   print *, 'WARNING: Detrainment is modified in thermcell_flux!'
    243                   print *, 'ig,l,lmax', ig, l, lmax(ig)
    244                ENDIF
    245                
    246                IF (prt_level.ge.100) THEN
    247                   print *, 'fm+', fm(ig,l+1)
    248                   print *, 'entr,detr', entr(ig,l), detr(ig,l)
    249                   print *, 'fm-', fm(ig,l)
    250                ENDIF
    251                
    252201               ncorecdetr  = ncorecdetr + 1
    253                
    254             ENDIF
    255          ENDDO
    256          
    257 !-------------------------------------------------------------------------------
    258 ! Is entrainment mass fraction lesser than fomass_max ?
     202            ENDIF
     203         ENDDO
     204         
     205!-------------------------------------------------------------------------------
     206! Is entrained mass lesser than fomass_max ?
    259207!-------------------------------------------------------------------------------
    260208         
     
    271219!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    272220         
    273          labort_physic=.false.
    274          
    275221         DO ig=1,ngrid
    276222            eee0 = entr(ig,l)
     
    278224            eee  = entr(ig,l) - masse(ig,l) * fomass_max / ptimestep
    279225            ddd  = detr(ig,l) - eee
    280            
    281             IF (eee.gt.0.) THEN
     226            IF (eee > 0.) THEN
    282227               entr(ig,l) = entr(ig,l) - eee
    283228               ncorecentr  = ncorecentr + 1
    284                
    285                IF (prt_level.ge.10) THEN
    286                   print *, 'WARNING: Entrainment is modified in thermcell_flux!'
    287                   print *, 'ig,l,lmax', ig, l, lmax(ig)
    288                ENDIF
    289                
    290                IF (ddd.gt.0.) THEN                          ! detr in the current layer is reduced
     229               IF (ddd > 0.) THEN
    291230                  detr(ig,l) = ddd
    292                ELSEIF (l.eq.lmax(ig)) THEN                  ! detr in the last layer is adjusted
     231               ELSEIF (l == lmax(ig)) THEN
    293232                  detr(ig,l) = fm(ig,l) + entr(ig,l)
    294                ELSEIF (entr(ig,l+1).gt.ABS(ddd)) THEN       ! detr in the current layer is set to 0 and entr in the layer above is reduced
     233               ELSEIF (entr(ig,l+1) > ABS(ddd)) THEN
    295234                  detr(ig,l) = 0.
    296235                  fm(ig,l+1) = fm(ig,l) + entr(ig,l)
     
    298237!               ELSE
    299238!                  entr(ig,l) = entr(ig,l) + eee
    300 !                  igout=ig
    301 !                  lout=l
    302 !                  labort_physic=.true.
     239!                  igout = ig
     240!                  lout = l
     241!                  labort_physic = .true.
    303242               ELSE
    304                   fact = (eee0 - eee) / eee0
     243                  fact = max(fact, eee0 / (eee0 - eee))
    305244                  entr(ig,l) = eee0
    306                   detr(ig,:) = detr(ig,:) * fact
    307                   entr(ig,:) = entr(ig,:) * fact
    308                   fm(ig,:)   = fm(ig,:) * fact
    309                  
    310                   IF (prt_level.ge.1) THEN
    311                      print *, 'WARNING: Normalisation is modified in thermcell_flux!'
    312                      print *, 'old f, new f :', f(ig), fact * f(ig)
    313                   ENDIF
     245                  ncorecfact = ncorecfact + 1
    314246               ENDIF
    315247            ENDIF
    316248         ENDDO
    317249         
    318 !         IF (labort_physic) THEN
    319 !            print *, 'ERROR: Entrainment is greater than its maximal authorized value!'
    320 !            print *, '       Nor detrainment neither entrainment can compensate it!'
    321 !            print *, 'ig,l,entr', igout, lout, entr(igout,lout)
    322 !            print *, 'lmin,lmax', lmin(igout), lmax(igout)
    323 !            print *, '--------------------'
    324 !            print *, 'e_max :', masse(igout,lout)*fomass_max/ptimestep
    325 !            print *, '   fomass_max :', fomass_max
    326 !            print *, '   masse      :', masse(igout,lout)
    327 !            print *, '   ptimestep  :', ptimestep
    328 !            print *, 'norm  :', f(igout)
    329 !            print *, 'entr* :', entr_star(igout,lout)
    330 !            print *, '--------------------'
    331 !            DO k=nlay,1,-1
    332 !               print *, 'fm ', fm(igout,k+1)
    333 !               print *, 'entr,detr', entr(igout,k), detr(igout,k)
    334 !            ENDDO
    335 !            print *, 'fm ', fm(igout,1)
    336 !            print *, '-------------------------------'
    337 !            abort_message = 'Entrainment is too large in thermcell_flux'
    338 !            CALL abort_physic (modname,abort_message,1)
    339 !         ENDIF
    340          
    341 !-------------------------------------------------------------------------------
    342 ! Is updraft fraction lesser than alpha_max ?
    343 !-------------------------------------------------------------------------------
    344          
    345 !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    346 ! FH : Partie a revisiter.
    347 !      Il semble qu'etaient codees ici deux optiques dans le cas F/(rho*w) > 1
    348 !      - soit limiter la hauteur du thermique en considerant que c'est
    349 !        la derniere chouche
    350 !      - soit limiter F a rho w.
    351 !      Dans le second cas, il faut en fait limiter a un peu moins que ca parce
    352 !      qu'on a des 1/(1-alpha) un peu plus loin dans thermcell_main et qu'il
    353 !      semble de toutes facons deraisonable d'avoir des fractions de 1...
    354 !      Ci-dessous, et dans l'etat actuel, le premier des deux if est sans doute inutile. 
    355 !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                 
     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
     272         
     273!-------------------------------------------------------------------------------
     274! Is Updraft fraction lesser than alpha_max ?
     275!-------------------------------------------------------------------------------
    356276         
    357277         DO ig=1,ngrid
    358278            zfm = rhobarz(ig,l+1) * zw2(ig,l+1) * alpha_max
    359279           
    360             IF (fm(ig,l+1) .gt. zfm) THEN
     280            IF (fm(ig,l+1) > zfm) THEN
    361281               f_old = fm(ig,l+1)
    362282               fm(ig,l+1) = zfm
    363283               detr(ig,l) = detr(ig,l) + f_old - fm(ig,l+1)
    364                
     284               ncorecalpha = ncorecalpha + 1
    365285!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    366286! AB : The previous change doesn't observe the equation df/dz = e - d.
    367 !      To avoid this issue, what is better to do? I choose to increase the
    368 !      entrainment in the layer above when l<lmax. If l=lmax then fm(l+1)=0 and
    369 !      there are never any problems.
    370 !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    371                IF (l.lt.lmax(ig)) THEN
    372                   entr(ig,l+1) = entr(ig,l+1) + f_old - fm(ig,l+1)
    373                ENDIF
    374                
    375                IF (prt_level.ge.10) THEN
    376                   print *, 'Mass flux is modified in thermcell_flux'
    377                   print *, 'ig,l,lmax', ig, l, lmax(ig)
    378                ENDIF
    379                
    380                IF (prt_level.ge.100) THEN
    381                   print *, 'fm-', fm(ig,l)
    382                   print *, 'entr,detr', entr(ig,l), detr(ig,l)
    383                   print *, 'fm+', fm(ig,l+1)
    384                ENDIF
    385                
    386                ncorecalpha = ncorecalpha + 1
     287!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     288               entr(ig,l+1) = entr(ig,l+1) + f_old - fm(ig,l+1)
    387289            ENDIF
    388290         ENDDO
     
    390292      ENDDO
    391293     
    392 !-------------------------------------------------------------------------------
    393 ! Boundary conditions
    394 !-------------------------------------------------------------------------------
    395      
    396 !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    397 ! AB : test added to avoid problem when lmax = 0, which is not a fortran index.
    398 !      Theoretically, we always get lmax >= lmin >= linf > 0
    399 !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     294      IF (fact > 0.) THEN
     295         entr(:,:) = entr(:,:) / fact
     296         detr(:,:) = entr(:,:) / fact
     297         fm(:,:) = entr(:,:) / fact
     298      ENDIF
     299     
     300!-------------------------------------------------------------------------------
     301! Is equation df/dz = e - d still verified ?
     302!-------------------------------------------------------------------------------
     303     
     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     
    400317      DO ig=1,ngrid
    401          IF (lmax(ig).gt.0) THEN
     318         IF (lmax(ig).GT.0) THEN
    402319            detr(ig,lmax(ig)) = fm(ig,lmax(ig)) + entr(ig,lmax(ig))
    403320            fm(ig,lmax(ig)+1) = 0.
     
    406323      ENDDO
    407324     
    408 !-------------------------------------------------------------------------------
    409 ! Corrections display
    410 !-------------------------------------------------------------------------------
    411      
    412       IF (prt_level.GE.1) THEN
    413                   
    414          IF (ncorecdetr.GE.1) THEN
     325!===============================================================================
     326! Outputs
     327!===============================================================================
     328     
     329      IF (prt_level > 0) THEN
     330         
     331         IF (ncorecdetr.ge.1) THEN
    415332            print *, 'WARNING: Detrainment is greater than mass flux!'
    416             print *, '         In', ncorecdetr, 'point(s)'
    417          ENDIF
    418          
    419          IF (ncorecentr.GE.1) THEN
     333            print *, 'In', ncorecdetr, 'grid point(s) over', nlay, 'x', ngrid
     334         ENDIF
     335         
     336         IF (ncorecentr.ge.1) THEN
    420337            print *, 'WARNING: Entrained mass is greater than maximal authorized value!'
    421             print *, '         In', ncorecentr, 'point(s)'
    422          ENDIF
    423          
    424          IF (ncorecalpha.GE.1) THEN
     338            print *, 'in', ncorecentr, 'grid point(s) over', nlay, 'x', ngrid
     339         ENDIF
     340         
     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
    425352            print *, 'WARNING: Updraft fraction is greater than maximal authorized value!'
    426             print *, '         In', ncorecalpha, 'point(s)'
     353            print *, 'in', ncorecalpha, 'grid point(s) over', nlay, 'x', ngrid
    427354         ENDIF
    428355         
    429356      ENDIF
    430      
    431 ! AB : temporary test added to check the validity of eq. df/dz = e - d
    432 !      DO l=1,nlay
    433 !         DO ig=1,ngrid
    434 !            test = abs(fm(ig,l) + entr(ig,l) - detr(ig,l) - fm(ig,l+1))
    435 !            IF (test.gt.1.e-10) THEN
    436 !               print *, 'WARNING: df/dz != entr - detr'
    437 !               print *, 'ig,l', ig, l
    438 !               print *, 'fm+  :', fm(ig,l+1)
    439 !               print *, 'entr,detr', entr(ig,l), detr(ig,l)
    440 !               print *, 'fm   :', fm(ig,l)
    441 !               print *, 'entr,detr', entr(ig,l-1), detr(ig,l-1)
    442 !               print *, 'fm-  :', fm(ig,l-1)
    443 !               print *, 'err. :', test
    444 !            ENDIF
    445 !         ENDDO
    446 !      ENDDO
    447357     
    448358     
Note: See TracChangeset for help on using the changeset viewer.