LCOV - code coverage report
Current view: top level - physics/carma/base - versub.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 36 0.0 %
Date: 2025-03-14 01:30:37 Functions: 0 1 0.0 %

          Line data    Source code
       1             : ! Include shortname defintions, so that the F77 code does not have to be modified to
       2             : ! reference the CARMA structure.
       3             : #include "carma_globaer.h"
       4             : 
       5             : !!  This routine solves for sedimentation using an explicit substepping approach. It
       6             : !!  is faster and handles large cfl and irregular grids better than the normal PPM
       7             : !!  solver (versol), but it is more diffusive.
       8             : !!
       9             : !! @author Andy Ackerman, Chuck Bardeen 
      10             : !! version Aug 2010
      11           0 : subroutine versub(carma, cstate, pcmax, cvert, itbnd, ibbnd, ftop, fbot, cvert_tbnd, cvert_bbnd, &
      12           0 :   vertadvu, vertadvd, vertdifu, vertdifd, rc)
      13             : 
      14             :   ! types
      15             :   use carma_precision_mod
      16             :   use carma_enums_mod
      17             :   use carma_constants_mod
      18             :   use carma_types_mod
      19             :   use carmastate_mod
      20             :   use carma_mod
      21             : 
      22             :   implicit none
      23             : 
      24             :   type(carma_type), intent(in)         :: carma           !! the carma object
      25             :   type(carmastate_type), intent(inout) :: cstate          !! the carma state object
      26             :   real(kind=f), intent(in)             :: pcmax(NZ)       !! maximum particle concentration (#/x/y/z)
      27             :   real(kind=f), intent(inout)          :: cvert(NZ)       !! quantity being transported (#/x/y/z)
      28             :   integer, intent(in)                  :: itbnd           !! top boundary condition
      29             :   integer, intent(in)                  :: ibbnd           !! bottom boundary condition
      30             :   real(kind=f), intent(in)             :: ftop            !! flux at top boundary
      31             :   real(kind=f), intent(in)             :: fbot            !! flux at bottom boundary
      32             :   real(kind=f), intent(in)             :: cvert_tbnd      !! quantity at top boundary
      33             :   real(kind=f), intent(in)             :: cvert_bbnd      !! quantity at bottom boundary
      34             :   real(kind=f), intent(in)             :: vertadvu(NZP1)  !! upward vertical transport rate into level k from level k-1 [cm/s]
      35             :   real(kind=f), intent(in)             :: vertadvd(NZP1)  !! downward vertical transport rate into level k from level k-1 [cm/s]
      36             :   real(kind=f), intent(in)             :: vertdifu(NZP1)  !! upward vertical diffusion rate into level k from level k-1 [cm/s]
      37             :   real(kind=f), intent(in)             :: vertdifd(NZP1)  !! downward vertical diffusion rate into level k from level k-1 [cm/s]
      38             :   integer, intent(inout)               :: rc              !! return code, negative indicates failure
      39             : 
      40             :   !  Declare local variables
      41             :   integer                        :: iz
      42             :   integer                        :: istep
      43             :   integer                        :: nstep_sed
      44           0 :   real(kind=f)                   :: fvert(NZ)
      45           0 :   real(kind=f)                   :: up(NZP1)
      46           0 :   real(kind=f)                   :: dn(NZP1)
      47             :   real(kind=f)                   :: cfl_max
      48             :   real(kind=f)                   :: fvert_1
      49             :   real(kind=f)                   :: fvert_nz
      50             : 
      51             :   ! Determine the total upward and downward velocities.
      52           0 :   up(:) = vertadvu(:) + vertdifu(:)
      53           0 :   dn(:) = vertadvd(:) + vertdifd(:)
      54             : 
      55             :   ! Compute the maximum CFL for each bin that has a significant concentration
      56             :   ! of particles.
      57           0 :   cfl_max = 0._f
      58             : 
      59           0 :   do iz = 1, NZ
      60           0 :     if (pcmax(iz) > SMALL_PC) then
      61           0 :       cfl_max = max(cfl_max, max(abs(up(iz)), abs(up(iz+1)), abs(dn(iz)), abs(dn(iz+1))) * dtime / dz(iz))
      62             :     end if
      63             :   end do
      64             : 
      65             :   ! Use the maximum CFL determined above to figure out how much substepping is
      66             :   ! needed to sediment explicitly without violating the CFL anywhere in the column.
      67           0 :   if (cfl_max >= 0._f) then
      68           0 :     nstep_sed = int(1._f + cfl_max)
      69             :   else
      70             :     nstep_sed = 0
      71             :   endif
      72             :   
      73             :   ! If velocities are in both directions, then more steps are needed to make sure
      74             :   ! that no more than half of the concentration can be transported in either direction.
      75           0 :   if (maxval(up(:) * dn(:)) > 0._f) then
      76           0 :     nstep_sed = nstep_sed * 2
      77             :   end if
      78             : 
      79             :   ! Determine the top and bottom boundary fluxes, keeping in mind that
      80             :   ! the velocities and grid coordinates are reversed in sigma or hybrid
      81             :   ! coordinates
      82           0 :   if ((igridv .eq. I_SIG) .or. (igridv .eq. I_HYBRID)) then
      83           0 :     if (itbnd .eq. I_FLUX_SPEC) then
      84           0 :       fvert_nz = -fbot
      85             :     else
      86           0 :       fvert_nz = cvert_bbnd*dn(NZ+1)
      87             :     end if
      88             : 
      89           0 :     if (ibbnd .eq. I_FLUX_SPEC) then
      90           0 :       fvert_1 = -ftop
      91             :     else
      92           0 :       fvert_1 = cvert_tbnd*up(1)
      93             :     end if
      94             :   
      95             :   else
      96           0 :     if (itbnd .eq. I_FLUX_SPEC) then
      97           0 :       fvert_nz = ftop
      98             :     else
      99           0 :       fvert_nz = cvert_tbnd*dn(NZ+1)
     100             :     end if
     101             : 
     102           0 :     if (ibbnd .eq. I_FLUX_SPEC) then
     103           0 :       fvert_1 = fbot
     104             :     else
     105           0 :       fvert_1 = cvert_bbnd*up(1)
     106             :     end if
     107             :   endif
     108             : 
     109             :   ! Sediment the particles using multiple iterations to satisfy the CFL.
     110           0 :   do istep = 1, nstep_sed
     111             : 
     112             :     ! Determine the net particle flux at each gridbox. The first and last levels
     113             :     ! need special treatment to handle to bottom and top boundary conditions.
     114           0 :     fvert(1) = (-cvert(1)*dn(1) + fvert_1 + cvert(2)*dn(2) - cvert(1)*up(2))
     115             :     
     116           0 :     do iz = 2, NZ-1
     117           0 :       fvert(iz) = (-cvert(iz)*dn(iz) + cvert(iz-1)*up(iz) + cvert(iz+1)*dn(iz+1) - cvert(iz)*up(iz+1))
     118             :     end do
     119             : 
     120           0 :     fvert(NZ) = (-cvert(NZ)*dn(NZ) + cvert(NZ-1)*up(NZ) + fvert_nz - cvert(NZ)*up(NZ+1))
     121             :     
     122             :     ! Now update the actual concentrations.
     123           0 :     cvert(:) = cvert(:) + fvert(:) * dtime / nstep_sed / dz(:)
     124             :   enddo
     125             : 
     126           0 :   return
     127           0 : end subroutine versub

Generated by: LCOV version 1.14