LCOV - code coverage report
Current view: top level - dynamics/se/dycore - fv_mapz.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 182 804 22.6 %
Date: 2025-01-13 21:54:50 Functions: 3 9 33.3 %

          Line data    Source code
       1             : 
       2             : !**************************************************************************************
       3             : !
       4             : ! fv_mapz contains vertical remapping algorithms that come from the FV3 dycore.
       5             : ! They have been minimally modified for use in CAM.
       6             : !
       7             : ! The following license statement is from the original code.
       8             : !
       9             : !**************************************************************************************
      10             :   
      11             : !***********************************************************************
      12             : !*                   GNU Lesser General Public License                 
      13             : !*
      14             : !* This file is part of the FV3 dynamical core.
      15             : !*
      16             : !* The FV3 dynamical core is free software: you can redistribute it 
      17             : !* and/or modify it under the terms of the
      18             : !* GNU Lesser General Public License as published by the
      19             : !* Free Software Foundation, either version 3 of the License, or 
      20             : !* (at your option) any later version.
      21             : !*
      22             : !* The FV3 dynamical core is distributed in the hope that it will be 
      23             : !* useful, but WITHOUT ANYWARRANTY; without even the implied warranty 
      24             : !* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
      25             : !* See the GNU General Public License for more details.
      26             : !*
      27             : !* You should have received a copy of the GNU Lesser General Public
      28             : !* License along with the FV3 dynamical core.  
      29             : !* If not, see <http://www.gnu.org/licenses/>.
      30             : !***********************************************************************
      31             : module fv_mapz
      32             :   
      33             :   use shr_kind_mod,           only: r8=>shr_kind_r8
      34             :   use cam_abortutils,         only: endrun
      35             :   
      36             :   implicit none
      37             :   
      38             :   public map_scalar, map1_ppm, mapn_tracer
      39             :   
      40             :   real(kind=r8), parameter::  r3 = 1._r8/3._r8, r23 = 2._r8/3._r8, r12 = 1._r8/12._r8
      41             : contains
      42             :   
      43           0 :   subroutine map_scalar( km,   pe1,    q1,   qs,           &
      44           0 :        kn,   pe2,    q2,   i1, i2,       &
      45             :        j,  ibeg, iend, jbeg, jend, iv,  kord, q_min)
      46             :     ! iv=1
      47             :     integer, intent(in) :: i1                !< Starting longitude
      48             :     integer, intent(in) :: i2                !< Finishing longitude
      49             :     integer, intent(in) :: iv                !< Mode: 0 == constituents 1 == temp 2 == remap temp with cs scheme
      50             :     integer, intent(in) :: kord              !< Method order
      51             :     integer, intent(in) :: j                 !< Current latitude
      52             :     integer, intent(in) :: ibeg, iend, jbeg, jend
      53             :     integer, intent(in) :: km                !< Original vertical dimension
      54             :     integer, intent(in) :: kn                !< Target vertical dimension
      55             :     real(kind=r8), intent(in) ::   qs(i1:i2)       !< bottom BC
      56             :     real(kind=r8), intent(in) ::  pe1(i1:i2,km+1)  !< pressure at layer edges from model top to bottom surface in the original vertical coordinate
      57             :     real(kind=r8), intent(in) ::  pe2(i1:i2,kn+1)  !< pressure at layer edges from model top to bottom surface in the new vertical coordinate
      58             :     real(kind=r8), intent(in) ::    q1(ibeg:iend,jbeg:jend,km) !< Field input
      59             :     ! INPUT/OUTPUT PARAMETERS:
      60             :     real(kind=r8), intent(inout)::  q2(ibeg:iend,jbeg:jend,kn) !< Field output
      61             :     real(kind=r8), intent(in):: q_min
      62             :     
      63             :     ! DESCRIPTION:
      64             :     ! IV = 0: constituents
      65             :     ! pe1: pressure at layer edges (from model top to bottom surface)
      66             :     !      in the original vertical coordinate
      67             :     ! pe2: pressure at layer edges (from model top to bottom surface)
      68             :     !      in the new vertical coordinate
      69             :     ! LOCAL VARIABLES:
      70           0 :     real(kind=r8)    dp1(i1:i2,km)
      71           0 :     real(kind=r8)   q4(4,i1:i2,km)
      72             :     real(kind=r8)    pl, pr, qsum, dp, esl
      73             :     integer i, k, l, m, k0
      74             :     
      75           0 :     do k=1,km
      76           0 :       do i=i1,i2
      77           0 :         dp1(i,k) = pe1(i,k+1) - pe1(i,k)
      78           0 :         q4(1,i,k) = q1(i,j,k)
      79             :       enddo
      80             :     enddo
      81             :     
      82             :     ! Compute vertical subgrid distribution
      83           0 :     if ( kord >7 ) then
      84           0 :       call scalar_profile( qs, q4, dp1, km, i1, i2, iv, kord, q_min )
      85             :     else
      86           0 :       call ppm_profile( q4, dp1, km, i1, i2, iv, kord )
      87             :     endif
      88             :     
      89           0 :     do i=i1,i2
      90             :       k0 = 1
      91           0 :       do 555 k=1,kn
      92           0 :         do l=k0,km
      93             :           ! locate the top edge: pe2(i,k)
      94           0 :           if( pe2(i,k) >= pe1(i,l) .and. pe2(i,k) <= pe1(i,l+1) ) then
      95           0 :             pl = (pe2(i,k)-pe1(i,l)) / dp1(i,l)
      96           0 :             if( pe2(i,k+1) <= pe1(i,l+1) ) then
      97             :               ! entire new grid is within the original grid
      98           0 :               pr = (pe2(i,k+1)-pe1(i,l)) / dp1(i,l)
      99           0 :               q2(i,j,k) = q4(2,i,l) + 0.5_r8*(q4(4,i,l)+q4(3,i,l)-q4(2,i,l))  &
     100           0 :                    *(pr+pl)-q4(4,i,l)*r3*(pr*(pr+pl)+pl**2)
     101           0 :               k0 = l
     102           0 :               goto 555
     103             :             else
     104             :               ! Fractional area...
     105             :               qsum = (pe1(i,l+1)-pe2(i,k))*(q4(2,i,l)+0.5_r8*(q4(4,i,l)+   &
     106             :                    q4(3,i,l)-q4(2,i,l))*(1._r8+pl)-q4(4,i,l)*           &
     107           0 :                    (r3*(1._r8+pl*(1._r8+pl))))
     108           0 :               do m=l+1,km
     109             :                 ! locate the bottom edge: pe2(i,k+1)
     110           0 :                 if( pe2(i,k+1) > pe1(i,m+1) ) then
     111             :                   ! Whole layer
     112           0 :                   qsum = qsum + dp1(i,m)*q4(1,i,m)
     113             :                 else
     114           0 :                   dp = pe2(i,k+1)-pe1(i,m)
     115           0 :                   esl = dp / dp1(i,m)
     116             :                   qsum = qsum + dp*(q4(2,i,m)+0.5_r8*esl*               &
     117           0 :                        (q4(3,i,m)-q4(2,i,m)+q4(4,i,m)*(1._r8-r23*esl)))
     118           0 :                   k0 = m
     119           0 :                   goto 123
     120             :                 endif
     121             :               enddo
     122             :               goto 123
     123             :             endif
     124             :           endif
     125             :         enddo
     126           0 : 123     q2(i,j,k) = qsum / ( pe2(i,k+1) - pe2(i,k) )
     127           0 : 555     continue
     128             :       enddo
     129           0 :   end subroutine map_scalar
     130             :     
     131             :   
     132           0 :   subroutine mapn_tracer(nq, km, pe1, pe2, q1, dp2, kord, j,     &
     133             :        i1, i2, isd, ied, jsd, jed, q_min, fill)
     134             :     ! INPUT PARAMETERS:
     135             :     integer, intent(in):: km                !< vertical dimension
     136             :     integer, intent(in):: j, nq, i1, i2
     137             :     integer, intent(in):: isd, ied, jsd, jed
     138             :     integer, intent(in):: kord(nq)
     139             :     real(kind=r8), intent(in)::  pe1(i1:i2,km+1)     !< pressure at layer edges from model top to bottom surface in the original vertical coordinate
     140             :     real(kind=r8), intent(in)::  pe2(i1:i2,km+1)     !< pressure at layer edges from model top to bottom surface in the new vertical coordinate
     141             :     real(kind=r8), intent(in)::  dp2(i1:i2,km)
     142             :     real(kind=r8), intent(in)::  q_min
     143             :     logical, intent(in):: fill
     144             :     real(kind=r8), intent(inout):: q1(isd:ied,jsd:jed,km,nq) ! Field input
     145             :     ! LOCAL VARIABLES:
     146           0 :     real(kind=r8):: q4(4,i1:i2,km,nq)
     147           0 :     real(kind=r8):: q2(i1:i2,km,nq) !< Field output
     148           0 :     real(kind=r8):: qsum(nq)
     149           0 :     real(kind=r8):: dp1(i1:i2,km)
     150           0 :     real(kind=r8):: qs(i1:i2)
     151             :     real(kind=r8):: pl, pr, dp, esl, fac1, fac2
     152             :     integer:: i, k, l, m, k0, iq
     153             :     
     154           0 :     do k=1,km
     155           0 :       do i=i1,i2
     156           0 :         dp1(i,k) = pe1(i,k+1) - pe1(i,k)
     157             :       enddo
     158             :     enddo
     159             :     
     160           0 :     do iq=1,nq
     161           0 :       do k=1,km
     162           0 :         do i=i1,i2
     163           0 :           q4(1,i,k,iq) = q1(i,j,k,iq)
     164             :         enddo
     165             :       enddo
     166           0 :       call scalar_profile( qs, q4(1,i1,1,iq), dp1, km, i1, i2, 0, kord(iq), q_min )
     167             :     enddo
     168             :     ! Mapping
     169           0 :     do 1000 i=i1,i2
     170             :       k0 = 1
     171           0 :       do 555 k=1,km
     172           0 :         do 100 l=k0,km
     173             :           ! locate the top edge: pe2(i,k)
     174           0 :           if(pe2(i,k) >= pe1(i,l) .and. pe2(i,k) <= pe1(i,l+1)) then
     175           0 :             pl = (pe2(i,k)-pe1(i,l)) / dp1(i,l)
     176           0 :             if(pe2(i,k+1) <= pe1(i,l+1)) then
     177             :               ! entire new grid is within the original grid
     178           0 :               pr = (pe2(i,k+1)-pe1(i,l)) / dp1(i,l)
     179           0 :               fac1 = pr + pl
     180           0 :               fac2 = r3*(pr*fac1 + pl*pl) 
     181           0 :               fac1 = 0.5_r8*fac1
     182           0 :               do iq=1,nq
     183           0 :                 q2(i,k,iq) = q4(2,i,l,iq) + (q4(4,i,l,iq)+q4(3,i,l,iq)-q4(2,i,l,iq))*fac1  &
     184           0 :                      -  q4(4,i,l,iq)*fac2
     185             :               enddo
     186             :               k0 = l
     187             :               goto 555
     188             :             else
     189             :               ! Fractional area...
     190           0 :               dp = pe1(i,l+1) - pe2(i,k)
     191           0 :               fac1 = 1.0_r8 + pl
     192           0 :               fac2 = r3*(1.0_r8+pl*fac1)
     193           0 :               fac1 = 0.5_r8*fac1
     194           0 :               do iq=1,nq
     195           0 :                 qsum(iq) = dp*(q4(2,i,l,iq) + (q4(4,i,l,iq)+   &
     196           0 :                      q4(3,i,l,iq) - q4(2,i,l,iq))*fac1 - q4(4,i,l,iq)*fac2)
     197             :               enddo
     198           0 :               do m=l+1,km
     199             :                 ! locate the bottom edge: pe2(i,k+1)
     200           0 :                 if(pe2(i,k+1) > pe1(i,m+1) ) then
     201             :                   ! Whole layer..
     202           0 :                   do iq=1,nq
     203           0 :                     qsum(iq) = qsum(iq) + dp1(i,m)*q4(1,i,m,iq)
     204             :                   enddo
     205             :                 else
     206           0 :                   dp = pe2(i,k+1)-pe1(i,m)
     207           0 :                   esl = dp / dp1(i,m)
     208           0 :                   fac1 = 0.5_r8*esl
     209           0 :                   fac2 = 1.0_r8-r23*esl
     210           0 :                   do iq=1,nq
     211           0 :                     qsum(iq) = qsum(iq) + dp*( q4(2,i,m,iq) + fac1*(         &
     212           0 :                          q4(3,i,m,iq)-q4(2,i,m,iq)+q4(4,i,m,iq)*fac2 ) )
     213             :                   enddo
     214             :                   k0 = m
     215             :                   goto 123
     216             :                 endif
     217             :               enddo
     218             :               goto 123
     219             :             endif
     220             :           endif
     221           0 : 100     continue
     222             : 123   continue
     223           0 :       do iq=1,nq
     224           0 :         q2(i,k,iq) = qsum(iq) / dp2(i,k)
     225             :       enddo
     226           0 : 555   continue
     227           0 : 1000  continue
     228             :           
     229           0 :       if (fill) call fillz(i2-i1+1, km, nq, q2, dp2)
     230             :       
     231           0 :       do iq=1,nq
     232             :         !    if (fill) call fillz(i2-i1+1, km, 1, q2(i1,1,iq), dp2)
     233           0 :         do k=1,km
     234           0 :           do i=i1,i2
     235           0 :             q1(i,j,k,iq) = q2(i,k,iq)
     236             :           enddo
     237             :         enddo
     238             :       enddo
     239             : 
     240           0 :     end subroutine mapn_tracer
     241             : 
     242             : 
     243   171428400 :     subroutine map1_ppm( km,   pe1,    q1,   qs,           &
     244   171428400 :          kn,   pe2,    q2,   i1, i2,       &
     245             :          j,    ibeg, iend, jbeg, jend, iv,  kord)
     246             :       integer, intent(in) :: i1                !< Starting longitude
     247             :       integer, intent(in) :: i2                !< Finishing longitude
     248             :       integer, intent(in) :: iv                !< Mode: 0 == constituents 1 == ??? 2 == remap temp with cs scheme
     249             :       integer, intent(in) :: kord              !< Method order
     250             :       integer, intent(in) :: j                 !< Current latitude
     251             :       integer, intent(in) :: ibeg, iend, jbeg, jend
     252             :       integer, intent(in) :: km                !< Original vertical dimension
     253             :       integer, intent(in) :: kn                !< Target vertical dimension
     254             :       real(kind=r8), intent(in) ::   qs(i1:i2)       !< bottom BC
     255             :       real(kind=r8), intent(in) ::  pe1(i1:i2,km+1)  !< pressure at layer edges from model top to bottom surface in the original vertical coordinate
     256             :       real(kind=r8), intent(in) ::  pe2(i1:i2,kn+1)  !< pressure at layer edges from model top to bottom surface in the new vertical coordinate
     257             :       real(kind=r8), intent(in) ::    q1(ibeg:iend,jbeg:jend,km) !< Field input
     258             :       ! INPUT/OUTPUT PARAMETERS:
     259             :       real(kind=r8), intent(inout)::  q2(ibeg:iend,jbeg:jend,kn) !< Field output
     260             :       
     261             :       ! DESCRIPTION:
     262             :       ! IV = 0: constituents
     263             :       ! pe1: pressure at layer edges (from model top to bottom surface)
     264             :       !      in the original vertical coordinate
     265             :       ! pe2: pressure at layer edges (from model top to bottom surface)
     266             :       !      in the new vertical coordinate
     267             :       
     268             :       ! LOCAL VARIABLES:
     269   342856800 :       real(kind=r8)    dp1(i1:i2,km)
     270   342856800 :       real(kind=r8)   q4(4,i1:i2,km)
     271             :       real(kind=r8)    pl, pr, qsum, dp, esl
     272             :       integer i, k, l, m, k0
     273             :       
     274  4628566800 :       do k=1,km
     275 21241537200 :         do i=i1,i2
     276 16612970400 :           dp1(i,k) = pe1(i,k+1) - pe1(i,k)
     277 21070108800 :           q4(1,i,k) = q1(i,j,k)
     278             :         enddo
     279             :       enddo
     280             :       
     281             :       ! Compute vertical subgrid distribution
     282   171428400 :       if ( kord >7 ) then
     283   171428400 :         call  cs_profile( qs, q4, dp1, km, i1, i2, iv, kord )
     284             :       else
     285           0 :         call ppm_profile( q4, dp1, km, i1, i2, iv, kord )
     286             :       endif
     287             :       
     288   810388800 :       do i=i1,i2
     289             :         k0 = 1
     290 17423359200 :         do 555 k=1,kn
     291 16612970400 :           do l=k0,km
     292             :             ! locate the top edge: pe2(i,k)
     293 16612970400 :             if( pe2(i,k) >= pe1(i,l) .and. pe2(i,k) <= pe1(i,l+1) ) then
     294 16612970400 :               pl = (pe2(i,k)-pe1(i,l)) / dp1(i,l)
     295 16612970400 :               if( pe2(i,k+1) <= pe1(i,l+1) ) then
     296             :                 ! entire new grid is within the original grid
     297  2383214901 :                 pr = (pe2(i,k+1)-pe1(i,l)) / dp1(i,l)
     298  4766429802 :                 q2(i,j,k) = q4(2,i,l) + 0.5_r8*(q4(4,i,l)+q4(3,i,l)-q4(2,i,l))  &
     299  2383214901 :                      *(pr+pl)-q4(4,i,l)*r3*(pr*(pr+pl)+pl**2)
     300  2383214901 :                 k0 = l
     301  2383214901 :                 goto 555
     302             :               else
     303             :                 ! Fractional area...
     304             :                 qsum = (pe1(i,l+1)-pe2(i,k))*(q4(2,i,l)+0.5_r8*(q4(4,i,l)+   &
     305             :                      q4(3,i,l)-q4(2,i,l))*(1.0_r8+pl)-q4(4,i,l)*           &
     306 14229755499 :                      (r3*(1.0_r8+pl*(1.0_r8+pl))))
     307 15974010000 :                 do m=l+1,km
     308             :                   ! locate the bottom edge: pe2(i,k+1)
     309 15974010000 :                   if( pe2(i,k+1) > pe1(i,m+1) ) then
     310             :                     ! Whole layer
     311  1744254501 :                     qsum = qsum + dp1(i,m)*q4(1,i,m)
     312             :                   else
     313 14229755499 :                     dp = pe2(i,k+1)-pe1(i,m)
     314 14229755499 :                     esl = dp / dp1(i,m)
     315             :                     qsum = qsum + dp*(q4(2,i,m)+0.5_r8*esl*               &
     316 14229755499 :                          (q4(3,i,m)-q4(2,i,m)+q4(4,i,m)*(1.0_r8-r23*esl)))
     317 14229755499 :                     k0 = m
     318 14229755499 :                     goto 123
     319             :                   endif
     320             :                 enddo
     321             :                 goto 123
     322             :               endif
     323             :             endif
     324             :           enddo
     325 14229755499 : 123       q2(i,j,k) = qsum / ( pe2(i,k+1) - pe2(i,k) )
     326   638960400 : 555       continue
     327             :         enddo
     328             : 
     329   171428400 :     end subroutine map1_ppm
     330             : 
     331           0 :     subroutine ppm_profile(a4, delp, km, i1, i2, iv, kord)
     332             :       
     333             :       ! INPUT PARAMETERS:
     334             :       integer, intent(in):: iv      !< iv =-1: winds iv = 0: positive definite scalars iv = 1: others iv = 2: temp (if remap_t) and w (iv=-2)
     335             :       integer, intent(in):: i1      !< Starting longitude
     336             :       integer, intent(in):: i2      !< Finishing longitude
     337             :       integer, intent(in):: km      !< Vertical dimension
     338             :       integer, intent(in):: kord    !< Order (or more accurately method no.):
     339             :       ! 
     340             :       real(kind=r8) , intent(in):: delp(i1:i2,km)     !< Layer pressure thickness
     341             :       
     342             :       ! !INPUT/OUTPUT PARAMETERS:
     343             :       real(kind=r8) , intent(inout):: a4(4,i1:i2,km)  !< Interpolated values
     344             :       
     345             :       ! DESCRIPTION:
     346             :       !
     347             :       !   Perform the piecewise parabolic reconstruction
     348             :       ! 
     349             :       ! !REVISION HISTORY: 
     350             :       ! S.-J. Lin   revised at GFDL 2007
     351             :       !-----------------------------------------------------------------------
     352             :       ! local arrays:
     353           0 :       real(kind=r8)    dc(i1:i2,km)
     354           0 :       real(kind=r8)    h2(i1:i2,km)
     355           0 :       real(kind=r8)  delq(i1:i2,km)
     356           0 :       real(kind=r8)   df2(i1:i2,km)
     357           0 :       real(kind=r8)    d4(i1:i2,km)
     358             :       
     359             :       ! local scalars:
     360             :       integer i, k, km1, lmt, it
     361             :       real(kind=r8)  fac
     362             :       real(kind=r8)  a1, a2, c1, c2, c3, d1, d2
     363             :       real(kind=r8)  qm, dq, lac, qmp, pmp
     364             :       
     365           0 :       km1 = km - 1
     366           0 :       it = i2 - i1 + 1
     367             :       
     368           0 :       do k=2,km
     369           0 :         do i=i1,i2
     370           0 :           delq(i,k-1) =   a4(1,i,k) - a4(1,i,k-1)
     371           0 :           d4(i,k  ) = delp(i,k-1) + delp(i,k)
     372             :         enddo
     373             :       enddo
     374             :       
     375           0 :       do k=2,km1
     376           0 :         do i=i1,i2
     377           0 :           c1  = (delp(i,k-1)+0.5_r8*delp(i,k))/d4(i,k+1)
     378           0 :           c2  = (delp(i,k+1)+0.5_r8*delp(i,k))/d4(i,k)
     379             :           df2(i,k) = delp(i,k)*(c1*delq(i,k) + c2*delq(i,k-1)) /      &
     380           0 :                (d4(i,k)+delp(i,k+1))
     381             :           dc(i,k) = sign( min(abs(df2(i,k)),              &
     382             :                max(a4(1,i,k-1),a4(1,i,k),a4(1,i,k+1))-a4(1,i,k),  &
     383           0 :                a4(1,i,k)-min(a4(1,i,k-1),a4(1,i,k),a4(1,i,k+1))), df2(i,k) )
     384             :         enddo
     385             :       enddo
     386             :       
     387             :       !-----------------------------------------------------------
     388             :       ! 4th order interpolation of the provisional cell edge value
     389             :       !-----------------------------------------------------------
     390             :       
     391           0 :       do k=3,km1
     392           0 :         do i=i1,i2
     393           0 :           c1 = delq(i,k-1)*delp(i,k-1) / d4(i,k)
     394           0 :           a1 = d4(i,k-1) / (d4(i,k) + delp(i,k-1))
     395           0 :           a2 = d4(i,k+1) / (d4(i,k) + delp(i,k))
     396             :           a4(2,i,k) = a4(1,i,k-1) + c1 + 2.0_r8/(d4(i,k-1)+d4(i,k+1)) *    &
     397             :                ( delp(i,k)*(c1*(a1 - a2)+a2*dc(i,k-1)) -          &
     398           0 :                delp(i,k-1)*a1*dc(i,k  ) )
     399             :         enddo
     400             :       enddo
     401             :       
     402             :       !     if(km>8 .and. kord>4) call steepz(i1, i2, km, a4, df2, dc, delq, delp, d4)
     403             :       
     404             :       ! Area preserving cubic with 2nd deriv. = 0 at the boundaries
     405             :       ! Top
     406           0 :       do i=i1,i2
     407           0 :         d1 = delp(i,1)
     408           0 :         d2 = delp(i,2)
     409           0 :         qm = (d2*a4(1,i,1)+d1*a4(1,i,2)) / (d1+d2)
     410           0 :         dq = 2.0_r8*(a4(1,i,2)-a4(1,i,1)) / (d1+d2)
     411           0 :         c1 = 4.0_r8*(a4(2,i,3)-qm-d2*dq) / ( d2*(2.0_r8*d2*d2+d1*(d2+3.0_r8*d1)) )
     412           0 :         c3 = dq - 0.5_r8*c1*(d2*(5.0_r8*d1+d2)-3.0_r8*d1*d1)
     413           0 :         a4(2,i,2) = qm - 0.25_r8*c1*d1*d2*(d2+3.0_r8*d1)
     414             :         ! Top edge:
     415             :         !-------------------------------------------------------
     416           0 :         a4(2,i,1) = d1*(2.0_r8*c1*d1**2-c3) + a4(2,i,2)
     417             :         !-------------------------------------------------------
     418             :         !        a4(2,i,1) = (12./7.)*a4(1,i,1)-(13./14.)*a4(1,i,2)+(3./14.)*a4(1,i,3)
     419             :         !-------------------------------------------------------
     420             :         ! No over- and undershoot condition
     421           0 :         a4(2,i,2) = max( a4(2,i,2), min(a4(1,i,1), a4(1,i,2)) )
     422           0 :         a4(2,i,2) = min( a4(2,i,2), max(a4(1,i,1), a4(1,i,2)) )
     423           0 :         dc(i,1) =  0.5_r8*(a4(2,i,2) - a4(1,i,1))
     424             :       enddo
     425             :       
     426             :       ! Enforce monotonicity  within the top layer
     427             :       
     428           0 :       if( iv==0 ) then
     429           0 :         do i=i1,i2
     430           0 :           a4(2,i,1) = max(0.0_r8, a4(2,i,1))
     431           0 :           a4(2,i,2) = max(0.0_r8, a4(2,i,2))
     432             :         enddo
     433           0 :       elseif( iv==-1 ) then
     434           0 :         do i=i1,i2
     435           0 :           if ( a4(2,i,1)*a4(1,i,1) <= 0.0_r8 ) a4(2,i,1) = 0.0_r8
     436             :         enddo
     437           0 :       elseif( abs(iv)==2 ) then
     438           0 :         do i=i1,i2
     439           0 :           a4(2,i,1) = a4(1,i,1)
     440           0 :           a4(3,i,1) = a4(1,i,1)
     441             :         enddo
     442             :       endif
     443             :       
     444             :       ! Bottom
     445             :       ! Area preserving cubic with 2nd deriv. = 0 at the surface
     446           0 :       do i=i1,i2
     447           0 :         d1 = delp(i,km)
     448           0 :         d2 = delp(i,km1)
     449           0 :         qm = (d2*a4(1,i,km)+d1*a4(1,i,km1)) / (d1+d2)
     450           0 :         dq = 2.0_r8*(a4(1,i,km1)-a4(1,i,km)) / (d1+d2)
     451           0 :         c1 = (a4(2,i,km1)-qm-d2*dq) / (d2*(2.0_r8*d2*d2+d1*(d2+3.0_r8*d1)))
     452           0 :         c3 = dq - 2.0_r8*c1*(d2*(5._r8*d1+d2)-3.0_r8*d1*d1)
     453           0 :         a4(2,i,km) = qm - c1*d1*d2*(d2+3.0_r8*d1)
     454             :         ! Bottom edge:
     455             :         !-----------------------------------------------------
     456           0 :         a4(3,i,km) = d1*(8.0_r8*c1*d1**2-c3) + a4(2,i,km)
     457             :         !        dc(i,km) = 0.5*(a4(3,i,km) - a4(1,i,km))
     458             :         !-----------------------------------------------------
     459             :         !        a4(3,i,km) = (12./7.)*a4(1,i,km)-(13./14.)*a4(1,i,km-1)+(3./14.)*a4(1,i,km-2)
     460             :         ! No over- and under-shoot condition
     461           0 :         a4(2,i,km) = max( a4(2,i,km), min(a4(1,i,km), a4(1,i,km1)) )
     462           0 :         a4(2,i,km) = min( a4(2,i,km), max(a4(1,i,km), a4(1,i,km1)) )
     463           0 :         dc(i,km) = 0.5_r8*(a4(1,i,km) - a4(2,i,km))
     464             :       enddo
     465             :       
     466             :       
     467             :       ! Enforce constraint on the "slope" at the surface
     468             :       
     469             : #ifdef BOT_MONO
     470             :       do i=i1,i2
     471             :         a4(4,i,km) = 0
     472             :         if( a4(3,i,km) * a4(1,i,km) <= 0.0_r8 ) a4(3,i,km) = 0.0_r8
     473             :         d1 = a4(1,i,km) - a4(2,i,km)
     474             :         d2 = a4(3,i,km) - a4(1,i,km)
     475             :         if ( d1*d2 < 0.0_r8 ) then
     476             :           a4(2,i,km) = a4(1,i,km)
     477             :           a4(3,i,km) = a4(1,i,km)
     478             :         else
     479             :           dq = sign(min(abs(d1),abs(d2),0.5_r8*abs(delq(i,km-1))), d1)
     480             :           a4(2,i,km) = a4(1,i,km) - dq
     481             :           a4(3,i,km) = a4(1,i,km) + dq
     482             :         endif
     483             :       enddo
     484             : #else
     485           0 :       if( iv==0 ) then
     486           0 :         do i=i1,i2
     487           0 :           a4(2,i,km) = max(0.0_r8,a4(2,i,km))
     488           0 :           a4(3,i,km) = max(0.0_r8,a4(3,i,km))
     489             :         enddo
     490           0 :       elseif( iv<0 ) then
     491           0 :         do i=i1,i2
     492           0 :           if( a4(1,i,km)*a4(3,i,km) <= 0.0_r8 )  a4(3,i,km) = 0.0_r8
     493             :         enddo
     494             :       endif
     495             : #endif
     496             :       
     497           0 :       do k=1,km1
     498           0 :         do i=i1,i2
     499           0 :           a4(3,i,k) = a4(2,i,k+1)
     500             :         enddo
     501             :       enddo
     502             :       
     503             :       !-----------------------------------------------------------
     504             :       ! f(s) = AL + s*[(AR-AL) + A6*(1-s)]         ( 0 <= s  <= 1 )
     505             :       !-----------------------------------------------------------
     506             :       ! Top 2 and bottom 2 layers always use monotonic mapping
     507           0 :       do k=1,2
     508           0 :         do i=i1,i2
     509           0 :           a4(4,i,k) = 3.0_r8*(2.0_r8*a4(1,i,k) - (a4(2,i,k)+a4(3,i,k)))
     510             :         enddo
     511           0 :         call ppm_limiters(dc(i1,k), a4(1,i1,k), it, 0)
     512             :       enddo
     513             :       
     514           0 :       if(kord >= 7) then
     515             :         !-----------------------
     516             :         ! Huynh's 2nd constraint
     517             :         !-----------------------
     518           0 :         do k=2,km1
     519           0 :           do i=i1,i2
     520             :             ! Method#1
     521             :             !           h2(i,k) = delq(i,k) - delq(i,k-1)
     522             :             ! Method#2 - better
     523           0 :             h2(i,k) = 2.0_r8*(dc(i,k+1)/delp(i,k+1) - dc(i,k-1)/delp(i,k-1))  &
     524             :                  / ( delp(i,k)+0.5_r8*(delp(i,k-1)+delp(i,k+1)) )        &
     525           0 :                  * delp(i,k)**2 
     526             :             ! Method#3
     527             : !!!            h2(i,k) = dc(i,k+1) - dc(i,k-1)
     528             :           enddo
     529             :         enddo
     530             :         
     531           0 :         fac = 1.5_r8           ! original quasi-monotone
     532             :         
     533           0 :         do k=3,km-2
     534           0 :           do i=i1,i2
     535             :             ! Right edges
     536             :             !        qmp   = a4(1,i,k) + 2.0*delq(i,k-1)
     537             :             !        lac   = a4(1,i,k) + fac*h2(i,k-1) + 0.5*delq(i,k-1)
     538             :             !
     539           0 :             pmp   = 2.0_r8*dc(i,k)
     540           0 :             qmp   = a4(1,i,k) + pmp
     541           0 :             lac   = a4(1,i,k) + fac*h2(i,k-1) + dc(i,k)
     542             :             a4(3,i,k) = min(max(a4(3,i,k), min(a4(1,i,k), qmp, lac)),    &
     543           0 :                  max(a4(1,i,k), qmp, lac) )
     544             :             ! Left  edges
     545             :             !        qmp   = a4(1,i,k) - 2.0*delq(i,k)
     546             :             !        lac   = a4(1,i,k) + fac*h2(i,k+1) - 0.5*delq(i,k)
     547             :             !
     548           0 :             qmp   = a4(1,i,k) - pmp
     549           0 :             lac   = a4(1,i,k) + fac*h2(i,k+1) - dc(i,k)
     550             :             a4(2,i,k) = min(max(a4(2,i,k),  min(a4(1,i,k), qmp, lac)),   &
     551           0 :                  max(a4(1,i,k), qmp, lac))
     552             :             !-------------
     553             :             ! Recompute A6
     554             :             !-------------
     555           0 :             a4(4,i,k) = 3.0_r8*(2.0_r8*a4(1,i,k) - (a4(2,i,k)+a4(3,i,k)))
     556             :           enddo
     557             :           ! Additional constraint to ensure positivity when kord=7
     558           0 :           if (iv == 0 .and. kord >= 6 )                      &
     559           0 :                call ppm_limiters(dc(i1,k), a4(1,i1,k), it, 2)
     560             :         enddo
     561             :         
     562             :       else
     563             :         
     564           0 :         lmt = kord - 3
     565           0 :         lmt = max(0, lmt)
     566           0 :         if (iv == 0) lmt = min(2, lmt)
     567             :         
     568           0 :         do k=3,km-2
     569           0 :           if( kord /= 4) then
     570           0 :             do i=i1,i2
     571           0 :               a4(4,i,k) = 3.0_r8*(2.0_r8*a4(1,i,k) - (a4(2,i,k)+a4(3,i,k)))
     572             :             enddo
     573             :           endif
     574           0 :           if(kord/=6) call ppm_limiters(dc(i1,k), a4(1,i1,k), it, lmt)
     575             :         enddo
     576             :       endif
     577             :       
     578           0 :       do k=km1,km
     579           0 :         do i=i1,i2
     580           0 :           a4(4,i,k) = 3.0_r8*(2.0_r8*a4(1,i,k) - (a4(2,i,k)+a4(3,i,k)))
     581             :         enddo
     582           0 :         call ppm_limiters(dc(i1,k), a4(1,i1,k), it, 0)
     583             :       enddo
     584             : 
     585           0 :     end subroutine ppm_profile
     586             : 
     587           0 :     subroutine ppm_limiters(dm, a4, itot, lmt)
     588             :       
     589             :       ! INPUT PARAMETERS:
     590             :       real(kind=r8) , intent(in):: dm(*)     !< Linear slope
     591             :       integer, intent(in) :: itot      !< Total Longitudes
     592             :       integer, intent(in) :: lmt       !< 0: Standard PPM constraint 1: Improved full monotonicity constraint
     593             :       !< (Lin) 2: Positive definite constraint 
     594             :       !< 3: do nothing (return immediately)
     595             :       ! INPUT/OUTPUT PARAMETERS:
     596             :       real(kind=r8) , intent(inout) :: a4(4,*)   !< PPM array AA <-- a4(1,i) AL <-- a4(2,i) AR <-- a4(3,i) A6 <-- a4(4,i)
     597             :       ! LOCAL VARIABLES:
     598             :       real(kind=r8)  qmp
     599             :       real(kind=r8)  da1, da2, a6da
     600             :       real(kind=r8)  fmin
     601             :       integer i
     602             :       
     603             :       ! Developer: S.-J. Lin
     604             :       
     605           0 :       if ( lmt == 3 ) return
     606             :       
     607           0 :       if(lmt == 0) then
     608             :         ! Standard PPM constraint
     609           0 :         do i=1,itot
     610           0 :           if(dm(i) == 0.0_r8) then
     611           0 :             a4(2,i) = a4(1,i)
     612           0 :             a4(3,i) = a4(1,i)
     613           0 :             a4(4,i) = 0.0_r8
     614             :           else
     615           0 :             da1  = a4(3,i) - a4(2,i)
     616           0 :             da2  = da1**2
     617           0 :             a6da = a4(4,i)*da1
     618           0 :             if(a6da < -da2) then
     619           0 :               a4(4,i) = 3.0_r8*(a4(2,i)-a4(1,i))
     620           0 :               a4(3,i) = a4(2,i) - a4(4,i)
     621           0 :             elseif(a6da > da2) then
     622           0 :               a4(4,i) = 3.0_r8*(a4(3,i)-a4(1,i))
     623           0 :               a4(2,i) = a4(3,i) - a4(4,i)
     624             :             endif
     625             :           endif
     626             :         enddo
     627             :         
     628           0 :       elseif (lmt == 1) then
     629             :         
     630             :         ! Improved full monotonicity constraint (Lin 2004)
     631             :         ! Note: no need to provide first guess of A6 <-- a4(4,i)
     632           0 :         do i=1, itot
     633           0 :           qmp = 2.0_r8*dm(i)
     634           0 :           a4(2,i) = a4(1,i)-sign(min(abs(qmp),abs(a4(2,i)-a4(1,i))), qmp)
     635           0 :           a4(3,i) = a4(1,i)+sign(min(abs(qmp),abs(a4(3,i)-a4(1,i))), qmp)
     636           0 :           a4(4,i) = 3.0_r8*( 2.0_r8*a4(1,i) - (a4(2,i)+a4(3,i)) )
     637             :         enddo
     638             :         
     639           0 :       elseif (lmt == 2) then
     640             :         
     641             :         ! Positive definite constraint
     642           0 :         do i=1,itot
     643           0 :           if( abs(a4(3,i)-a4(2,i)) < -a4(4,i) ) then
     644           0 :             fmin = a4(1,i)+0.25_r8*(a4(3,i)-a4(2,i))**2/a4(4,i)+a4(4,i)*r12
     645           0 :             if( fmin < 0.0_r8 ) then
     646           0 :               if(a4(1,i)<a4(3,i) .and. a4(1,i)<a4(2,i)) then
     647           0 :                 a4(3,i) = a4(1,i)
     648           0 :                 a4(2,i) = a4(1,i)
     649           0 :                 a4(4,i) = 0.0_r8
     650           0 :               elseif(a4(3,i) > a4(2,i)) then
     651           0 :                 a4(4,i) = 3.0_r8*(a4(2,i)-a4(1,i))
     652           0 :                 a4(3,i) = a4(2,i) - a4(4,i)
     653             :               else
     654           0 :                 a4(4,i) = 3.0_r8*(a4(3,i)-a4(1,i))
     655           0 :                 a4(2,i) = a4(3,i) - a4(4,i)
     656             :               endif
     657             :             endif
     658             :           endif
     659             :         enddo
     660             :         
     661             :       endif
     662             :       
     663             :     end subroutine ppm_limiters
     664             :  
     665             :  
     666           0 :     subroutine scalar_profile(qs, a4, delp, km, i1, i2, iv, kord, qmin)
     667             :       ! Optimized vertical profile reconstruction:
     668             :       ! Latest: Apr 2008 S.-J. Lin, NOAA/GFDL
     669             :       integer, intent(in):: i1, i2
     670             :       integer, intent(in):: km      !< vertical dimension
     671             :       integer, intent(in):: iv      !< iv =-1: winds iv = 0: positive definite scalars iv = 1: others
     672             :       integer, intent(in):: kord
     673             :       real(kind=r8), intent(in)   ::   qs(i1:i2)
     674             :       real(kind=r8), intent(in)   :: delp(i1:i2,km)     !< Layer pressure thickness
     675             :       real(kind=r8), intent(inout):: a4(4,i1:i2,km)     !< Interpolated values
     676             :       real(kind=r8), intent(in):: qmin
     677             :       !-----------------------------------------------------------------------
     678           0 :       logical, dimension(i1:i2,km):: extm, ext5, ext6
     679           0 :       real(kind=r8)  gam(i1:i2,km)
     680           0 :       real(kind=r8)    q(i1:i2,km+1)
     681           0 :       real(kind=r8)   d4(i1:i2)
     682             :       real(kind=r8)   bet, a_bot, grat 
     683             :       real(kind=r8)   pmp_1, lac_1, pmp_2, lac_2, x0, x1
     684             :       integer i, k, im
     685             :       
     686           0 :       if ( iv .eq. -2 ) then
     687           0 :         do i=i1,i2
     688           0 :           gam(i,2) = 0.5_r8
     689           0 :           q(i,1) = 1.5_r8*a4(1,i,1)
     690             :         enddo
     691           0 :         do k=2,km-1
     692           0 :           do i=i1, i2
     693           0 :             grat = delp(i,k-1) / delp(i,k)
     694           0 :             bet =  2.0_r8 + grat + grat - gam(i,k)
     695           0 :             q(i,k) = (3.0_r8*(a4(1,i,k-1)+a4(1,i,k)) - q(i,k-1))/bet
     696           0 :             gam(i,k+1) = grat / bet
     697             :           enddo
     698             :         enddo
     699           0 :         do i=i1,i2
     700           0 :           grat = delp(i,km-1) / delp(i,km) 
     701           0 :           q(i,km) = (3.0_r8*(a4(1,i,km-1)+a4(1,i,km)) - grat*qs(i) - q(i,km-1)) /  &
     702           0 :                (2.0_r8 + grat + grat - gam(i,km))
     703           0 :           q(i,km+1) = qs(i)
     704             :         enddo
     705           0 :         do k=km-1,1,-1
     706           0 :           do i=i1,i2
     707           0 :             q(i,k) = q(i,k) - gam(i,k+1)*q(i,k+1)
     708             :           enddo
     709             :         enddo
     710             :       else
     711           0 :         do i=i1,i2
     712           0 :           grat = delp(i,2) / delp(i,1)   ! grid ratio
     713           0 :           bet = grat*(grat+0.5_r8)
     714           0 :           q(i,1) = ( (grat+grat)*(grat+1.0_r8)*a4(1,i,1) + a4(1,i,2) ) / bet
     715           0 :           gam(i,1) = ( 1.0_r8 + grat*(grat+1.5_r8) ) / bet
     716             :         enddo
     717             :         
     718           0 :         do k=2,km
     719           0 :           do i=i1,i2
     720           0 :             d4(i) = delp(i,k-1) / delp(i,k)
     721           0 :             bet =  2.0_r8 + d4(i) + d4(i) - gam(i,k-1)
     722           0 :             q(i,k) = ( 3.0_r8*(a4(1,i,k-1)+d4(i)*a4(1,i,k)) - q(i,k-1) )/bet
     723           0 :             gam(i,k) = d4(i) / bet
     724             :           enddo
     725             :         enddo
     726             :         
     727           0 :         do i=i1,i2
     728           0 :           a_bot = 1.0_r8 + d4(i)*(d4(i)+1.5_r8)
     729           0 :           q(i,km+1) = (2.0_r8*d4(i)*(d4(i)+1.0_r8)*a4(1,i,km)+a4(1,i,km-1)-a_bot*q(i,km))  &
     730           0 :                / ( d4(i)*(d4(i)+0.5_r8) - a_bot*gam(i,km) )
     731             :         enddo
     732             :         
     733           0 :         do k=km,1,-1
     734           0 :           do i=i1,i2
     735           0 :             q(i,k) = q(i,k) - gam(i,k)*q(i,k+1)
     736             :           enddo
     737             :         enddo
     738             :       endif
     739             :       
     740             :       !----- Perfectly linear scheme --------------------------------
     741           0 :       if ( abs(kord) > 16 ) then
     742           0 :         do k=1,km
     743           0 :           do i=i1,i2
     744           0 :             a4(2,i,k) = q(i,k  )
     745           0 :             a4(3,i,k) = q(i,k+1)
     746           0 :             a4(4,i,k) = 3.0_r8*(2.0_r8*a4(1,i,k) - (a4(2,i,k)+a4(3,i,k)))
     747             :           enddo
     748             :         enddo
     749             :         return
     750             :       endif
     751             :       !----- Perfectly linear scheme --------------------------------
     752             :       !------------------
     753             :       ! Apply constraints
     754             :       !------------------
     755           0 :       im = i2 - i1 + 1
     756             :       
     757             :       ! Apply *large-scale* constraints 
     758           0 :       do i=i1,i2
     759           0 :         q(i,2) = min( q(i,2), max(a4(1,i,1), a4(1,i,2)) )
     760           0 :         q(i,2) = max( q(i,2), min(a4(1,i,1), a4(1,i,2)) )
     761             :       enddo
     762             :       
     763           0 :       do k=2,km
     764           0 :         do i=i1,i2
     765           0 :           gam(i,k) = a4(1,i,k) - a4(1,i,k-1)
     766             :         enddo
     767             :       enddo
     768             :       
     769             :       ! Interior:
     770           0 :       do k=3,km-1
     771           0 :         do i=i1,i2
     772           0 :           if ( gam(i,k-1)*gam(i,k+1)>0.0_r8 ) then
     773             :             ! Apply large-scale constraint to ALL fields if not local max/min
     774           0 :             q(i,k) = min( q(i,k), max(a4(1,i,k-1),a4(1,i,k)) )
     775           0 :             q(i,k) = max( q(i,k), min(a4(1,i,k-1),a4(1,i,k)) )
     776             :           else
     777           0 :             if ( gam(i,k-1) > 0.0_r8 ) then
     778             :               ! There exists a local max
     779           0 :               q(i,k) = max(q(i,k), min(a4(1,i,k-1),a4(1,i,k)))
     780             :             else
     781             :               ! There exists a local min
     782           0 :               q(i,k) = min(q(i,k), max(a4(1,i,k-1),a4(1,i,k)))
     783           0 :               if ( iv==0 ) q(i,k) = max(0.0_r8, q(i,k))
     784             :             endif
     785             :           endif
     786             :         enddo
     787             :       enddo
     788             :       
     789             :       ! Bottom:
     790           0 :       do i=i1,i2
     791           0 :         q(i,km) = min( q(i,km), max(a4(1,i,km-1), a4(1,i,km)) )
     792           0 :         q(i,km) = max( q(i,km), min(a4(1,i,km-1), a4(1,i,km)) )
     793             :       enddo
     794             :       
     795           0 :       do k=1,km
     796           0 :         do i=i1,i2
     797           0 :           a4(2,i,k) = q(i,k  )
     798           0 :           a4(3,i,k) = q(i,k+1)
     799             :         enddo
     800             :       enddo
     801             :       
     802           0 :       do k=1,km
     803           0 :         if ( k==1 .or. k==km ) then
     804           0 :           do i=i1,i2
     805           0 :             extm(i,k) = (a4(2,i,k)-a4(1,i,k)) * (a4(3,i,k)-a4(1,i,k)) > 0.0_r8
     806             :           enddo
     807             :         else
     808           0 :           do i=i1,i2
     809           0 :             extm(i,k) = gam(i,k)*gam(i,k+1) < 0.0_r8
     810             :           enddo
     811             :         endif
     812           0 :         if ( abs(kord) > 9 ) then
     813           0 :           do i=i1,i2
     814           0 :             x0 = 2.0_r8*a4(1,i,k) - (a4(2,i,k)+a4(3,i,k))
     815           0 :             x1 = abs(a4(2,i,k)-a4(3,i,k))
     816           0 :             a4(4,i,k) = 3.0_r8*x0
     817           0 :             ext5(i,k) = abs(x0) > x1
     818           0 :             ext6(i,k) = abs(a4(4,i,k)) > x1
     819             :           enddo
     820             :         endif
     821             :       enddo
     822             :       
     823             :       !---------------------------
     824             :       ! Apply subgrid constraints:
     825             :       !---------------------------
     826             :       ! f(s) = AL + s*[(AR-AL) + A6*(1-s)]         ( 0 <= s  <= 1 )
     827             :       ! Top 2 and bottom 2 layers always use monotonic mapping
     828             :       
     829           0 :       if ( iv==0 ) then
     830           0 :         do i=i1,i2
     831           0 :           a4(2,i,1) = max(0.0_r8, a4(2,i,1))
     832             :         enddo
     833           0 :       elseif ( iv==-1 ) then 
     834           0 :         do i=i1,i2
     835           0 :           if ( a4(2,i,1)*a4(1,i,1) <= 0.0_r8 ) a4(2,i,1) = 0.0_r8
     836             :         enddo
     837           0 :       elseif ( iv==2 ) then
     838           0 :         do i=i1,i2
     839           0 :           a4(2,i,1) = a4(1,i,1)
     840           0 :           a4(3,i,1) = a4(1,i,1)
     841           0 :           a4(4,i,1) = 0.0_r8
     842             :         enddo
     843             :       endif
     844             :       
     845           0 :       if ( iv/=2 ) then
     846           0 :         do i=i1,i2
     847           0 :           a4(4,i,1) = 3.0_r8*(2.0_r8*a4(1,i,1) - (a4(2,i,1)+a4(3,i,1)))
     848             :         enddo
     849           0 :         call cs_limiters(im, extm(i1,1), a4(1,i1,1), 1)
     850             :       endif
     851             :       
     852             :       ! k=2
     853           0 :       do i=i1,i2
     854           0 :         a4(4,i,2) = 3.0_r8*(2.0_r8*a4(1,i,2) - (a4(2,i,2)+a4(3,i,2)))
     855             :       enddo
     856           0 :       call cs_limiters(im, extm(i1,2), a4(1,i1,2), 2)
     857             :       
     858             :       !-------------------------------------
     859             :       ! Huynh's 2nd constraint for interior:
     860             :       !-------------------------------------
     861           0 :       do k=3,km-2
     862           0 :         if ( abs(kord)<9 ) then
     863           0 :           do i=i1,i2
     864             :             ! Left  edges
     865           0 :             pmp_1 = a4(1,i,k) - 2.0_r8*gam(i,k+1)
     866           0 :             lac_1 = pmp_1 + 1.5_r8*gam(i,k+2)
     867             :             a4(2,i,k) = min(max(a4(2,i,k), min(a4(1,i,k), pmp_1, lac_1)),   &
     868           0 :                  max(a4(1,i,k), pmp_1, lac_1) )
     869             :             ! Right edges
     870           0 :             pmp_2 = a4(1,i,k) + 2.0_r8*gam(i,k)
     871           0 :             lac_2 = pmp_2 - 1.5_r8*gam(i,k-1)
     872             :             a4(3,i,k) = min(max(a4(3,i,k), min(a4(1,i,k), pmp_2, lac_2)),    &
     873           0 :                  max(a4(1,i,k), pmp_2, lac_2) )
     874             :             
     875           0 :             a4(4,i,k) = 3.0_r8*(2.0_r8*a4(1,i,k) - (a4(2,i,k)+a4(3,i,k)))
     876             :           enddo
     877             :           
     878             :         elseif ( abs(kord)==9 ) then
     879           0 :           do i=i1,i2
     880           0 :             if ( extm(i,k) .and. extm(i,k-1) ) then
     881             :               ! grid-scale 2-delta-z wave detected
     882           0 :               a4(2,i,k) = a4(1,i,k)
     883           0 :               a4(3,i,k) = a4(1,i,k)
     884           0 :               a4(4,i,k) = 0.0_r8
     885           0 :             else if ( extm(i,k) .and. extm(i,k+1) ) then
     886             :               ! grid-scale 2-delta-z wave detected
     887           0 :               a4(2,i,k) = a4(1,i,k)
     888           0 :               a4(3,i,k) = a4(1,i,k)
     889           0 :               a4(4,i,k) = 0.0_r8
     890           0 :             else if ( extm(i,k) .and. a4(1,i,k)<qmin ) then
     891             :               ! grid-scale 2-delta-z wave detected
     892           0 :               a4(2,i,k) = a4(1,i,k)
     893           0 :               a4(3,i,k) = a4(1,i,k)
     894           0 :               a4(4,i,k) = 0.0_r8
     895             :             else
     896           0 :               a4(4,i,k) = 3.0_r8*(2.0_r8*a4(1,i,k) - (a4(2,i,k)+a4(3,i,k)))
     897             :               ! Check within the smooth region if subgrid profile is non-monotonic
     898           0 :               if( abs(a4(4,i,k)) > abs(a4(2,i,k)-a4(3,i,k)) ) then
     899           0 :                 pmp_1 = a4(1,i,k) - 2.0_r8*gam(i,k+1)
     900           0 :                 lac_1 = pmp_1 + 1.5_r8*gam(i,k+2)
     901             :                 a4(2,i,k) = min(max(a4(2,i,k), min(a4(1,i,k), pmp_1, lac_1)),  &
     902           0 :                      max(a4(1,i,k), pmp_1, lac_1) )
     903           0 :                 pmp_2 = a4(1,i,k) + 2.0_r8*gam(i,k)
     904           0 :                 lac_2 = pmp_2 - 1.5_r8*gam(i,k-1)
     905             :                 a4(3,i,k) = min(max(a4(3,i,k), min(a4(1,i,k), pmp_2, lac_2)),  &
     906           0 :                      max(a4(1,i,k), pmp_2, lac_2) )
     907           0 :                 a4(4,i,k) = 3.0_r8*(2.0_r8*a4(1,i,k) - (a4(2,i,k)+a4(3,i,k)))
     908             :               endif
     909             :             endif
     910             :           enddo
     911             :         elseif ( abs(kord)==10 ) then
     912           0 :           do i=i1,i2
     913           0 :             if( ext5(i,k) ) then
     914           0 :               if( ext5(i,k-1) .or. ext5(i,k+1) ) then
     915           0 :                 a4(2,i,k) = a4(1,i,k)
     916           0 :                 a4(3,i,k) = a4(1,i,k)
     917           0 :               elseif ( ext6(i,k-1) .or. ext6(i,k+1) ) then
     918           0 :                 pmp_1 = a4(1,i,k) - 2.0_r8*gam(i,k+1)
     919           0 :                 lac_1 = pmp_1 + 1.5_r8*gam(i,k+2)
     920             :                 a4(2,i,k) = min(max(a4(2,i,k), min(a4(1,i,k), pmp_1, lac_1)),  &
     921           0 :                      max(a4(1,i,k), pmp_1, lac_1) )
     922           0 :                 pmp_2 = a4(1,i,k) + 2.0_r8*gam(i,k)
     923           0 :                 lac_2 = pmp_2 - 1.5_r8*gam(i,k-1)
     924             :                 a4(3,i,k) = min(max(a4(3,i,k), min(a4(1,i,k), pmp_2, lac_2)),  &
     925           0 :                      max(a4(1,i,k), pmp_2, lac_2) )
     926             :               endif
     927           0 :             elseif( ext6(i,k) ) then
     928           0 :               if( ext5(i,k-1) .or. ext5(i,k+1) ) then
     929           0 :                 pmp_1 = a4(1,i,k) - 2.0_r8*gam(i,k+1)
     930           0 :                 lac_1 = pmp_1 + 1.5_r8*gam(i,k+2)
     931             :                 a4(2,i,k) = min(max(a4(2,i,k), min(a4(1,i,k), pmp_1, lac_1)),  &
     932           0 :                      max(a4(1,i,k), pmp_1, lac_1) )
     933           0 :                 pmp_2 = a4(1,i,k) + 2.0_r8*gam(i,k)
     934           0 :                 lac_2 = pmp_2 - 1.5_r8*gam(i,k-1)
     935             :                 a4(3,i,k) = min(max(a4(3,i,k), min(a4(1,i,k), pmp_2, lac_2)),  &
     936           0 :                      max(a4(1,i,k), pmp_2, lac_2) )
     937             :               endif
     938             :             endif
     939             :           enddo
     940           0 :           do i=i1,i2
     941           0 :             a4(4,i,k) = 3.0_r8*(2.0_r8*a4(1,i,k) - (a4(2,i,k)+a4(3,i,k)))
     942             :           enddo
     943             :         elseif ( abs(kord)==12 ) then
     944           0 :           do i=i1,i2
     945           0 :             if( extm(i,k) ) then
     946           0 :               a4(2,i,k) = a4(1,i,k)
     947           0 :               a4(3,i,k) = a4(1,i,k)
     948           0 :               a4(4,i,k) = 0.0_r8
     949             :             else        ! not a local extremum
     950           0 :               a4(4,i,k) = 6.0_r8*a4(1,i,k) - 3.0_r8*(a4(2,i,k)+a4(3,i,k))
     951             :               ! Check within the smooth region if subgrid profile is non-monotonic
     952           0 :               if( abs(a4(4,i,k)) > abs(a4(2,i,k)-a4(3,i,k)) ) then
     953           0 :                 pmp_1 = a4(1,i,k) - 2.0_r8*gam(i,k+1)
     954           0 :                 lac_1 = pmp_1 + 1.5_r8*gam(i,k+2)
     955             :                 a4(2,i,k) = min(max(a4(2,i,k), min(a4(1,i,k), pmp_1, lac_1)),  &
     956           0 :                      max(a4(1,i,k), pmp_1, lac_1) )
     957           0 :                 pmp_2 = a4(1,i,k) + 2.0_r8*gam(i,k)
     958           0 :                 lac_2 = pmp_2 - 1.5_r8*gam(i,k-1)
     959             :                 a4(3,i,k) = min(max(a4(3,i,k), min(a4(1,i,k), pmp_2, lac_2)),  &
     960           0 :                      max(a4(1,i,k), pmp_2, lac_2) )
     961           0 :                 a4(4,i,k) = 6.0_r8*a4(1,i,k) - 3.0_r8*(a4(2,i,k)+a4(3,i,k))
     962             :               endif
     963             :             endif
     964             :           enddo
     965             :         elseif ( abs(kord)==13 ) then
     966           0 :           do i=i1,i2
     967           0 :             if( ext6(i,k) ) then
     968           0 :               if ( ext6(i,k-1) .and. ext6(i,k+1) ) then
     969             :                 ! grid-scale 2-delta-z wave detected
     970           0 :                 a4(2,i,k) = a4(1,i,k)
     971           0 :                 a4(3,i,k) = a4(1,i,k)
     972             :               endif
     973             :             endif
     974             :           enddo
     975           0 :           do i=i1,i2
     976           0 :             a4(4,i,k) = 3.0_r8*(2.0_r8*a4(1,i,k) - (a4(2,i,k)+a4(3,i,k)))
     977             :           enddo
     978             :         elseif ( abs(kord)==14 ) then
     979             :           
     980           0 :           do i=i1,i2
     981           0 :             a4(4,i,k) = 3.0_r8*(2.0_r8*a4(1,i,k) - (a4(2,i,k)+a4(3,i,k)))
     982             :           enddo
     983             :           
     984             :         elseif ( abs(kord)==15 ) then   ! Revised abs(kord)=9 scheme
     985           0 :           do i=i1,i2
     986           0 :             if ( ext5(i,k) .and. ext5(i,k-1) ) then
     987           0 :               a4(2,i,k) = a4(1,i,k)
     988           0 :               a4(3,i,k) = a4(1,i,k)
     989           0 :             else if ( ext5(i,k) .and. ext5(i,k+1) ) then
     990           0 :               a4(2,i,k) = a4(1,i,k)
     991           0 :               a4(3,i,k) = a4(1,i,k)
     992           0 :             else if ( ext5(i,k) .and. a4(1,i,k)<qmin ) then
     993           0 :               a4(2,i,k) = a4(1,i,k)
     994           0 :               a4(3,i,k) = a4(1,i,k)
     995           0 :             elseif( ext6(i,k) ) then
     996           0 :               pmp_1 = a4(1,i,k) - 2.0_r8*gam(i,k+1)
     997           0 :               lac_1 = pmp_1 + 1.5_r8*gam(i,k+2)
     998             :               a4(2,i,k) = min(max(a4(2,i,k), min(a4(1,i,k), pmp_1, lac_1)),  &
     999           0 :                    max(a4(1,i,k), pmp_1, lac_1) )
    1000           0 :               pmp_2 = a4(1,i,k) + 2.0_r8*gam(i,k)
    1001           0 :               lac_2 = pmp_2 - 1.5_r8*gam(i,k-1)
    1002             :               a4(3,i,k) = min(max(a4(3,i,k), min(a4(1,i,k), pmp_2, lac_2)),  &
    1003           0 :                    max(a4(1,i,k), pmp_2, lac_2) )
    1004             :             endif
    1005             :           enddo
    1006           0 :           do i=i1,i2
    1007           0 :             a4(4,i,k) = 3.0_r8*(2.0_r8*a4(1,i,k) - (a4(2,i,k)+a4(3,i,k)))
    1008             :           enddo
    1009             :         elseif ( abs(kord)==16 ) then
    1010           0 :           do i=i1,i2
    1011           0 :             if( ext5(i,k) ) then
    1012           0 :               if ( ext5(i,k-1) .or. ext5(i,k+1) ) then
    1013           0 :                 a4(2,i,k) = a4(1,i,k)
    1014           0 :                 a4(3,i,k) = a4(1,i,k)
    1015           0 :               elseif ( ext6(i,k-1) .or. ext6(i,k+1) ) then
    1016             :                 ! Left  edges
    1017           0 :                 pmp_1 = a4(1,i,k) - 2.0_r8*gam(i,k+1)
    1018           0 :                 lac_1 = pmp_1 + 1.5_r8*gam(i,k+2)
    1019             :                 a4(2,i,k) = min(max(a4(2,i,k), min(a4(1,i,k), pmp_1, lac_1)),   &
    1020           0 :                      max(a4(1,i,k), pmp_1, lac_1) )
    1021             :                 ! Right edges
    1022           0 :                 pmp_2 = a4(1,i,k) + 2.0_r8*gam(i,k)
    1023           0 :                 lac_2 = pmp_2 - 1.5_r8*gam(i,k-1)
    1024             :                 a4(3,i,k) = min(max(a4(3,i,k), min(a4(1,i,k), pmp_2, lac_2)),    &
    1025           0 :                      max(a4(1,i,k), pmp_2, lac_2) )
    1026             :               endif
    1027             :             endif
    1028             :           enddo
    1029           0 :           do i=i1,i2
    1030           0 :             a4(4,i,k) = 3.0_r8*(2.0_r8*a4(1,i,k) - (a4(2,i,k)+a4(3,i,k)))
    1031             :           enddo
    1032             :         else      ! kord = 11, 13
    1033           0 :           do i=i1,i2
    1034           0 :             if ( ext5(i,k) .and. (ext5(i,k-1).or.ext5(i,k+1).or.a4(1,i,k)<qmin) ) then
    1035             :               ! Noisy region:
    1036           0 :               a4(2,i,k) = a4(1,i,k)
    1037           0 :               a4(3,i,k) = a4(1,i,k)
    1038           0 :               a4(4,i,k) = 0.0_r8
    1039             :             else
    1040           0 :               a4(4,i,k) = 3.0_r8*(2.0_r8*a4(1,i,k) - (a4(2,i,k)+a4(3,i,k)))
    1041             :             endif
    1042             :           enddo
    1043             :         endif
    1044             :         
    1045             :         ! Additional constraint to ensure positivity
    1046           0 :         if ( iv==0 ) call cs_limiters(im, extm(i1,k), a4(1,i1,k), 0)
    1047             :         
    1048             :       enddo      ! k-loop
    1049             :       
    1050             :       !----------------------------------
    1051             :       ! Bottom layer subgrid constraints:
    1052             :       !----------------------------------
    1053           0 :       if ( iv==0 ) then
    1054           0 :         do i=i1,i2
    1055           0 :           a4(3,i,km) = max(0.0_r8, a4(3,i,km))
    1056             :         enddo
    1057           0 :       elseif ( iv .eq. -1 ) then 
    1058           0 :         do i=i1,i2
    1059           0 :           if ( a4(3,i,km)*a4(1,i,km) <= 0.0_r8 )  a4(3,i,km) = 0.0_r8
    1060             :         enddo
    1061             :       endif
    1062             :       
    1063           0 :       do k=km-1,km
    1064           0 :         do i=i1,i2
    1065           0 :           a4(4,i,k) = 3.0_r8*(2.0_r8*a4(1,i,k) - (a4(2,i,k)+a4(3,i,k)))
    1066             :         enddo
    1067           0 :         if(k==(km-1)) call cs_limiters(im, extm(i1,k), a4(1,i1,k), 2)
    1068           0 :         if(k== km   ) call cs_limiters(im, extm(i1,k), a4(1,i1,k), 1)
    1069             :       enddo
    1070             : 
    1071             :     end subroutine scalar_profile
    1072             : 
    1073             :  
    1074   171428400 :     subroutine cs_profile(qs, a4, delp, km, i1, i2, iv, kord)
    1075             :       ! Optimized vertical profile reconstruction:
    1076             :       ! Latest: Apr 2008 S.-J. Lin, NOAA/GFDL
    1077             :       integer, intent(in):: i1, i2
    1078             :       integer, intent(in):: km      !< vertical dimension
    1079             :       integer, intent(in):: iv      !< iv =-1: winds
    1080             :       !< iv = 0: positive definite scalars
    1081             :       !< iv = 1: others
    1082             :       integer, intent(in):: kord
    1083             :       real(kind=r8), intent(in)   ::   qs(i1:i2)
    1084             :       real(kind=r8), intent(in)   :: delp(i1:i2,km)     !< layer pressure thickness
    1085             :       real(kind=r8), intent(inout):: a4(4,i1:i2,km)     !< Interpolated values
    1086             :       !-----------------------------------------------------------------------
    1087   342856800 :       logical, dimension(i1:i2,km):: extm, ext5, ext6
    1088   342856800 :       real(kind=r8)  gam(i1:i2,km)
    1089   342856800 :       real(kind=r8)    q(i1:i2,km+1)
    1090   171428400 :       real(kind=r8)   d4(i1:i2)
    1091             :       real(kind=r8)   bet, a_bot, grat 
    1092             :       real(kind=r8)   pmp_1, lac_1, pmp_2, lac_2, x0, x1
    1093             :       integer i, k, im
    1094             :       
    1095   171428400 :       if ( iv .eq. -2 ) then
    1096           0 :         do i=i1,i2
    1097           0 :           gam(i,2) = 0.5_r8
    1098           0 :           q(i,1) = 1.5_r8*a4(1,i,1)
    1099             :         enddo
    1100           0 :         do k=2,km-1
    1101           0 :           do i=i1, i2
    1102           0 :             grat = delp(i,k-1) / delp(i,k)
    1103           0 :             bet =  2.0_r8 + grat + grat - gam(i,k)
    1104           0 :             q(i,k) = (3.0_r8*(a4(1,i,k-1)+a4(1,i,k)) - q(i,k-1))/bet
    1105           0 :             gam(i,k+1) = grat / bet
    1106             :           enddo
    1107             :         enddo
    1108           0 :         do i=i1,i2
    1109           0 :           grat = delp(i,km-1) / delp(i,km) 
    1110           0 :           q(i,km) = (3.0_r8*(a4(1,i,km-1)+a4(1,i,km)) - grat*qs(i) - q(i,km-1)) /  &
    1111           0 :                (2.0_r8 + grat + grat - gam(i,km))
    1112           0 :           q(i,km+1) = qs(i)
    1113             :         enddo
    1114           0 :         do k=km-1,1,-1
    1115           0 :           do i=i1,i2
    1116           0 :             q(i,k) = q(i,k) - gam(i,k+1)*q(i,k+1)
    1117             :           enddo
    1118             :         enddo
    1119             :       else
    1120   810388800 :         do i=i1,i2
    1121   638960400 :           grat = delp(i,2) / delp(i,1)   ! grid ratio
    1122   638960400 :           bet = grat*(grat+0.5_r8)
    1123   638960400 :           q(i,1) = ( (grat+grat)*(grat+1.0_r8)*a4(1,i,1) + a4(1,i,2) ) / bet
    1124   810388800 :           gam(i,1) = ( 1.0_r8 + grat*(grat+1.5_r8) ) / bet
    1125             :         enddo
    1126             :         
    1127  4457138400 :         do k=2,km
    1128 20431148400 :           do i=i1,i2
    1129 15974010000 :             d4(i) = delp(i,k-1) / delp(i,k)
    1130 15974010000 :             bet =  2.0_r8 + d4(i) + d4(i) - gam(i,k-1)
    1131 15974010000 :             q(i,k) = ( 3.0_r8*(a4(1,i,k-1)+d4(i)*a4(1,i,k)) - q(i,k-1) )/bet
    1132 20259720000 :             gam(i,k) = d4(i) / bet
    1133             :           enddo
    1134             :         enddo
    1135             :         
    1136   810388800 :         do i=i1,i2
    1137   638960400 :           a_bot = 1.0_r8 + d4(i)*(d4(i)+1.5_r8)
    1138  1277920800 :           q(i,km+1) = (2.0_r8*d4(i)*(d4(i)+1.0_r8)*a4(1,i,km)+a4(1,i,km-1)-a_bot*q(i,km))  &
    1139  1449349200 :                / ( d4(i)*(d4(i)+0.5_r8) - a_bot*gam(i,km) )
    1140             :         enddo
    1141             :         
    1142  4628566800 :         do k=km,1,-1
    1143 21241537200 :           do i=i1,i2
    1144 21070108800 :             q(i,k) = q(i,k) - gam(i,k)*q(i,k+1)
    1145             :           enddo
    1146             :         enddo
    1147             :       endif
    1148             :       !----- Perfectly linear scheme --------------------------------
    1149   171428400 :       if ( abs(kord) > 16 ) then
    1150           0 :         do k=1,km
    1151           0 :           do i=i1,i2
    1152           0 :             a4(2,i,k) = q(i,k  )
    1153           0 :             a4(3,i,k) = q(i,k+1)
    1154           0 :             a4(4,i,k) = 3.0_r8*(2.0_r8*a4(1,i,k) - (a4(2,i,k)+a4(3,i,k)))
    1155             :           enddo
    1156             :         enddo
    1157             :         return
    1158             :       endif
    1159             :       !----- Perfectly linear scheme --------------------------------
    1160             :       
    1161             :       !------------------
    1162             :       ! Apply constraints
    1163             :       !------------------
    1164   171428400 :       im = i2 - i1 + 1
    1165             :       
    1166             :       ! Apply *large-scale* constraints 
    1167   810388800 :       do i=i1,i2
    1168   638960400 :         q(i,2) = min( q(i,2), max(a4(1,i,1), a4(1,i,2)) )
    1169   810388800 :         q(i,2) = max( q(i,2), min(a4(1,i,1), a4(1,i,2)) )
    1170             :       enddo
    1171             :       
    1172  4457138400 :       do k=2,km
    1173 20431148400 :         do i=i1,i2
    1174 20259720000 :           gam(i,k) = a4(1,i,k) - a4(1,i,k-1)
    1175             :         enddo
    1176             :       enddo
    1177             :       
    1178             :       ! Interior:
    1179  4114281600 :       do k=3,km-1
    1180 18810370800 :         do i=i1,i2
    1181 18638942400 :           if ( gam(i,k-1)*gam(i,k+1)>0.0_r8 ) then
    1182             :             ! Apply large-scale constraint to ALL fields if not local max/min
    1183 10799865931 :             q(i,k) = min( q(i,k), max(a4(1,i,k-1),a4(1,i,k)) )
    1184 10799865931 :             q(i,k) = max( q(i,k), min(a4(1,i,k-1),a4(1,i,k)) )
    1185             :           else
    1186  3896223269 :             if ( gam(i,k-1) > 0.0_r8 ) then
    1187             :               ! There exists a local max
    1188  1905969455 :               q(i,k) = max(q(i,k), min(a4(1,i,k-1),a4(1,i,k)))
    1189             :             else
    1190             :               ! There exists a local min
    1191  1990253814 :               q(i,k) = min(q(i,k), max(a4(1,i,k-1),a4(1,i,k)))
    1192  1990253814 :               if ( iv==0 ) q(i,k) = max(0.0_r8, q(i,k))
    1193             :             endif
    1194             :           endif
    1195             :         enddo
    1196             :       enddo
    1197             :       
    1198             :       ! Bottom:
    1199   810388800 :       do i=i1,i2
    1200   638960400 :         q(i,km) = min( q(i,km), max(a4(1,i,km-1), a4(1,i,km)) )
    1201   810388800 :         q(i,km) = max( q(i,km), min(a4(1,i,km-1), a4(1,i,km)) )
    1202             :       enddo
    1203             :       
    1204  4628566800 :       do k=1,km
    1205 21241537200 :         do i=i1,i2
    1206 16612970400 :           a4(2,i,k) = q(i,k  )
    1207 21070108800 :           a4(3,i,k) = q(i,k+1)
    1208             :         enddo
    1209             :       enddo
    1210             :       
    1211  4628566800 :       do k=1,km
    1212  4457138400 :         if ( k==1 .or. k==km ) then
    1213  1620777600 :           do i=i1,i2
    1214  1620777600 :             extm(i,k) = (a4(2,i,k)-a4(1,i,k)) * (a4(3,i,k)-a4(1,i,k)) > 0.0_r8
    1215             :           enddo
    1216             :         else
    1217 19449331200 :           do i=i1,i2
    1218 19449331200 :             extm(i,k) = gam(i,k)*gam(i,k+1) < 0.0_r8
    1219             :           enddo
    1220             :         endif
    1221  4628566800 :         if ( abs(kord) > 9 ) then
    1222           0 :           do i=i1,i2
    1223           0 :             x0 = 2.0_r8*a4(1,i,k) - (a4(2,i,k)+a4(3,i,k))
    1224           0 :             x1 = abs(a4(2,i,k)-a4(3,i,k))
    1225           0 :             a4(4,i,k) = 3.0_r8*x0
    1226           0 :             ext5(i,k) = abs(x0) > x1
    1227           0 :             ext6(i,k) = abs(a4(4,i,k)) > x1
    1228             :           enddo
    1229             :         endif
    1230             :       enddo
    1231             :       
    1232             :       !---------------------------
    1233             :       ! Apply subgrid constraints:
    1234             :       !---------------------------
    1235             :       ! f(s) = AL + s*[(AR-AL) + A6*(1-s)]         ( 0 <= s  <= 1 )
    1236             :       ! Top 2 and bottom 2 layers always use monotonic mapping
    1237             :       
    1238   171428400 :       if ( iv==0 ) then
    1239   498700800 :         do i=i1,i2
    1240   498700800 :           a4(2,i,1) = max(0.0_r8, a4(2,i,1))
    1241             :         enddo
    1242    62337600 :       elseif ( iv==-1 ) then 
    1243   207792000 :         do i=i1,i2
    1244   207792000 :           if ( a4(2,i,1)*a4(1,i,1) <= 0.0_r8 ) a4(2,i,1) = 0.0_r8
    1245             :         enddo
    1246    20779200 :       elseif ( iv==2 ) then
    1247           0 :         do i=i1,i2
    1248           0 :           a4(2,i,1) = a4(1,i,1)
    1249           0 :           a4(3,i,1) = a4(1,i,1)
    1250           0 :           a4(4,i,1) = 0.0_r8
    1251             :         enddo
    1252             :       endif
    1253             :       
    1254   171428400 :       if ( iv/=2 ) then
    1255   810388800 :         do i=i1,i2
    1256   810388800 :           a4(4,i,1) = 3.0_r8*(2.0_r8*a4(1,i,1) - (a4(2,i,1)+a4(3,i,1)))
    1257             :         enddo
    1258   171428400 :         call cs_limiters(im, extm(i1,1), a4(1,i1,1), 1)
    1259             :       endif
    1260             :       
    1261   810388800 :       do i=i1,i2
    1262   810388800 :         a4(4,i,2) = 3.0_r8*(2.0_r8*a4(1,i,2) - (a4(2,i,2)+a4(3,i,2)))
    1263             :       enddo
    1264   171428400 :       call cs_limiters(im, extm(i1,2), a4(1,i1,2), 2)
    1265             :       
    1266             :       !-------------------------------------
    1267             :       ! Huynh's 2nd constraint for interior:
    1268             :       !-------------------------------------
    1269  3942853200 :       do k=3,km-2
    1270  3771424800 :         if ( abs(kord)<9 ) then
    1271           0 :           do i=i1,i2
    1272             :             ! Left  edges
    1273           0 :             pmp_1 = a4(1,i,k) - 2.0_r8*gam(i,k+1)
    1274           0 :             lac_1 = pmp_1 + 1.5_r8*gam(i,k+2)
    1275             :             a4(2,i,k) = min(max(a4(2,i,k), min(a4(1,i,k), pmp_1, lac_1)),   &
    1276           0 :                  max(a4(1,i,k), pmp_1, lac_1) )
    1277             :             ! Right edges
    1278           0 :             pmp_2 = a4(1,i,k) + 2.0_r8*gam(i,k)
    1279           0 :             lac_2 = pmp_2 - 1.5_r8*gam(i,k-1)
    1280             :             a4(3,i,k) = min(max(a4(3,i,k), min(a4(1,i,k), pmp_2, lac_2)),    &
    1281           0 :                  max(a4(1,i,k), pmp_2, lac_2) )
    1282             :             
    1283           0 :             a4(4,i,k) = 3.0_r8*(2.0_r8*a4(1,i,k) - (a4(2,i,k)+a4(3,i,k)))
    1284             :           enddo
    1285             :           
    1286             :         elseif ( abs(kord)==9 ) then
    1287 17828553600 :           do i=i1,i2
    1288 17828553600 :             if ( extm(i,k) .and. extm(i,k-1) ) then  ! c90_mp122
    1289             :               ! grid-scale 2-delta-z wave detected
    1290   842272345 :               a4(2,i,k) = a4(1,i,k)
    1291   842272345 :               a4(3,i,k) = a4(1,i,k)
    1292   842272345 :               a4(4,i,k) = 0.0_r8
    1293 13214856455 :             else if ( extm(i,k) .and. extm(i,k+1) ) then  ! c90_mp122
    1294             :               ! grid-scale 2-delta-z wave detected
    1295   605102218 :               a4(2,i,k) = a4(1,i,k)
    1296   605102218 :               a4(3,i,k) = a4(1,i,k)
    1297   605102218 :               a4(4,i,k) = 0.0_r8
    1298             :             else
    1299 12609754237 :               a4(4,i,k) = 6.0_r8*a4(1,i,k) - 3.0_r8*(a4(2,i,k)+a4(3,i,k))
    1300             :               ! Check within the smooth region if subgrid profile is non-monotonic
    1301 12609754237 :               if( abs(a4(4,i,k)) > abs(a4(2,i,k)-a4(3,i,k)) ) then
    1302  5119002489 :                 pmp_1 = a4(1,i,k) - 2.0_r8*gam(i,k+1)
    1303  5119002489 :                 lac_1 = pmp_1 + 1.5_r8*gam(i,k+2)
    1304             :                 a4(2,i,k) = min(max(a4(2,i,k), min(a4(1,i,k), pmp_1, lac_1)),  &
    1305  5119002489 :                      max(a4(1,i,k), pmp_1, lac_1) )
    1306  5119002489 :                 pmp_2 = a4(1,i,k) + 2.0_r8*gam(i,k)
    1307  5119002489 :                 lac_2 = pmp_2 - 1.5_r8*gam(i,k-1)
    1308             :                 a4(3,i,k) = min(max(a4(3,i,k), min(a4(1,i,k), pmp_2, lac_2)),  &
    1309  5119002489 :                      max(a4(1,i,k), pmp_2, lac_2) )
    1310  5119002489 :                 a4(4,i,k) = 6.0_r8*a4(1,i,k) - 3.0_r8*(a4(2,i,k)+a4(3,i,k))
    1311             :               endif
    1312             :             endif
    1313             :           enddo
    1314             :         elseif ( abs(kord)==10 ) then
    1315           0 :           do i=i1,i2
    1316           0 :             if( ext5(i,k) ) then
    1317           0 :               if( ext5(i,k-1) .or. ext5(i,k+1) ) then
    1318           0 :                 a4(2,i,k) = a4(1,i,k)
    1319           0 :                 a4(3,i,k) = a4(1,i,k)
    1320           0 :               elseif ( ext6(i,k-1) .or. ext6(i,k+1) ) then
    1321           0 :                 pmp_1 = a4(1,i,k) - 2.0_r8*gam(i,k+1)
    1322           0 :                 lac_1 = pmp_1 + 1.5_r8*gam(i,k+2)
    1323             :                 a4(2,i,k) = min(max(a4(2,i,k), min(a4(1,i,k), pmp_1, lac_1)),  &
    1324           0 :                      max(a4(1,i,k), pmp_1, lac_1) )
    1325           0 :                 pmp_2 = a4(1,i,k) + 2.0_r8*gam(i,k)
    1326           0 :                 lac_2 = pmp_2 - 1.5_r8*gam(i,k-1)
    1327             :                 a4(3,i,k) = min(max(a4(3,i,k), min(a4(1,i,k), pmp_2, lac_2)),  &
    1328           0 :                      max(a4(1,i,k), pmp_2, lac_2) )
    1329             :               endif
    1330           0 :             elseif( ext6(i,k) ) then
    1331           0 :               if( ext5(i,k-1) .or. ext5(i,k+1) ) then
    1332           0 :                 pmp_1 = a4(1,i,k) - 2.0_r8*gam(i,k+1)
    1333           0 :                 lac_1 = pmp_1 + 1.5_r8*gam(i,k+2)
    1334             :                 a4(2,i,k) = min(max(a4(2,i,k), min(a4(1,i,k), pmp_1, lac_1)),  &
    1335           0 :                      max(a4(1,i,k), pmp_1, lac_1) )
    1336           0 :                 pmp_2 = a4(1,i,k) + 2.0_r8*gam(i,k)
    1337           0 :                 lac_2 = pmp_2 - 1.5_r8*gam(i,k-1)
    1338             :                 a4(3,i,k) = min(max(a4(3,i,k), min(a4(1,i,k), pmp_2, lac_2)),  &
    1339           0 :                      max(a4(1,i,k), pmp_2, lac_2) )
    1340             :               endif
    1341             :             endif
    1342             :           enddo
    1343           0 :           do i=i1,i2
    1344           0 :             a4(4,i,k) = 3.0_r8*(2.0_r8*a4(1,i,k) - (a4(2,i,k)+a4(3,i,k)))
    1345             :           enddo
    1346             :         elseif ( abs(kord)==12 ) then
    1347           0 :           do i=i1,i2
    1348           0 :             if( extm(i,k) ) then
    1349             :               ! grid-scale 2-delta-z wave detected
    1350           0 :               a4(2,i,k) = a4(1,i,k)
    1351           0 :               a4(3,i,k) = a4(1,i,k)
    1352           0 :               a4(4,i,k) = 0.0_r8
    1353             :             else        ! not a local extremum
    1354           0 :               a4(4,i,k) = 6.0_r8*a4(1,i,k) - 3.0_r8*(a4(2,i,k)+a4(3,i,k))
    1355             :               ! Check within the smooth region if subgrid profile is non-monotonic
    1356           0 :               if( abs(a4(4,i,k)) > abs(a4(2,i,k)-a4(3,i,k)) ) then
    1357           0 :                 pmp_1 = a4(1,i,k) - 2.0_r8*gam(i,k+1)
    1358           0 :                 lac_1 = pmp_1 + 1.5_r8*gam(i,k+2)
    1359             :                 a4(2,i,k) = min(max(a4(2,i,k), min(a4(1,i,k), pmp_1, lac_1)),  &
    1360           0 :                      max(a4(1,i,k), pmp_1, lac_1) )
    1361           0 :                 pmp_2 = a4(1,i,k) + 2.0_r8*gam(i,k)
    1362           0 :                 lac_2 = pmp_2 - 1.5_r8*gam(i,k-1)
    1363             :                 a4(3,i,k) = min(max(a4(3,i,k), min(a4(1,i,k), pmp_2, lac_2)),  &
    1364           0 :                      max(a4(1,i,k), pmp_2, lac_2) )
    1365           0 :                 a4(4,i,k) = 6.0_r8*a4(1,i,k) - 3.0_r8*(a4(2,i,k)+a4(3,i,k))
    1366             :               endif
    1367             :             endif
    1368             :           enddo
    1369             :         elseif ( abs(kord)==13 ) then
    1370           0 :           do i=i1,i2
    1371           0 :             if( ext6(i,k) ) then
    1372           0 :               if ( ext6(i,k-1) .and. ext6(i,k+1) ) then
    1373             :                 ! grid-scale 2-delta-z wave detected
    1374           0 :                 a4(2,i,k) = a4(1,i,k)
    1375           0 :                 a4(3,i,k) = a4(1,i,k)
    1376             :               endif
    1377             :             endif
    1378             :           enddo
    1379           0 :           do i=i1,i2
    1380           0 :             a4(4,i,k) = 3.0_r8*(2.0_r8*a4(1,i,k) - (a4(2,i,k)+a4(3,i,k)))
    1381             :           enddo
    1382             :         elseif ( abs(kord)==14 ) then
    1383             :           
    1384           0 :           do i=i1,i2
    1385           0 :             a4(4,i,k) = 3.0_r8*(2.0_r8*a4(1,i,k) - (a4(2,i,k)+a4(3,i,k)))
    1386             :           enddo
    1387             :           
    1388             :         elseif ( abs(kord)==15 ) then   ! revised kord=9 scehem
    1389           0 :           do i=i1,i2
    1390           0 :             if ( ext5(i,k) ) then  ! c90_mp122
    1391           0 :               if ( ext5(i,k-1) .or. ext5(i,k+1) ) then  ! c90_mp122
    1392             :                 ! grid-scale 2-delta-z wave detected
    1393           0 :                 a4(2,i,k) = a4(1,i,k)
    1394           0 :                 a4(3,i,k) = a4(1,i,k)
    1395             :               endif
    1396           0 :             elseif( ext6(i,k) ) then
    1397             :               ! Check within the smooth region if subgrid profile is non-monotonic
    1398           0 :               pmp_1 = a4(1,i,k) - 2.0_r8*gam(i,k+1)
    1399           0 :               lac_1 = pmp_1 + 1.5_r8*gam(i,k+2)
    1400             :               a4(2,i,k) = min(max(a4(2,i,k), min(a4(1,i,k), pmp_1, lac_1)),  &
    1401           0 :                    max(a4(1,i,k), pmp_1, lac_1) )
    1402           0 :               pmp_2 = a4(1,i,k) + 2.0_r8*gam(i,k)
    1403           0 :               lac_2 = pmp_2 - 1.5_r8*gam(i,k-1)
    1404             :               a4(3,i,k) = min(max(a4(3,i,k), min(a4(1,i,k), pmp_2, lac_2)),  &
    1405           0 :                    max(a4(1,i,k), pmp_2, lac_2) )
    1406             :             endif
    1407             :           enddo
    1408           0 :           do i=i1,i2
    1409           0 :             a4(4,i,k) = 3.0_r8*(2.0_r8*a4(1,i,k) - (a4(2,i,k)+a4(3,i,k)))
    1410             :           enddo
    1411             :         elseif ( abs(kord)==16 ) then
    1412           0 :           do i=i1,i2
    1413           0 :             if( ext5(i,k) ) then
    1414           0 :               if ( ext5(i,k-1) .or. ext5(i,k+1) ) then
    1415           0 :                 a4(2,i,k) = a4(1,i,k)
    1416           0 :                 a4(3,i,k) = a4(1,i,k)
    1417           0 :               elseif ( ext6(i,k-1) .or. ext6(i,k+1) ) then
    1418             :                 ! Left  edges
    1419           0 :                 pmp_1 = a4(1,i,k) - 2.0_r8*gam(i,k+1)
    1420           0 :                 lac_1 = pmp_1 + 1.5_r8*gam(i,k+2)
    1421             :                 a4(2,i,k) = min(max(a4(2,i,k), min(a4(1,i,k), pmp_1, lac_1)),   &
    1422           0 :                      max(a4(1,i,k), pmp_1, lac_1) )
    1423             :                 ! Right edges
    1424           0 :                 pmp_2 = a4(1,i,k) + 2.0_r8*gam(i,k)
    1425           0 :                 lac_2 = pmp_2 - 1.5_r8*gam(i,k-1)
    1426             :                 a4(3,i,k) = min(max(a4(3,i,k), min(a4(1,i,k), pmp_2, lac_2)),    &
    1427           0 :                      max(a4(1,i,k), pmp_2, lac_2) )
    1428             :               endif
    1429             :             endif
    1430             :           enddo
    1431           0 :           do i=i1,i2
    1432           0 :             a4(4,i,k) = 3.0_r8*(2.0_r8*a4(1,i,k) - (a4(2,i,k)+a4(3,i,k)))
    1433             :           enddo
    1434             :         else      ! kord = 11
    1435           0 :           do i=i1,i2
    1436           0 :             if ( ext5(i,k) .and. (ext5(i,k-1) .or. ext5(i,k+1)) ) then
    1437             :               ! Noisy region:
    1438           0 :               a4(2,i,k) = a4(1,i,k)
    1439           0 :               a4(3,i,k) = a4(1,i,k)
    1440           0 :               a4(4,i,k) = 0.0_r8
    1441             :             else
    1442           0 :               a4(4,i,k) = 3.0_r8*(2.0_r8*a4(1,i,k) - (a4(2,i,k)+a4(3,i,k)))
    1443             :             endif
    1444             :           enddo
    1445             :         endif
    1446             :         
    1447             :         ! Additional constraint to ensure positivity
    1448  3942853200 :         if ( iv==0 ) call cs_limiters(im, extm(i1,k), a4(1,i1,k), 0)
    1449             :         
    1450             :       enddo      ! k-loop
    1451             :       
    1452             :       !----------------------------------
    1453             :       ! Bottom layer subgrid constraints:
    1454             :       !----------------------------------
    1455   171428400 :       if ( iv==0 ) then
    1456   498700800 :         do i=i1,i2
    1457   498700800 :           a4(3,i,km) = max(0.0_r8, a4(3,i,km))
    1458             :         enddo
    1459    62337600 :       elseif ( iv .eq. -1 ) then 
    1460   207792000 :         do i=i1,i2
    1461   207792000 :           if ( a4(3,i,km)*a4(1,i,km) <= 0.0_r8 )  a4(3,i,km) = 0.0_r8
    1462             :         enddo
    1463             :       endif
    1464             :       
    1465   514285200 :       do k=km-1,km
    1466  1620777600 :         do i=i1,i2
    1467  1620777600 :           a4(4,i,k) = 3.0_r8*(2.0_r8*a4(1,i,k) - (a4(2,i,k)+a4(3,i,k)))
    1468             :         enddo
    1469   342856800 :         if(k==(km-1)) call cs_limiters(im, extm(i1,k), a4(1,i1,k), 2)
    1470   514285200 :         if(k== km   ) call cs_limiters(im, extm(i1,k), a4(1,i1,k), 1)
    1471             :       enddo
    1472             :       
    1473             :     end subroutine cs_profile
    1474             :     
    1475  3085711200 :     subroutine cs_limiters(im, extm, a4, iv)
    1476             :       integer, intent(in) :: im
    1477             :       integer, intent(in) :: iv
    1478             :       logical, intent(in) :: extm(im)
    1479             :       real(kind=r8) , intent(inout) :: a4(4,im)   !< PPM array
    1480             :       ! LOCAL VARIABLES:
    1481             :       real(kind=r8)  da1, da2, a6da
    1482             :       integer i
    1483             :       
    1484  3085711200 :       if ( iv==0 ) then
    1485             :         ! Positive definite constraint
    1486 10971417600 :         do i=1,im
    1487 10971417600 :           if( a4(1,i)<=0.0_r8) then
    1488  1567798095 :             a4(2,i) = a4(1,i)
    1489  1567798095 :             a4(3,i) = a4(1,i)
    1490  1567798095 :             a4(4,i) = 0.0_r8
    1491             :           else
    1492  7003621905 :             if( abs(a4(3,i)-a4(2,i)) < -a4(4,i) ) then
    1493  1258062329 :               if( (a4(1,i)+0.25_r8*(a4(3,i)-a4(2,i))**2/a4(4,i)+a4(4,i)*r12) < 0.0_r8 ) then
    1494             :                 ! local minimum is negative
    1495   275120694 :                 if( a4(1,i)<a4(3,i) .and. a4(1,i)<a4(2,i) ) then
    1496      891701 :                   a4(3,i) = a4(1,i)
    1497      891701 :                   a4(2,i) = a4(1,i)
    1498      891701 :                   a4(4,i) = 0.0_r8
    1499   274228993 :                 elseif( a4(3,i) > a4(2,i) ) then
    1500   152306596 :                   a4(4,i) = 3.0_r8*(a4(2,i)-a4(1,i))
    1501   152306596 :                   a4(3,i) = a4(2,i) - a4(4,i)
    1502             :                 else
    1503   121922397 :                   a4(4,i) = 3.0_r8*(a4(3,i)-a4(1,i))
    1504   121922397 :                   a4(2,i) = a4(3,i) - a4(4,i)
    1505             :                 endif
    1506             :               endif
    1507             :             endif
    1508             :           endif
    1509             :         enddo
    1510   685713600 :       elseif ( iv==1 ) then
    1511  1620777600 :         do i=1,im
    1512  1620777600 :           if( (a4(1,i)-a4(2,i))*(a4(1,i)-a4(3,i))>=0.0_r8 ) then
    1513   462717819 :             a4(2,i) = a4(1,i)
    1514   462717819 :             a4(3,i) = a4(1,i)
    1515   462717819 :             a4(4,i) = 0.0_r8
    1516             :           else
    1517   815202981 :             da1  = a4(3,i) - a4(2,i)
    1518   815202981 :             da2  = da1**2
    1519   815202981 :             a6da = a4(4,i)*da1
    1520   815202981 :             if(a6da < -da2) then
    1521   174978013 :               a4(4,i) = 3.0_r8*(a4(2,i)-a4(1,i))
    1522   174978013 :               a4(3,i) = a4(2,i) - a4(4,i)
    1523   640224968 :             elseif(a6da > da2) then
    1524    65366476 :               a4(4,i) = 3.0_r8*(a4(3,i)-a4(1,i))
    1525    65366476 :               a4(2,i) = a4(3,i) - a4(4,i)
    1526             :             endif
    1527             :           endif
    1528             :         enddo
    1529             :       else
    1530             :         ! Standard PPM constraint
    1531  1620777600 :         do i=1,im
    1532  1620777600 :           if( extm(i) ) then
    1533   175280777 :             a4(2,i) = a4(1,i)
    1534   175280777 :             a4(3,i) = a4(1,i)
    1535   175280777 :             a4(4,i) = 0.0_r8
    1536             :           else
    1537  1102640023 :             da1  = a4(3,i) - a4(2,i)
    1538  1102640023 :             da2  = da1**2
    1539  1102640023 :             a6da = a4(4,i)*da1
    1540  1102640023 :             if(a6da < -da2) then
    1541   205743392 :               a4(4,i) = 3.0_r8*(a4(2,i)-a4(1,i))
    1542   205743392 :               a4(3,i) = a4(2,i) - a4(4,i)
    1543   896896631 :             elseif(a6da > da2) then
    1544   191993177 :               a4(4,i) = 3.0_r8*(a4(3,i)-a4(1,i))
    1545   191993177 :               a4(2,i) = a4(3,i) - a4(4,i)
    1546             :             endif
    1547             :           endif
    1548             :         enddo
    1549             :       endif
    1550  3085711200 :     end subroutine cs_limiters
    1551             :     
    1552             :     
    1553           0 :     subroutine fillz(im, km, nq, q, dp)
    1554             :       integer,  intent(in):: im                !< No. of longitudes
    1555             :       integer,  intent(in):: km                !< No. of levels
    1556             :       integer,  intent(in):: nq                !< Total number of tracers
    1557             :       real(kind=r8) , intent(in)::  dp(im,km)           !< pressure thickness
    1558             :       real(kind=r8) , intent(inout) :: q(im,km,nq)      !< tracer mixing ratio
    1559             :       ! LOCAL VARIABLES:
    1560           0 :       logical:: zfix(im)
    1561           0 :       real(kind=r8) ::  dm(km)
    1562             :       integer i, k, ic, k1
    1563             :       real(kind=r8)  qup, qly, dup, dq, sum0, sum1, fac
    1564             :       
    1565           0 :       do ic=1,nq
    1566             : #ifdef DEV_GFS_PHYS
    1567             :         ! Bottom up:
    1568             :         do k=km,2,-1
    1569             :           k1 = k-1
    1570             :           do i=1,im
    1571             :             if( q(i,k,ic) < 0.0_r8 ) then
    1572             :               q(i,k1,ic) = q(i,k1,ic) + q(i,k,ic)*dp(i,k)/dp(i,k1)
    1573             :               q(i,k ,ic) = 0.0_r8
    1574             :             endif
    1575             :           enddo
    1576             :         enddo
    1577             :         ! Top down:
    1578             :         do k=1,km-1
    1579             :           k1 = k+1
    1580             :           do i=1,im
    1581             :             if( q(i,k,ic) < 0.0_r8 ) then
    1582             :               q(i,k1,ic) = q(i,k1,ic) + q(i,k,ic)*dp(i,k)/dp(i,k1)
    1583             :               q(i,k ,ic) = 0.0_r8
    1584             :             endif
    1585             :           enddo
    1586             :         enddo
    1587             : #else
    1588             :         ! Top layer
    1589           0 :         do i=1,im
    1590           0 :           if( q(i,1,ic) < 0.0_r8 ) then
    1591           0 :             q(i,2,ic) = q(i,2,ic) + q(i,1,ic)*dp(i,1)/dp(i,2)
    1592           0 :             q(i,1,ic) = 0.0_r8
    1593             :           endif
    1594             :         enddo
    1595             :         
    1596             :         ! Interior
    1597           0 :         zfix(:) = .false.
    1598           0 :         do k=2,km-1
    1599           0 :           do i=1,im
    1600           0 :             if( q(i,k,ic) < 0.0_r8 ) then
    1601           0 :               zfix(i) = .true.
    1602           0 :               if ( q(i,k-1,ic) > 0.0_r8 ) then
    1603             :                 ! Borrow from above
    1604           0 :                 dq = min ( q(i,k-1,ic)*dp(i,k-1), -q(i,k,ic)*dp(i,k) ) 
    1605           0 :                 q(i,k-1,ic) = q(i,k-1,ic) - dq/dp(i,k-1)
    1606           0 :                 q(i,k  ,ic) = q(i,k  ,ic) + dq/dp(i,k  )
    1607             :               endif
    1608           0 :               if ( q(i,k,ic)<0.0_r8 .and. q(i,k+1,ic)>0.0_r8 ) then
    1609             :                 ! Borrow from below:
    1610           0 :                 dq = min ( q(i,k+1,ic)*dp(i,k+1), -q(i,k,ic)*dp(i,k) ) 
    1611           0 :                 q(i,k+1,ic) = q(i,k+1,ic) - dq/dp(i,k+1)
    1612           0 :                 q(i,k  ,ic) = q(i,k  ,ic) + dq/dp(i,k  )
    1613             :               endif
    1614             :             endif
    1615             :           enddo
    1616             :         enddo
    1617             :         
    1618             :         ! Bottom layer
    1619           0 :         k = km
    1620           0 :         do i=1,im
    1621           0 :           if( q(i,k,ic)<0.0_r8 .and. q(i,k-1,ic)>0.0_r8) then
    1622           0 :             zfix(i) = .true.
    1623             :             ! Borrow from above
    1624           0 :             qup =  q(i,k-1,ic)*dp(i,k-1)
    1625           0 :             qly = -q(i,k  ,ic)*dp(i,k  )
    1626           0 :             dup =  min(qly, qup)
    1627           0 :             q(i,k-1,ic) = q(i,k-1,ic) - dup/dp(i,k-1) 
    1628           0 :             q(i,k,  ic) = q(i,k,  ic) + dup/dp(i,k  )
    1629             :           endif
    1630             :         enddo
    1631             :         
    1632             :         ! Perform final check and non-local fix if needed
    1633           0 :         do i=1,im
    1634           0 :           if ( zfix(i) ) then
    1635             :             sum0 = 0.0_r8
    1636           0 :             do k=2,km
    1637           0 :               dm(k) = q(i,k,ic)*dp(i,k)
    1638           0 :               sum0 = sum0 + dm(k)
    1639             :             enddo
    1640             :             
    1641           0 :             if ( sum0 > 0.0_r8 ) then
    1642             :               sum1 = 0.0_r8
    1643           0 :               do k=2,km
    1644           0 :                 sum1 = sum1 + max(0.0_r8, dm(k))
    1645             :               enddo
    1646           0 :               fac = sum0 / sum1
    1647           0 :               do k=2,km
    1648           0 :                 q(i,k,ic) = max(0.0_r8, fac*dm(k)/dp(i,k))
    1649             :               enddo
    1650             :             endif
    1651             :             
    1652             :           endif
    1653             :         enddo
    1654             : #endif
    1655             :         
    1656             :       enddo
    1657           0 :     end subroutine fillz
    1658             :   end module fv_mapz

Generated by: LCOV version 1.14