LCOV - code coverage report
Current view: top level - physics/cam - pkg_cld_sediment.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 167 174 96.0 %
Date: 2025-01-13 21:54:50 Functions: 6 6 100.0 %

          Line data    Source code
       1             : #undef OLDLIQSED
       2             : module pkg_cld_sediment
       3             : 
       4             : !---------------------------------------------------------------------------------
       5             : ! Purpose:
       6             : !
       7             : ! Contains routines to compute tendencies from sedimentation of cloud liquid and 
       8             : ! ice particles
       9             : !
      10             : ! Author: Byron Boville  Sept 19, 2002 from code by P. J. Rasch
      11             : !
      12             : !---------------------------------------------------------------------------------
      13             : 
      14             :   use shr_kind_mod,   only: r8=>shr_kind_r8
      15             :   use spmd_utils,     only: masterproc
      16             :   use ppgrid,         only: pcols, pver, pverp
      17             :   use physconst,      only: gravit, latvap, latice, rair, rhoh2o
      18             :   use cldwat,         only: icritc
      19             :   use pkg_cldoptics,  only: reitab, reltab
      20             :   use phys_control,   only: use_simple_phys
      21             :   use cam_abortutils, only: endrun
      22             :   use cam_logfile,    only: iulog
      23             : 
      24             :   implicit none
      25             :   private
      26             :   save
      27             : 
      28             :   public :: cld_sediment_readnl, cld_sediment_vel, cld_sediment_tend
      29             : 
      30             : 
      31             :   real (r8), parameter :: vland  = 1.5_r8            ! liquid fall velocity over land  (cm/s)
      32             :   real (r8), parameter :: vocean = 2.8_r8            ! liquid fall velocity over ocean (cm/s)
      33             :   real (r8), parameter :: mxsedfac   = 0.99_r8       ! maximum sedimentation flux factor
      34             : 
      35             :   logical,   parameter :: stokes = .true.         ! use Stokes velocity instead of McFarquhar and Heymsfield
      36             : 
      37             : ! parameter for modified McFarquhar and Heymsfield
      38             :   real (r8), parameter :: vice_small = 1._r8         ! ice fall velocity for small concentration (cm/s)
      39             : 
      40             : ! parameters for Stokes velocity
      41             :   real (r8), parameter :: eta =  1.7e-5_r8           ! viscosity of air (kg m / s)
      42             :   real (r8), parameter :: r40 =  40._r8              !  40 micron radius
      43             :   real (r8), parameter :: r400= 400._r8              ! 400 micron radius
      44             :   real (r8), parameter :: v400= 1.00_r8              ! fall velocity of 400 micron sphere (m/s)
      45             :   real (r8)            :: v40 ! = (2._r8/9._r8) * rhoh2o * gravit/eta * r40**2 * 1.e-12_r8  
      46             :                                                      ! Stokes fall velocity of 40 micron sphere (m/s)
      47             :   real (r8)            :: vslope !  = (v400 - v40)/(r400 -r40) ! linear slope for large particles m/s/micron
      48             : 
      49             :   ! namelist variables
      50             :   real(r8) :: cldsed_ice_stokes_fac = huge(1._r8)    ! factor applied to the ice fall velocity computed from 
      51             :                                                      ! stokes terminal velocity
      52             : 
      53             : !===============================================================================
      54             : contains
      55             : !===============================================================================
      56             : 
      57        1536 : subroutine cld_sediment_readnl(nlfile)
      58             : 
      59             :    use namelist_utils,  only: find_group_name
      60             :    use units,           only: getunit, freeunit
      61             :    use mpishorthand
      62             : 
      63             :    character(len=*), intent(in) :: nlfile  ! filepath for file containing namelist input
      64             : 
      65             :    ! Local variables
      66             :    integer :: unitn, ierr
      67             :    character(len=*), parameter :: subname = 'cld_sediment_readnl'
      68             : 
      69             :    namelist /cldsed_nl/ cldsed_ice_stokes_fac
      70             :    !-----------------------------------------------------------------------------
      71             : 
      72        1536 :    if (masterproc) then
      73           2 :       unitn = getunit()
      74           2 :       open( unitn, file=trim(nlfile), status='old' )
      75           2 :       call find_group_name(unitn, 'cldsed_nl', status=ierr)
      76           2 :       if (ierr == 0) then
      77           2 :          read(unitn, cldsed_nl, iostat=ierr)
      78           2 :          if (ierr /= 0) then
      79           0 :             call endrun(subname // ':: ERROR reading namelist')
      80             :          end if
      81             :       end if
      82           2 :       close(unitn)
      83           2 :       call freeunit(unitn)
      84             : 
      85             :    end if
      86             : 
      87             : #ifdef SPMD
      88             :    ! Broadcast namelist variables
      89        1536 :    call mpibcast(cldsed_ice_stokes_fac, 1, mpir8, 0, mpicom)
      90             : #endif
      91             : 
      92        1536 :    if (masterproc .and. .not. use_simple_phys) then
      93           2 :       write(iulog,*) subname//': cldsed_ice_stokes_fac = ', cldsed_ice_stokes_fac
      94             :    end if
      95             : 
      96        1536 : end subroutine cld_sediment_readnl
      97             : 
      98             : !===============================================================================
      99             : 
     100     1495368 :   subroutine cld_sediment_vel (ncol,                               &
     101             :        icefrac , landfrac, ocnfrac , pmid    , pdel    , t       , &
     102             :        cloud   , cldliq  , cldice  , pvliq   , pvice   , landm, snowh)
     103             : 
     104             : !----------------------------------------------------------------------
     105             : 
     106             : ! Compute gravitational sedimentation velocities for cloud liquid water
     107             : ! and ice, based on Lawrence and Crutzen (1998).
     108             : 
     109             : ! LIQUID
     110             : 
     111             : ! The fall velocities assume that droplets have a gamma distribution
     112             : ! with effective radii for land and ocean as assessed by Han et al.;
     113             : ! see Lawrence and Crutzen (1998) for a derivation.
     114             : 
     115             : ! ICE
     116             : 
     117             : ! The fall velocities are based on data from McFarquhar and Heymsfield
     118             : ! or on Stokes terminal velocity for spheres and the effective radius.
     119             : 
     120             : ! NEED TO BE CAREFUL - VELOCITIES SHOULD BE AT THE *LOWER* INTERFACE
     121             : ! (THAT IS, FOR K+1), FLUXES ARE ALSO AT THE LOWER INTERFACE (K+1), 
     122             : ! BUT MIXING RATIOS ARE AT THE MIDPOINTS (K)...
     123             : 
     124             : ! NOTE THAT PVEL IS ON PVERP (INTERFACES), WHEREAS VFALL IS FOR THE CELL
     125             : ! AVERAGES (I.E., MIDPOINTS); ASSUME THE FALL VELOCITY APPLICABLE TO THE 
     126             : ! LOWER INTERFACE (K+1) IS THE SAME AS THAT APPLICABLE FOR THE CELL (V(K))
     127             : 
     128             : !-----------------------------------------------------------------------
     129             : !     MATCH-MPIC version 2.0, Author: mgl, March 1998
     130             : ! adapted by P. J. Rasch
     131             : !            B. A. Boville, September 19, 2002
     132             : !            P. J. Rasch    May 22, 2003 (added stokes flow calc for liquid
     133             : !                                         drops based on effect radii)
     134             : !-----------------------------------------------------------------------
     135             : 
     136             : 
     137             : ! Arguments
     138             :     integer, intent(in) :: ncol                     ! number of colums to process
     139             : 
     140             :     real(r8), intent(in)  :: icefrac (pcols)        ! sea ice fraction (fraction)
     141             :     real(r8), intent(in)  :: landfrac(pcols)        ! land fraction (fraction)
     142             :     real(r8), intent(in)  :: ocnfrac (pcols)        ! ocean fraction (fraction)
     143             :     real(r8), intent(in)  :: pmid  (pcols,pver)     ! pressure of midpoint levels (Pa)
     144             :     real(r8), intent(in)  :: pdel  (pcols,pver)     ! pressure diff across layer (Pa)
     145             :     real(r8), intent(in)  :: cloud (pcols,pver)     ! cloud fraction (fraction)
     146             :     real(r8), intent(in)  :: t     (pcols,pver)     ! temperature (K)
     147             :     real(r8), intent(in)  :: cldliq(pcols,pver)     ! cloud water, liquid (kg/kg)
     148             :     real(r8), intent(in)  :: cldice(pcols,pver)     ! cloud water, ice    (kg/kg)
     149             :     real(r8), intent(in) :: snowh(pcols)         ! Snow depth over land, water equivalent (m)
     150             : 
     151             :     real(r8), intent(out) :: pvliq (pcols,pverp)    ! vertical velocity of cloud liquid drops (Pa/s)
     152             :     real(r8), intent(out) :: pvice (pcols,pverp)    ! vertical velocity of cloud ice particles (Pa/s)
     153             :     real(r8), intent(in) :: landm(pcols)            ! land fraction ramped over water
     154             : ! -> note that pvel is at the interfaces (loss from cell is based on pvel(k+1))
     155             : 
     156             : ! Local variables
     157             :     real (r8) :: rho(pcols,pver)                    ! air density in kg/m3
     158             :     real (r8) :: vfall                              ! settling velocity of cloud particles (m/s)
     159             :     real (r8) :: icice                              ! in cloud ice water content (kg/kg)
     160             :     real (r8) :: iciwc                              ! in cloud ice water content in g/m3
     161             :     real (r8) :: icefac
     162             :     real (r8) :: logiwc
     163             : 
     164             :     real (r8) :: rei(pcols,pver)                    ! effective radius of ice particles (microns)
     165             :     real (r8) :: rel(pcols,pver)                    ! effective radius of liq particles (microns)
     166             :     real(r8)  pvliq2 (pcols,pverp)    ! vertical velocity of cloud liquid drops (Pa/s)
     167             : 
     168             :     integer i,k
     169             : 
     170             :     real (r8) :: lbound, ac, bc, cc
     171             : 
     172             : !-----------------------------------------------------------------------
     173             : !------- initialize linear ramp variables for fall velocity ------------
     174             : !-----------------------------------------------------------------------
     175             : 
     176     1495368 :   v40 = (2._r8/9._r8) * rhoh2o * gravit/eta * r40**2 * 1.e-12_r8  
     177     1495368 :   vslope = (v400 - v40)/(r400 -r40)
     178             : 
     179             : !-----------------------------------------------------------------------
     180             : !--------------------- liquid fall velocity ----------------------------
     181             : !-----------------------------------------------------------------------
     182             : 
     183             :     ! compute air density
     184   650693736 :     rho(:ncol,:) = pmid(:ncol,:) / (rair * t(:ncol,:))
     185             : 
     186   675662904 :     pvliq(:ncol,:) = 0._r8
     187             : 
     188             :     ! get effective radius of liquid drop
     189     1495368 :     call reltab(ncol, t, landfrac, landm, icefrac, rel, snowh)
     190             : 
     191    40374936 :     do k = 1,pver
     192   650693736 :        do i = 1,ncol
     193   649198368 :           if (cloud(i,k) > 0._r8 .and. cldliq(i,k) > 0._r8) then
     194             : 
     195             : #ifdef OLDLIQSED
     196             : ! oldway
     197             :              ! merge the liquid fall velocities for land and ocean (cm/s)
     198             :              ! SHOULD ALSO ACCOUNT FOR ICEFRAC
     199             :              vfall = vland*landfrac(i) + vocean*(1._r8-landfrac(i))
     200             : !!$          vfall = vland*landfrac(i) + vocean*ocnfrac(i) + vseaice*icefrac(i)
     201             : 
     202             :              ! convert the fall speed to pressure units, but do not apply the traditional
     203             :              ! negative convention for pvel.
     204             :              pvliq(i,k+1) = vfall     &
     205             :                   * 0.01_r8                 & ! cm to meters
     206             :                   * rho(i,k)*gravit        ! meters/sec to pascals/sec
     207             : #else
     208             : 
     209             : ! newway
     210   150493962 :              if (rel(i,k) < 40._r8 ) then
     211   150493962 :                 vfall = 2._r8/9._r8 * rhoh2o * gravit * rel(i,k)**2 / eta  * 1.e-12_r8  ! micons^2 -> m^2
     212             :              else
     213           0 :                 vfall = v40 + vslope * (rel(i,k)-r40)      ! linear above 40 microns
     214             :              end if
     215             :              ! convert the fall speed to pressure units
     216             :              ! but do not apply the traditional
     217             :              ! negative convention for pvel.
     218             : !             pvliq2(i,k+1) = vfall * rho(i,k)*gravit        ! meters/sec to pascals/sec
     219   150493962 :              pvliq(i,k+1) = vfall * rho(i,k)*gravit        ! meters/sec to pascals/sec
     220             : #endif
     221             :           end if
     222             :        end do
     223             :     end do
     224             : 
     225             :     !-----------------------------------------------------------------------
     226             :     !--------------------- ice fall velocity -------------------------------
     227             :     !-----------------------------------------------------------------------
     228             : 
     229   675662904 :     pvice(:ncol,:) = 0._r8
     230             : 
     231             :     if (stokes) then
     232             : 
     233             :        !-----------------------------------------------------------------------
     234             :        !--------------------- stokes terminal velocity < 40 microns -----------
     235             :        !-----------------------------------------------------------------------
     236             : 
     237             :        ! get effective radius
     238     1495368 :        call reitab(ncol, t, rei)
     239             : 
     240    40374936 :        do k = 1,pver
     241   650693736 :           do i = 1,ncol
     242   649198368 :              if (cloud(i,k) > 0._r8 .and. cldice(i,k) > 0._r8) then
     243   135492597 :                 if (rei(i,k) < 40._r8 ) then
     244    37825727 :                    vfall = 2._r8/9._r8 * rhoh2o * gravit * rei(i,k)**2 / eta  * 1.e-12_r8  ! micons^2 -> m^2
     245    37825727 :                    vfall = vfall * cldsed_ice_stokes_fac
     246             :                 else
     247    97666870 :                    vfall = v40 + vslope * (rei(i,k)-r40)      ! linear above 40 microns
     248             :                 end if
     249             : 
     250             :                 ! convert the fall speed to pressure units, but do not apply the traditional
     251             :                 ! negative convention for pvel.
     252   135492597 :                 pvice(i,k+1) = vfall * rho(i,k)*gravit        ! meters/sec to pascals/sec
     253             :              end if
     254             :           end do
     255             :        end do
     256             : 
     257             :     else
     258             : 
     259             :        !-----------------------------------------------------------------------
     260             :        !--------------------- McFarquhar and Heymsfield > icritc --------------
     261             :        !-----------------------------------------------------------------------
     262             : 
     263             :        ! lower bound for iciwc
     264             : 
     265             :        cc = 128.64_r8 
     266             :        bc = 53.242_r8
     267             :        ac = 5.4795_r8
     268             :        lbound = (-bc + sqrt(bc*bc-4*ac*cc))/(2*ac)
     269             :        lbound = 10._r8**lbound
     270             : 
     271             :        do k = 1,pver
     272             :           do i = 1,ncol
     273             :              if (cloud(i,k) > 0._r8 .and. cldice(i,k) > 0._r8) then
     274             : 
     275             :                 ! compute the in-cloud ice concentration (kg/kg)
     276             :                 icice = cldice(i,k) / cloud(i,k)
     277             : 
     278             :                 ! compute the ice water content in g/m3
     279             :                 iciwc = icice * rho(i,k) * 1.e3_r8
     280             : 
     281             :                 ! set the fall velocity (cm/s) to depend on the ice water content in g/m3,
     282             :                 if (iciwc > lbound) then ! need this because of log10
     283             :                    logiwc = log10(iciwc)
     284             :                    !          Median - 
     285             :                    vfall = 128.64_r8 + 53.242_r8*logiwc + 5.4795_r8*logiwc**2
     286             :                    !          Average - 
     287             :                 !!$             vfall = 122.63 + 44.111*logiwc + 4.2144*logiwc**2
     288             :                 else
     289             :                    vfall = 0._r8
     290             :                 end if
     291             : 
     292             :                 ! set ice velocity to 1 cm/s if ice mixing ratio < icritc, ramp to value
     293             :                 ! calculated above at 2*icritc
     294             :                 if (icice <= icritc) then
     295             :                    vfall = vice_small
     296             :                 else if(icice < 2*icritc) then
     297             :                    icefac = (icice-icritc)/icritc
     298             :                    vfall = vice_small * (1._r8-icefac) + vfall * icefac
     299             :                 end if
     300             : 
     301             :                 ! bound the terminal velocity of ice particles at high concentration
     302             :                 vfall = min(100.0_r8, vfall)
     303             : 
     304             :                 ! convert the fall speed to pressure units, but do not apply the traditional
     305             :                 ! negative convention for pvel.
     306             :                 pvice(i,k+1) = vfall     &
     307             :                    * 0.01_r8                 & ! cm to meters
     308             :                    * rho(i,k)*gravit        ! meters/sec to pascals/sec
     309             :              end if
     310             :           end do
     311             :        end do
     312             : 
     313             :     end if
     314             : 
     315     1495368 :  end subroutine cld_sediment_vel
     316             : 
     317             : 
     318             : !===============================================================================
     319     1495368 :   subroutine cld_sediment_tend (ncol, dtime  ,               &
     320             :        pint   , pmid   , pdel   , t      ,                   &
     321             :        cloud  , cldliq , cldice , pvliq  , pvice  ,          &
     322             :        liqtend, icetend, wvtend , htend  , sfliq  , sfice   )
     323             : 
     324             : !----------------------------------------------------------------------
     325             : !     Apply Cloud Particle Gravitational Sedimentation to Condensate
     326             : !----------------------------------------------------------------------
     327             : 
     328             : 
     329             : ! Arguments
     330             :     integer,  intent(in)  :: ncol                      ! number of colums to process
     331             : 
     332             :     real(r8), intent(in)  :: dtime                     ! time step
     333             :     real(r8), intent(in)  :: pint  (pcols,pverp)       ! interfaces pressure (Pa)
     334             :     real(r8), intent(in)  :: pmid  (pcols,pver)        ! midpoint pressures (Pa)
     335             :     real(r8), intent(in)  :: pdel  (pcols,pver)        ! pressure diff across layer (Pa)
     336             :     real(r8), intent(in)  :: cloud (pcols,pver)        ! cloud fraction (fraction)
     337             :     real(r8), intent(in)  :: t     (pcols,pver)        ! temperature (K)
     338             :     real(r8), intent(in)  :: cldliq(pcols,pver)        ! cloud liquid water (kg/kg)
     339             :     real(r8), intent(in)  :: cldice(pcols,pver)        ! cloud ice water    (kg/kg)
     340             :     real(r8), intent(in)  :: pvliq (pcols,pverp)       ! vertical velocity of liquid drops  (Pa/s)
     341             :     real(r8), intent(in)  :: pvice (pcols,pverp)       ! vertical velocity of ice particles (Pa/s)
     342             : ! -> note that pvel is at the interfaces (loss from cell is based on pvel(k+1))
     343             : 
     344             :     real(r8), intent(out) :: liqtend(pcols,pver)       ! liquid condensate tend
     345             :     real(r8), intent(out) :: icetend(pcols,pver)       ! ice condensate tend
     346             :     real(r8), intent(out) :: wvtend (pcols,pver)       ! water vapor tend
     347             :     real(r8), intent(out) :: htend  (pcols,pver)       ! heating rate
     348             :     real(r8), intent(out) :: sfliq  (pcols)            ! surface flux of liquid (rain, kg/m/s)
     349             :     real(r8), intent(out) :: sfice  (pcols)            ! surface flux of ice    (snow, kg/m/s)
     350             : 
     351             : ! Local variables
     352             :     real(r8) :: fxliq(pcols,pverp)                     ! fluxes at the interfaces, liquid (positive = down)
     353             :     real(r8) :: fxice(pcols,pverp)                     ! fluxes at the interfaces, ice    (positive = down)
     354             :     real(r8) :: cldab(pcols)                           ! cloud in layer above
     355             :     real(r8) :: evapliq                                ! evaporation of cloud liquid into environment
     356             :     real(r8) :: evapice                                ! evaporation of cloud ice into environment
     357             :     real(r8) :: cldovrl                                ! cloud overlap factor
     358             : 
     359             :     integer :: i,k
     360             : !----------------------------------------------------------------------
     361             : 
     362             : ! initialize variables
     363   677158272 :     fxliq  (:ncol,:) = 0._r8 ! flux at interfaces (liquid)
     364   675662904 :     fxice  (:ncol,:) = 0._r8 ! flux at interfaces (ice)
     365   650693736 :     liqtend(:ncol,:) = 0._r8 ! condensate tend (liquid)
     366   650693736 :     icetend(:ncol,:) = 0._r8 ! condensate tend (ice)
     367   650693736 :     wvtend(:ncol,:)  = 0._r8 ! environmental moistening
     368   650693736 :     htend(:ncol,:)   = 0._r8 ! evaporative cooling
     369    24969168 :     sfliq(:ncol)     = 0._r8 ! condensate sedimentation flux out bot of column (liquid)
     370    24969168 :     sfice(:ncol)     = 0._r8 ! condensate sedimentation flux out bot of column (ice)
     371             : 
     372             : ! fluxes at interior points
     373     1495368 :     call getflx(ncol, pint, cldliq, pvliq, dtime, fxliq)
     374     1495368 :     call getflx(ncol, pint, cldice, pvice, dtime, fxice)
     375             : 
     376             : ! calculate fluxes at boundaries
     377    24969168 :     do i = 1,ncol
     378    23473800 :        fxliq(i,1) = 0._r8
     379    23473800 :        fxice(i,1) = 0._r8
     380             : ! surface flux by upstream scheme
     381    23473800 :        fxliq(i,pverp) = cldliq(i,pver) * pvliq(i,pverp) * dtime
     382    24969168 :        fxice(i,pverp) = cldice(i,pver) * pvice(i,pverp) * dtime
     383             :     end do
     384             : 
     385             : ! filter out any negative fluxes from the getflx routine
     386             : ! (typical fluxes are of order > 1e-3 when clouds are present)
     387    38879568 :     do k = 2,pver
     388   624229200 :        fxliq(:ncol,k) = max(0._r8, fxliq(:ncol,k))
     389   625724568 :        fxice(:ncol,k) = max(0._r8, fxice(:ncol,k))
     390             :     end do
     391             : 
     392             : ! Limit the flux out of the bottom of each cell to the water content in each phase.
     393             : ! Apply mxsedfac to prevent generating very small negative cloud water/ice
     394             : ! NOTE, REMOVED CLOUD FACTOR FROM AVAILABLE WATER. ALL CLOUD WATER IS IN CLOUDS.
     395             : ! ***Should we include the flux in the top, to allow for thin surface layers?
     396             : ! ***Requires simple treatment of cloud overlap, already included below.
     397    40374936 :     do k = 1,pver
     398   650693736 :        do i = 1,ncol
     399   610318800 :           fxliq(i,k+1) = min( fxliq(i,k+1), mxsedfac * cldliq(i,k) * pdel(i,k) )
     400   649198368 :           fxice(i,k+1) = min( fxice(i,k+1), mxsedfac * cldice(i,k) * pdel(i,k) )
     401             : !!$        fxliq(i,k+1) = min( fxliq(i,k+1), cldliq(i,k) * pdel(i,k) + fxliq(i,k))
     402             : !!$        fxice(i,k+1) = min( fxice(i,k+1), cldice(i,k) * pdel(i,k) + fxice(i,k))
     403             : !!$        fxliq(i,k+1) = min( fxliq(i,k+1), cloud(i,k) * cldliq(i,k) * pdel(i,k) )
     404             : !!$        fxice(i,k+1) = min( fxice(i,k+1), cloud(i,k) * cldice(i,k) * pdel(i,k) )
     405             :        end do
     406             :     end do
     407             : 
     408             : ! Now calculate the tendencies assuming that condensate evaporates when
     409             : ! it falls into environment, and does not when it falls into cloud.
     410             : ! All flux out of the layer comes from the cloudy part.
     411             : ! Assume maximum overlap for stratiform clouds
     412             : !  if cloud above < cloud,  all water falls into cloud below
     413             : !  if cloud above > cloud,  water split between cloud  and environment
     414    40374936 :     do k = 1,pver
     415   649198368 :        cldab(:ncol) = 0._r8
     416   650693736 :        do i = 1,ncol
     417             : ! cloud overlap cloud factor
     418   610318800 :           cldovrl  = min( cloud(i,k) / (cldab(i)+.0001_r8), 1._r8 )
     419   610318800 :           cldab(i) = cloud(i,k)
     420             : ! evaporation into environment cause moistening and cooling
     421   610318800 :           evapliq = fxliq(i,k) * (1._r8-cldovrl) / (dtime * pdel(i,k))  ! into env (kg/kg/s)
     422   610318800 :           evapice = fxice(i,k) * (1._r8-cldovrl) / (dtime * pdel(i,k))  ! into env (kg/kg/s)
     423   610318800 :           wvtend(i,k) = evapliq + evapice                          ! evaporation into environment (kg/kg/s)
     424   610318800 :           htend (i,k) = -latvap*evapliq -(latvap+latice)*evapice   ! evaporation (W/kg)
     425             : ! net flux into cloud changes cloud liquid/ice (all flux is out of cloud)
     426   610318800 :           liqtend(i,k)  = (fxliq(i,k)*cldovrl - fxliq(i,k+1)) / (dtime * pdel(i,k))
     427   649198368 :           icetend(i,k)  = (fxice(i,k)*cldovrl - fxice(i,k+1)) / (dtime * pdel(i,k))
     428             :        end do
     429             :     end do
     430             : 
     431             : ! convert flux out the bottom to mass units Pa -> kg/m2/s
     432    24969168 :     sfliq(:ncol) = fxliq(:ncol,pverp) / (dtime*gravit)
     433    24969168 :     sfice(:ncol) = fxice(:ncol,pverp) / (dtime*gravit)
     434             : 
     435     1495368 :     return
     436             :   end subroutine cld_sediment_tend
     437             : 
     438             : !===============================================================================
     439     2990736 :   subroutine getflx(ncol, xw, phi, vel, deltat, flux)
     440             : 
     441             : !.....xw1.......xw2.......xw3.......xw4.......xw5.......xw6
     442             : !....psiw1.....psiw2.....psiw3.....psiw4.....psiw5.....psiw6
     443             : !....velw1.....velw2.....velw3.....velw4.....velw5.....velw6
     444             : !.........phi1......phi2.......phi3.....phi4.......phi5.......
     445             : 
     446             : 
     447             : 
     448             :     integer, intent(in) :: ncol                      ! number of colums to process
     449             : 
     450             :     integer i
     451             :     integer k
     452             : 
     453             :     real (r8), intent(in) :: vel(pcols,pverp)
     454             :     real (r8) flux(pcols,pverp)
     455             :     real (r8) xw(pcols,pverp)
     456             :     real (r8) psi(pcols,pverp)
     457             :     real (r8), intent(in) :: phi(pcols,pverp-1)
     458             :     real (r8) fdot(pcols,pverp)
     459             :     real (r8) xx(pcols)
     460             :     real (r8) fxdot(pcols)
     461             :     real (r8) fxdd(pcols)
     462             : 
     463             :     real (r8) psistar(pcols)
     464             :     real (r8) deltat
     465             : 
     466             :     real (r8) xxk(pcols,pver)
     467             : 
     468    49938336 :     do i = 1,ncol
     469             : !        integral of phi
     470    46947600 :        psi(i,1) = 0._r8
     471             : !        fluxes at boundaries
     472    46947600 :        flux(i,1) = 0._r8
     473    49938336 :        flux(i,pverp) = 0._r8
     474             :     end do
     475             : 
     476             : !     integral function
     477    80749872 :     do k = 2,pverp
     478  1301387472 :        do i = 1,ncol
     479  1298396736 :           psi(i,k) = phi(i,k-1)*(xw(i,k)-xw(i,k-1)) + psi(i,k-1)
     480             :        end do
     481             :     end do
     482             : 
     483             : 
     484             : !     calculate the derivatives for the interpolating polynomial
     485     2990736 :     call cfdotmc_pro (ncol, xw, psi, fdot)
     486             : 
     487             : !  NEW WAY
     488             : !     calculate fluxes at interior pts
     489    77759136 :     do k = 2,pver
     490  1251449136 :        do i = 1,ncol
     491  1248458400 :           xxk(i,k) = xw(i,k)-vel(i,k)*deltat
     492             :        end do
     493             :     end do
     494    77759136 :     do k = 2,pver
     495    74768400 :        call cfint2(ncol, xw, psi, fdot, xxk(1,k), fxdot, fxdd, psistar)
     496  1251449136 :        do i = 1,ncol
     497  1248458400 :           flux(i,k) = (psi(i,k)-psistar(i))
     498             :        end do
     499             :     end do
     500             : 
     501             : 
     502     2990736 :     return
     503             :   end subroutine getflx
     504             : 
     505             : 
     506             : 
     507             : !##############################################################################
     508             : 
     509    74768400 :   subroutine cfint2 (ncol, x, f, fdot, xin, fxdot, fxdd, psistar)
     510             : 
     511             : 
     512             : 
     513             : ! input
     514             :     integer ncol                      ! number of colums to process
     515             : 
     516             :     real (r8) x(pcols, pverp)
     517             :     real (r8) f(pcols, pverp)
     518             :     real (r8) fdot(pcols, pverp)
     519             :     real (r8) xin(pcols)
     520             : 
     521             : ! output
     522             :     real (r8) fxdot(pcols)
     523             :     real (r8) fxdd(pcols)
     524             :     real (r8) psistar(pcols)
     525             : 
     526             :     integer i
     527             :     integer k
     528             :     integer intz(pcols)
     529             :     real (r8) dx
     530             :     real (r8) s
     531             :     real (r8) c2
     532             :     real (r8) c3
     533             :     real (r8) xx
     534             :     real (r8) xinf
     535             :     real (r8) psi1, psi2, psi3, psim
     536             :     real (r8) cfint
     537             :     real (r8) cfnew
     538             :     real (r8) xins(pcols)
     539             : 
     540             : !     the minmod function 
     541             :     real (r8) a, b, c
     542             :     real (r8) minmod
     543             :     real (r8) medan
     544             :     logical found_error
     545             : 
     546             :     minmod(a,b) = 0.5_r8*(sign(1._r8,a) + sign(1._r8,b))*min(abs(a),abs(b))
     547             :     medan(a,b,c) = a + minmod(b-a,c-a)
     548             : 
     549  1248458400 :     do i = 1,ncol
     550  1173690000 :        xins(i) = medan(x(i,1), xin(i), x(i,pverp))
     551  1248458400 :        intz(i) = 0
     552             :     end do
     553             : 
     554             : ! first find the interval 
     555  2018746800 :     do k =  1,pverp-1
     556 32534686800 :        do i = 1,ncol
     557 32459918400 :           if ((xins(i)-x(i,k))*(x(i,k+1)-xins(i)).ge.0) then
     558  2056902817 :              intz(i) = k
     559             :           endif
     560             :        end do
     561             :     end do
     562             : 
     563    74768400 :     found_error=.false.
     564  1248458400 :     do i = 1,ncol
     565  1248458400 :        if (intz(i).eq.0._r8) found_error=.true.
     566             :     end do
     567    74768400 :     if(found_error) then
     568           0 :        do i = 1,ncol
     569           0 :           if (intz(i).eq.0._r8) then
     570           0 :              write(iulog,*) ' interval was not found for col i ', i
     571           0 :              call endrun('CFINT2')
     572             :           endif
     573             :        end do
     574             :     endif
     575             : 
     576             : ! now interpolate
     577  1248458400 :     do i = 1,ncol
     578  1173690000 :        k = intz(i)
     579  1173690000 :        dx = (x(i,k+1)-x(i,k))
     580  1173690000 :        s = (f(i,k+1)-f(i,k))/dx
     581  1173690000 :        c2 = (3*s-2*fdot(i,k)-fdot(i,k+1))/dx
     582  1173690000 :        c3 = (fdot(i,k)+fdot(i,k+1)-2*s)/dx**2
     583  1173690000 :        xx = (xins(i)-x(i,k))
     584  1173690000 :        fxdot(i) =  (3*c3*xx + 2*c2)*xx + fdot(i,k)
     585  1173690000 :        fxdd(i) = 6*c3*xx + 2*c2
     586  1173690000 :        cfint = ((c3*xx + c2)*xx + fdot(i,k))*xx + f(i,k)
     587             : 
     588             : !        limit the interpolant
     589  1173690000 :        psi1 = f(i,k)+(f(i,k+1)-f(i,k))*xx/dx
     590  1173690000 :        if (k.eq.1) then
     591           0 :           psi2 = f(i,1)
     592             :        else
     593  1173690000 :           psi2 = f(i,k) + (f(i,k)-f(i,k-1))*xx/(x(i,k)-x(i,k-1))
     594             :        endif
     595  1173690000 :        if (k+1.eq.pverp) then
     596    23602375 :           psi3 = f(i,pverp)
     597             :        else
     598  1150087625 :           psi3 = f(i,k+1) - (f(i,k+2)-f(i,k+1))*(dx-xx)/(x(i,k+2)-x(i,k+1))
     599             :        endif
     600  1173690000 :        psim = medan(psi1, psi2, psi3)
     601  1173690000 :        cfnew = medan(cfint, psi1, psim)
     602             :        if (abs(cfnew-cfint)/(abs(cfnew)+abs(cfint)+1.e-36_r8)  .gt..03_r8) then
     603             : !     CHANGE THIS BACK LATER!!!
     604             : !     $        .gt..1) then
     605             : 
     606             : 
     607             : !     UNCOMMENT THIS LATER!!!
     608             : !            write(iulog,*) ' cfint2 limiting important ', cfint, cfnew
     609             : 
     610             : 
     611             :        endif
     612  1248458400 :        psistar(i) = cfnew
     613             :     end do
     614             : 
     615    74768400 :     return
     616             :   end subroutine cfint2
     617             : 
     618             : 
     619             : 
     620             : !##############################################################################
     621             : 
     622     2990736 :   subroutine cfdotmc_pro (ncol, x, f, fdot)
     623             : 
     624             : !     prototype version; eventually replace with final SPITFIRE scheme
     625             : 
     626             : !     calculate the derivative for the interpolating polynomial
     627             : !     multi column version
     628             : 
     629             : 
     630             : 
     631             : ! input
     632             :     integer ncol                      ! number of colums to process
     633             : 
     634             :     real (r8) x(pcols, pverp)
     635             :     real (r8) f(pcols, pverp)
     636             : ! output
     637             :     real (r8) fdot(pcols, pverp)          ! derivative at nodes
     638             : 
     639             : ! assumed variable distribution
     640             : !     x1.......x2.......x3.......x4.......x5.......x6     1,pverp points
     641             : !     f1.......f2.......f3.......f4.......f5.......f6     1,pverp points
     642             : !     ...sh1.......sh2......sh3......sh4......sh5....     1,pver points
     643             : !     .........d2.......d3.......d4.......d5.........     2,pver points
     644             : !     .........s2.......s3.......s4.......s5.........     2,pver points
     645             : !     .............dh2......dh3......dh4.............     2,pver-1 points
     646             : !     .............eh2......eh3......eh4.............     2,pver-1 points
     647             : !     ..................e3.......e4..................     3,pver-1 points
     648             : !     .................ppl3......ppl4................     3,pver-1 points
     649             : !     .................ppr3......ppr4................     3,pver-1 points
     650             : !     .................t3........t4..................     3,pver-1 points
     651             : !     ................fdot3.....fdot4................     3,pver-1 points
     652             : 
     653             : 
     654             : ! work variables
     655             : 
     656             : 
     657             :     integer i
     658             :     integer k
     659             : 
     660             :     real (r8) a                    ! work var
     661             :     real (r8) b                    ! work var
     662             :     real (r8) c                    ! work var
     663             :     real (r8) s(pcols,pverp)             ! first divided differences at nodes
     664             :     real (r8) sh(pcols,pverp)            ! first divided differences between nodes
     665             :     real (r8) d(pcols,pverp)             ! second divided differences at nodes
     666             :     real (r8) dh(pcols,pverp)            ! second divided differences between nodes
     667             :     real (r8) e(pcols,pverp)             ! third divided differences at nodes
     668             :     real (r8) eh(pcols,pverp)            ! third divided differences between nodes
     669             :     real (r8) pp                   ! p prime
     670             :     real (r8) ppl(pcols,pverp)           ! p prime on left
     671             :     real (r8) ppr(pcols,pverp)           ! p prime on right
     672             :     real (r8) qpl
     673             :     real (r8) qpr
     674             :     real (r8) ttt
     675             :     real (r8) t
     676             :     real (r8) tmin
     677             :     real (r8) tmax
     678             :     real (r8) delxh(pcols,pverp)
     679             : 
     680             : 
     681             : !     the minmod function 
     682             :     real (r8) minmod
     683             :     real (r8) medan
     684             :     minmod(a,b) = 0.5_r8*(sign(1._r8,a) + sign(1._r8,b))*min(abs(a),abs(b))
     685             :     medan(a,b,c) = a + minmod(b-a,c-a)
     686             : 
     687    80749872 :     do k = 1,pver
     688             : 
     689             : 
     690             : !        first divided differences between nodes
     691  1298396736 :        do i = 1, ncol
     692  1220637600 :           delxh(i,k) = (x(i,k+1)-x(i,k))
     693  1298396736 :           sh(i,k) = (f(i,k+1)-f(i,k))/delxh(i,k)
     694             :        end do
     695             : 
     696             : !        first and second divided differences at nodes
     697    80749872 :        if (k.ge.2) then
     698  1248458400 :           do i = 1,ncol
     699  1173690000 :              d(i,k) = (sh(i,k)-sh(i,k-1))/(x(i,k+1)-x(i,k-1))
     700  1248458400 :              s(i,k) = minmod(sh(i,k),sh(i,k-1))
     701             :           end do
     702             :        endif
     703             :     end do
     704             : 
     705             : !     second and third divided diffs between nodes
     706    74768400 :     do k = 2,pver-1
     707  1201510800 :        do i = 1, ncol
     708  1126742400 :           eh(i,k) = (d(i,k+1)-d(i,k))/(x(i,k+2)-x(i,k-1))
     709  1198520064 :           dh(i,k) = minmod(d(i,k),d(i,k+1))
     710             :        end do
     711             :     end do
     712             : 
     713             : !     treat the boundaries
     714    49938336 :     do i = 1,ncol
     715    46947600 :        e(i,2) = eh(i,2)
     716    46947600 :        e(i,pver) = eh(i,pver-1)
     717             : !        outside level
     718             :        fdot(i,1) = sh(i,1) - d(i,2)*delxh(i,1)  &
     719    46947600 :             - eh(i,2)*delxh(i,1)*(x(i,1)-x(i,3))
     720    46947600 :        fdot(i,1) = minmod(fdot(i,1),3*sh(i,1))
     721             :        fdot(i,pverp) = sh(i,pver) + d(i,pver)*delxh(i,pver)  &
     722    46947600 :             + eh(i,pver-1)*delxh(i,pver)*(x(i,pverp)-x(i,pver-1))
     723    46947600 :        fdot(i,pverp) = minmod(fdot(i,pverp),3*sh(i,pver))
     724             : !        one in from boundary
     725    46947600 :        fdot(i,2) = sh(i,1) + d(i,2)*delxh(i,1) - eh(i,2)*delxh(i,1)*delxh(i,2)
     726    46947600 :        fdot(i,2) = minmod(fdot(i,2),3*s(i,2))
     727             :        fdot(i,pver) = sh(i,pver) - d(i,pver)*delxh(i,pver)   &
     728    46947600 :             - eh(i,pver-1)*delxh(i,pver)*delxh(i,pver-1)
     729    49938336 :        fdot(i,pver) = minmod(fdot(i,pver),3*s(i,pver))
     730             :     end do
     731             : 
     732             : 
     733    71777664 :     do k = 3,pver-1
     734  1151572464 :        do i = 1,ncol
     735  1148581728 :           e(i,k) = minmod(eh(i,k),eh(i,k-1))
     736             :        end do
     737             :     end do
     738             : 
     739             : 
     740             : 
     741    71777664 :     do k = 3,pver-1
     742             : 
     743  1151572464 :        do i = 1,ncol
     744             : 
     745             : !           p prime at k-0.5
     746  1079794800 :           ppl(i,k)=sh(i,k-1) + dh(i,k-1)*delxh(i,k-1)  
     747             : !           p prime at k+0.5
     748  1079794800 :           ppr(i,k)=sh(i,k)   - dh(i,k)  *delxh(i,k)
     749             : 
     750  1079794800 :           t = minmod(ppl(i,k),ppr(i,k))
     751             : 
     752             : !           derivate from parabola thru f(i,k-1), f(i,k), and f(i,k+1)
     753  1079794800 :           pp = sh(i,k-1) + d(i,k)*delxh(i,k-1) 
     754             : 
     755             : !           quartic estimate of fdot
     756             :           fdot(i,k) = pp                            &
     757             :                - delxh(i,k-1)*delxh(i,k)            &
     758  1079794800 :                *(  eh(i,k-1)*(x(i,k+2)-x(i,k  ))    &
     759  1079794800 :                + eh(i,k  )*(x(i,k  )-x(i,k-2))      &
     760  2159589600 :                )/(x(i,k+2)-x(i,k-2))
     761             : 
     762             : !           now limit it
     763             :           qpl = sh(i,k-1)       &
     764             :                + delxh(i,k-1)*minmod(d(i,k-1)+e(i,k-1)*(x(i,k)-x(i,k-2)), &
     765  1079794800 :                d(i,k)  -e(i,k)*delxh(i,k))
     766             :           qpr = sh(i,k)         &
     767             :                + delxh(i,k  )*minmod(d(i,k)  +e(i,k)*delxh(i,k-1),        &
     768  1079794800 :                d(i,k+1)+e(i,k+1)*(x(i,k)-x(i,k+2)))
     769             : 
     770  1079794800 :           fdot(i,k) = medan(fdot(i,k), qpl, qpr)
     771             : 
     772  1079794800 :           ttt = minmod(qpl, qpr)
     773  1079794800 :           tmin = min(0._r8,3*s(i,k),1.5_r8*t,ttt)
     774  1079794800 :           tmax = max(0._r8,3*s(i,k),1.5_r8*t,ttt)
     775             : 
     776  1148581728 :           fdot(i,k) = fdot(i,k) + minmod(tmin-fdot(i,k), tmax-fdot(i,k))
     777             : 
     778             :        end do
     779             : 
     780             :     end do
     781             : 
     782     2990736 :     return
     783             :   end subroutine cfdotmc_pro
     784             : end module pkg_cld_sediment

Generated by: LCOV version 1.14