LCOV - code coverage report
Current view: | top level - chemistry/utils - mo_flbc.F90 (source / functions) |  |  | Hit | Total | Coverage
Test: | coverage.info |  | Lines: | 213 | 331 | 64.4 %
Date: | 2024-12-17 22:39:59 |  | Functions: | 9 | 10 | 90.0 %

              Line data    Source code
           1             : module mo_flbc
           2             :   !---------------------------------------------------------------
           3             :   !     ... lower boundary module
           4             :   !---------------------------------------------------------------
           5             :
           6             :   use shr_kind_mod,     only : r8 => shr_kind_r8
           7             :   use m_types,          only : time_ramp
           8             :   use spmd_utils,       only : masterproc
           9             :   use cam_abortutils,   only : endrun
          10             :   use ioFileMod,        only : getfil
          11             :   use ppgrid,           only : pcols, begchunk, endchunk, pver
          12             :   use time_manager,     only : get_curr_date
          13             :   use time_utils,       only : flt_date
          14             :   use cam_logfile,      only : iulog
          15             :   use constituents,     only : pcnst
          16             :
          17             :   implicit none
          18             :
          19             :   type :: flbc
          20             :      integer            :: spc_ndx = -1
          21             :      real(r8), pointer  :: vmr(:,:,:)
          22             :      character(len=16)  :: species = ' '
          23             :      logical            :: has_mean
          24             :      real(r8), pointer  :: vmr_mean(:)
          25             :   end type flbc
          26             :
          27             :   private
          28             :   public  :: flbc_inti, flbc_set, flbc_chk, has_flbc
          29             :   public  :: flbc_gmean_vmr
          30             :   public  :: flbc_get_cfc11eq, flbc_has_cfc11eq
          31             :
          32             :   save
          33             :
          34             :   integer, parameter :: time_span = 1
          35             :
          36             :   integer :: ntimes
          37             :   integer :: flbc_cnt
          38             :   integer :: tim_ndx(2)
          39             :   integer, allocatable  :: dates(:)
          40             :   real(r8), allocatable     :: times(:)
          41             :   logical, protected :: has_flbc(pcnst)
          42             :   character(len=256) :: filename
          43             :
          44             :   type(time_ramp) :: flbc_timing
          45             :   integer ::  ncdate, ncsec
          46             :
          47             :   integer, parameter :: nghg = 6
          48             :   integer, parameter :: max_nflbc = pcnst+nghg
          49             :
          50             :   integer, parameter :: co2_ndx = 1
          51             :   integer, parameter :: ch4_ndx = 2
          52             :   integer, parameter :: n2o_ndx = 3
          53             :   integer, parameter :: f11_ndx = 4
          54             :   integer, parameter :: f12_ndx = 5
          55             :   integer, parameter :: f11eq_ndx = 6
          56             :   character(len=8)  :: ghg_names(nghg) = (/ 'CO2     ','CH4     ','N2O     ','CFC11   ','CFC12   ','CFC11eq ' /)
          57             :   integer :: ghg_indices(nghg) = -1
          58             :
          59             :   type(flbc) :: flbcs(max_nflbc)
          60             :
          61             :   logical, parameter :: debug = .false.
          62             :   logical, protected :: flbc_has_cfc11eq = .false.
          63             :
          64             : contains
          65             :
          66        1536 :   subroutine flbc_inti( flbc_file, flbc_list, flbc_timing_in, co2vmr, ch4vmr, n2ovmr, f11vmr, f12vmr )
          67             :     !-----------------------------------------------------------------------
          68             :     !   ... initialize the fixed lower bndy cond
          69             :     !-----------------------------------------------------------------------
          70             :
          71             :     use string_utils,  only : to_upper
          72             :     use constituents,  only : cnst_get_ind
          73             :     use cam_pio_utils, only : cam_pio_openfile
          74             :     use pio,           only : pio_get_var,pio_inq_varid,pio_inq_dimid, pio_inq_dimlen
          75             :     use pio,           only : file_desc_t, pio_closefile, pio_nowrite
          76             :
          77             :     implicit none
          78             :
          79             :     !-----------------------------------------------------------------------
          80             :     !   ... dummy arguments
          81             :     !-----------------------------------------------------------------------
          82             :     character(len=*), intent(in) :: flbc_file
          83             :     character(len=*), intent(in) :: flbc_list(:)
          84             :     type(time_ramp),  intent(in) :: flbc_timing_in
          85             :     real(r8),         intent(in) :: co2vmr, ch4vmr, n2ovmr, f11vmr, f12vmr
          86             :
          87             :     !-----------------------------------------------------------------------
          88             :     !   ... local variables
          89             :     !-----------------------------------------------------------------------
          90             :     integer :: astat
          91             :     integer :: m, n                     ! Indices
          92             :     integer :: t1, t2
          93             :     type(file_desc_t) :: ncid
          94             :     integer :: dimid
          95             :     integer :: varid
          96             :     integer :: yr, mon, day, wrk_date, wrk_sec
          97             :     real(r8)    :: wrk_time
          98             :     character(len=8)   :: time_type
          99             :     integer :: ierr
         100             :
         101        1536 :     if ( len_trim( flbc_file ) == 0 .or. flbc_file.eq.'NONE') return
         102             :
         103        1536 :     call get_curr_date( yr, mon, day, ncsec )
         104        1536 :     ncdate = yr*10000 + mon*100 + day
         105             :
         106             :     !-----------------------------------------------------------------------
         107             :     !   ... check timing
         108             :     !-----------------------------------------------------------------------
         109        1536 :     flbc_timing = flbc_timing_in
         110        1536 :     time_type = to_upper(flbc_timing%type)
         111        1536 :     flbc_timing%type = time_type
         112             :     if( time_type /= 'SERIAL' .and. time_type /= 'CYCLICAL' &
         113        1536 :          .and. time_type /= 'FIXED' ) then
         114           0 :        write(iulog,*) 'flbc_inti: time type ',trim(time_type),' is not SERIAL,CYCLICAL, or FIXED'
         115           0 :        call endrun('flbc_inti: invalid time type ')
         116             :     end if
         117             :
         118        1536 :     if ( (flbc_timing%cycle_yr>0) .and. (time_type/='CYCLICAL') ) then
         119           0 :        call endrun('flbc_inti: cannot specify  flbc_cycle_yr if flbc_type is not CYCLICAL')
         120             :     endif
         121        1536 :     if ( ((flbc_timing%fixed_ymd>0).or.(flbc_timing%fixed_tod>0)).and.(time_type/='FIXED') ) then
         122           0 :        call endrun('flbc_inti: cannot specify  flbc_fixed_ymd or flbc_fixed_tod if flbc_type is not FIXED')
         123             :     endif
         124             :
         125        1536 :     wrk_sec  = ncsec
         126        1536 :     if( time_type == 'SERIAL' ) then
         127        1536 :        wrk_date = ncdate
         128           0 :     else if( time_type == 'CYCLICAL' ) then
         129             :
         130             :         ! If this is a leap-day, we have to avoid asking for a non-leap-year
         131             :         ! on a cyclical dataset. When this happens, just use Feb 28 instead
         132           0 :         if (( mon .eq. 2 ) .and. ( day.eq.29 )) then
         133           0 :            ncdate = yr*10000 + mon*100 + (day-1)
         134           0 :            write(iulog,*)'WARNING: flbc_inti using Feb 28 instead of Feb 29 for cyclical dataset'
         135             :         endif
         136           0 :        wrk_date = flbc_timing%cycle_yr*10000 + mod(ncdate,10000)
         137             :     else
         138           0 :        wrk_date = flbc_timing%fixed_ymd
         139           0 :        wrk_sec  = flbc_timing%fixed_tod
         140             :     end if
         141        1536 :     wrk_time = flt_date( wrk_date, wrk_sec )
         142        1536 :     if (masterproc) write(iulog,*) 'flbc_inti: wrk_date,wrk_sec,wrk_time = ',wrk_date,wrk_sec,wrk_time
         143             :
         144             :     !-----------------------------------------------------------------------
         145             :     !   ... species with fixed lbc ?
         146             :     !-----------------------------------------------------------------------
         147        1536 :     has_flbc(:) = .false.
         148        1536 :     flbc_cnt = 0
         149             :
         150       10752 :     do m = 1,max_nflbc
         151             :
         152       10752 :        if ( len_trim(flbc_list(m))==0 ) exit
         153             :
         154        9216 :        flbc_cnt = flbc_cnt + 1
         155             :
         156        9216 :        call cnst_get_ind (flbc_list(m), n, abort=.false.)
         157             :
         158        9216 :        if (n > 0) then
         159        7680 :           has_flbc(n) = .true.
         160        7680 :           flbcs(flbc_cnt)%spc_ndx = n
         161             :        else ! must be one of the GHGs which is not prognosted
         162        9216 :           if( .not. any( ghg_names(:) == flbc_list(m) ) ) then
         163           0 :              call endrun('flbc_inti: flbc_list member '// trim(flbc_list(m)) //' is not allowed')
         164             :           endif
         165        1536 :           flbcs(flbc_cnt)%spc_ndx = -1
         166             :        endif
         167             :
         168        9216 :        flbcs(flbc_cnt)%species = trim( flbc_list(m) )
         169             :
         170       64512 :        where( ghg_names(:) == flbc_list(m) )
         171             :           ghg_indices = m
         172             :        endwhere
         173             :
         174        9216 :        if( trim(flbcs(flbc_cnt)%species) == 'CFC11' ) then
         175        1536 :           flbcs(flbc_cnt)%species = 'CFCL3'
         176        7680 :        elseif( trim(flbcs(flbc_cnt)%species) == 'CFC12' ) then
         177        1536 :           flbcs(flbc_cnt)%species = 'CF2CL2'
         178             :        endif
         179             :
         180       10752 :        if ( trim(flbc_list(m)) .eq. trim(ghg_names(f11eq_ndx)) ) then
         181        1536 :           flbc_has_cfc11eq = .true.
         182             :        endif
         183             :
         184             :     enddo
         185             :
         186             :     ! check that user has not set vmr namelist values...
         187        1536 :     if ( ghg_indices(co2_ndx) > 0 .and. co2vmr>1.e-6_r8) then
         188           0 :        call endrun('flbc_inti: cannot specify both co2vmr and CO2 in flbc_file')
         189             :     endif
         190        1536 :     if ( ghg_indices(ch4_ndx) > 0 .and. ch4vmr > 0._r8) then
         191           0 :        call endrun('flbc_inti: cannot specify both ch4vmr and CH4 in flbc_file')
         192             :     endif
         193        1536 :     if ( ghg_indices(n2o_ndx) > 0 .and. n2ovmr > 0._r8) then
         194           0 :        call endrun('flbc_inti: cannot specify both n2ovmr and N2O in flbc_file')
         195             :     endif
         196        1536 :     if ( ghg_indices(f11_ndx) > 0 .and. f11vmr > 0._r8) then
         197           0 :        call endrun('flbc_inti: cannot specify both f11vmr and CFC11 in flbc_file')
         198             :     endif
         199        1536 :     if ( ghg_indices(f12_ndx) > 0 .and. f12vmr > 0._r8) then
         200           0 :        call endrun('flbc_inti: cannot specify both f12vmr and CFC12 in flbc_file')
         201             :     endif
         202             :
         203        1536 :     if( flbc_cnt == 0 ) then
         204             :        return
         205             :     end if
         206             :
         207        1536 :     if(masterproc) then
         208           2 :        write(iulog,*) ' '
         209           2 :        if( flbc_cnt > 0 ) then
         210           2 :           write(iulog,*) 'flbc_inti: Species with specified lower boundary values'
         211          14 :           do n = 1,flbc_cnt
         212          14 :              write(iulog,*) trim(flbcs(n)%species)
         213             :           enddo
         214             :        else
         215           0 :           write(iulog,*) 'There are no species with specified lower boundary values'
         216             :        end if
         217           2 :        write(iulog,*) ' '
         218             :
         219             :        !-----------------------------------------------------------------------
         220             :        !        ... diagnostics
         221             :        !-----------------------------------------------------------------------
         222           2 :        write(iulog,*) ' '
         223           2 :        write(iulog,*) 'flbc_inti: diagnostics'
         224           2 :        write(iulog,*) ' '
         225           2 :        write(iulog,*) 'lower bndy timing specs'
         226           2 :        write(iulog,*) 'type = ',flbc_timing%type
         227           2 :        if( time_type == 'CYCLICAL' ) then
         228           0 :           write(iulog,*) 'cycle year = ',flbc_timing%cycle_yr
         229             :        else
         230           2 :           write(iulog,*) 'fixed date = ',flbc_timing%fixed_ymd
         231           2 :           write(iulog,*) 'fixed time = ',flbc_timing%fixed_tod
         232             :        end if
         233           2 :        write(iulog,*) ' '
         234           2 :        write(iulog,*) 'there are ',flbc_cnt,' species with specified lower bndy values'
         235           2 :        write(iulog,*) ' '
         236             :     end if
         237             :     !-----------------------------------------------------------------------
         238             :     !   ... get timing information, allocate arrays, and read in dates
         239             :     !-----------------------------------------------------------------------
         240        1536 :     call getfil ( flbc_file, filename, 0)
         241        1536 :     call cam_pio_openfile (ncid, trim(filename), PIO_NOWRITE)
         242        1536 :     ierr = pio_inq_dimid( ncid, 'time', dimid )
         243        1536 :     ierr = pio_inq_dimlen( ncid, dimid, ntimes )
         244             :
         245        4608 :     allocate( dates(ntimes),stat=astat )
         246        1536 :     if( astat/= 0 ) then
         247           0 :        write(iulog,*) 'flbc_inti: failed to allocate dates array; error = ',astat
         248           0 :        call endrun
         249             :     end if
         250        4608 :     allocate( times(ntimes),stat=astat )
         251        1536 :     if( astat/= 0 ) then
         252           0 :        write(iulog,*) 'flbc_inti: failed to allocate times array; error = ',astat
         253           0 :        call endrun
         254             :     end if
         255             :
         256        1536 :     ierr = pio_inq_varid( ncid, 'date', varid )
         257        1536 :     ierr = pio_get_var( ncid, varid, dates )
         258             :
         259     4887552 :     do n = 1,ntimes
         260     4887552 :        times(n) = flt_date( dates(n), 0 )
         261             :     end do
         262        1536 :     if( time_type /= 'CYCLICAL' ) then
         263        1536 :        if( wrk_time < times(1) .or. wrk_time > times(ntimes) ) then
         264           0 :           write(iulog,*) 'flbc_inti: time out of bounds for dataset = ',trim(filename)
         265           0 :           call endrun
         266             :        end if
         267     4220928 :        do n = 2,ntimes
         268     4220928 :           if( wrk_time <= times(n) ) then
         269             :              exit
         270             :           end if
         271             :        end do
         272        1536 :        tim_ndx(1) = n - 1
         273             :     else
         274           0 :        yr = flbc_timing%cycle_yr
         275           0 :        do n = 1,ntimes
         276           0 :           if( yr == dates(n)/10000 ) then
         277             :              exit
         278             :           end if
         279             :        end do
         280           0 :        if( n >= ntimes ) then
         281           0 :           write(iulog,*) 'flbc_inti: time out of bounds for dataset = ',trim(filename)
         282           0 :           call endrun
         283             :        end if
         284           0 :        tim_ndx(1) = n
         285             :     end if
         286           0 :     select case( time_type )
         287             :     case( 'FIXED' )
         288           0 :        tim_ndx(2) = n
         289             :     case( 'CYCLICAL' )
         290           0 :        do n = tim_ndx(1),ntimes
         291           0 :           if( yr /= dates(n)/10000 ) then
         292             :              exit
         293             :           end if
         294             :        end do
         295           0 :        tim_ndx(2) = n - 1
         296           0 :        if( (tim_ndx(2) - tim_ndx(1)) < 2 ) then
         297           0 :           write(iulog,*) 'flbc_inti: cyclical lb conds require at least two time points'
         298           0 :           call endrun
         299             :        end if
         300             :     case( 'SERIAL' )
         301        1536 :        tim_ndx(2) = min( ntimes,tim_ndx(1) + time_span )
         302             :     end select
         303        1536 :     t1 = tim_ndx(1)
         304        1536 :     t2 = tim_ndx(2)
         305             :
         306             :     if( masterproc .and. debug ) then
         307             :        write(iulog,*) ' '
         308             :        write(iulog,*) 'flbc time cnt = ',ntimes
         309             :        write(iulog,*) 'flbc times'
         310             :        write(iulog,'(10i10)') dates(:)
         311             :        write(iulog,'(1p,5g15.7)') times(:)
         312             :        write(iulog,*) 'flbc time indicies = ',tim_ndx(:)
         313             :        write(iulog,'(10i10)') dates(tim_ndx(1):tim_ndx(2))
         314             :        write(iulog,*) ' '
         315             :     endif
         316             :
         317       10752 :     do m = 1,flbc_cnt
         318             :        !-----------------------------------------------------------------------
         319             :        !        ... allocate array
         320             :        !-----------------------------------------------------------------------
         321       36864 :        allocate( flbcs(m)%vmr(pcols,begchunk:endchunk,t1:t2),stat=astat )
         322        9216 :        if( astat/= 0 ) then
         323           0 :           write(iulog,*) 'flbc_inti: failed to allocate lbc vmr; error = ',astat
         324           0 :           call endrun
         325             :        end if
         326        9216 :        flbcs(m)%has_mean = file_has_gmean(ncid,flbcs(m)%species)
         327        9216 :        if ( flbcs(m)%has_mean) then
         328           0 :           allocate( flbcs(m)%vmr_mean(t1:t2),stat=astat )
         329           0 :           if( astat/= 0 ) then
         330           0 :              write(iulog,*) 'flbc_inti: failed to allocate lbc vmr_mean; error = ',astat
         331           0 :              call endrun
         332             :           end if
         333             :        endif
         334             :        !-----------------------------------------------------------------------
         335             :        !        ... readin the flbc vmr
         336             :        !-----------------------------------------------------------------------
         337       10752 :        call flbc_get( ncid, flbcs(m), .true., read_gmean=flbcs(m)%has_mean )
         338             :     end do
         339             :
         340             :     !-----------------------------------------------------------------------
         341             :     !   ... close the file
         342             :     !-----------------------------------------------------------------------
         343        1536 :     call pio_closefile( ncid )
         344             :
         345        3072 :   end subroutine flbc_inti
         346             :
         347      743424 :   subroutine flbc_chk( )
         348        1536 :     use cam_pio_utils, only : cam_pio_openfile
         349             :     use pio,           only : file_desc_t, pio_closefile, pio_nowrite
         350             :     !-----------------------------------------------------------------------
         351             :     !       ... check serial case for time span
         352             :     !-----------------------------------------------------------------------
         353             :
         354             :     implicit none
         355             :
         356             :     !-----------------------------------------------------------------------
         357             :     !       ... dummy arguments
         358             :     !-----------------------------------------------------------------------
         359             :
         360             :     !-----------------------------------------------------------------------
         361             :     !       ... local variables
         362             :     !-----------------------------------------------------------------------
         363             :     integer                     :: m
         364             :     integer                     :: t1, t2, tcnt
         365             :     integer                     :: astat
         366             :     type(file_desc_t)           :: ncid
         367             :     real(r8)                        :: wrk_time
         368             :     integer ::  yr, mon, day
         369             :
         370      743424 :     call get_curr_date( yr, mon, day, ncsec )
         371      743424 :     ncdate = yr*10000 + mon*100 + day
         372             :
         373      743424 :     if( flbc_cnt > 0 .and. flbc_timing%type == 'SERIAL' ) then
         374      743424 :        wrk_time = flt_date( ncdate, ncsec )
         375      743424 :        if( wrk_time > times(tim_ndx(2)) ) then
         376           0 :           tcnt = tim_ndx(2) - tim_ndx(1)
         377           0 :           tim_ndx(1) = tim_ndx(2)
         378           0 :           tim_ndx(2) = min( ntimes,tim_ndx(1) + time_span )
         379           0 :           t1 = tim_ndx(1)
         380           0 :           t2 = tim_ndx(2)
         381             : !!$          if( tcnt /= (t2 - t1) ) then
         382             :           !-----------------------------------------------------------------------
         383             :           !     ... allocate array
         384             :           !-----------------------------------------------------------------------
         385           0 :           do m = 1,flbc_cnt
         386           0 :              if( associated( flbcs(m)%vmr ) ) then
         387           0 :                 deallocate( flbcs(m)%vmr,stat=astat )
         388             :                 if( astat/= 0 ) then
         389             :                    write(iulog,*) 'flbc_chk: failed to deallocate flbc vmr; error = ',astat
         390             :                    call endrun
         391             :                 end if
         392             :              end if
         393           0 :              allocate( flbcs(m)%vmr(pcols,begchunk:endchunk,t1:t2),stat=astat )
         394           0 :              if( astat/= 0 ) then
         395           0 :                 write(iulog,*) 'flbc_chk: failed to allocate flbc vmr; error = ',astat
         396           0 :                 call endrun
         397             :              end if
         398             :
         399           0 :              if (flbcs(m)%has_mean) then
         400           0 :                 if( associated( flbcs(m)%vmr_mean ) ) then
         401           0 :                    deallocate( flbcs(m)%vmr_mean,stat=astat )
         402             :                    if( astat/= 0 ) then
         403             :                       write(iulog,*) 'flbc_chk: failed to deallocate flbc vmr; error = ',astat
         404             :                       call endrun
         405             :                    end if
         406             :                 end if
         407           0 :                 allocate( flbcs(m)%vmr_mean(t1:t2),stat=astat )
         408           0 :                 if( astat/= 0 ) then
         409           0 :                    write(iulog,*) 'flbc_chk: failed to allocate flbc vmr; error = ',astat
         410           0 :                    call endrun
         411             :                 end if
         412             :
         413             :              endif
         414             :           end do
         415             : !!$          end if
         416             :
         417           0 :           call cam_pio_openfile (ncid, trim(filename), PIO_NOWRITE)
         418             :           !-----------------------------------------------------------------------
         419             :           !     ... readin the lb concentrations
         420             :           !-----------------------------------------------------------------------
         421           0 :           do m = 1,flbc_cnt
         422           0 :              call flbc_get( ncid, flbcs(m), .true., read_gmean=flbcs(m)%has_mean )
         423             :           end do
         424             :
         425             :           !-----------------------------------------------------------------------
         426             :           !     ... close the file
         427             :           !-----------------------------------------------------------------------
         428           0 :           call pio_closefile( ncid )
         429             :
         430             :        end if
         431             :     end if
         432             :
         433     1486848 :   end subroutine flbc_chk
         434             :
         435             :   ! checks for global mean in input file
         436        9216 :   function file_has_gmean(ncid,species)
         437      743424 :     use pio, only : file_desc_t, pio_inq_varid, pio_noerr, pio_seterrorhandling, &
         438             :          pio_bcast_error, pio_internal_error
         439             :     implicit none
         440             :
         441             :     type(file_desc_t),      intent(inout) :: ncid
         442             :     character(*), intent(in) :: species
         443             :     logical :: file_has_gmean
         444             :
         445             :     integer :: varid, ierr
         446             :
         447             :     ! Allow pio to return the potential error and handle it locally
         448        9216 :     call pio_seterrorhandling(ncid, PIO_BCAST_ERROR)
         449        9216 :     ierr = pio_inq_varid( ncid, trim(species)//'_LBC_mean', varid)
         450        9216 :     call pio_seterrorhandling(ncid, PIO_INTERNAL_ERROR)
         451             :
         452             :
         453        9216 :     file_has_gmean = (ierr==PIO_NOERR)
         454             :
         455        9216 :   endfunction file_has_gmean
         456             :
         457        9216 :   subroutine flbc_get( ncid, lbcs, initial, read_gmean )
         458             :     !-----------------------------------------------------------------------
         459             :     !       ... read lower bndy values
         460             :     !-----------------------------------------------------------------------
         461             :     use mo_constants,  only : d2r, pi
         462             :     use phys_grid,     only: get_ncols_p, get_rlat_all_p, get_rlon_all_p
         463             :     use pio,           only: file_desc_t, pio_get_var, pio_inq_varndims
         464             :     use pio,           only: pio_max_name, pio_inq_varid, pio_inq_dimlen, pio_inq_dimid
         465             :     use pio,           only: pio_seterrorhandling, PIO_BCAST_ERROR, PIO_INTERNAL_ERROR, PIO_NOERR
         466             :     use interpolate_data, only : interp_type, lininterp_init, lininterp_finish, lininterp
         467             :
         468             :     implicit none
         469             :
         470             :     !-----------------------------------------------------------------------
         471             :     !       ... dummy arguments
         472             :     !-----------------------------------------------------------------------
         473             :     type(file_desc_t), intent(inout) :: ncid
         474             :     logical, intent(in)           :: initial
         475             :     type(flbc), intent(inout) :: lbcs
         476             :
         477             :     logical, intent(in), optional :: read_gmean
         478             :
         479             :     !-----------------------------------------------------------------------
         480             :     !       ... local variables
         481             :     !-----------------------------------------------------------------------
         482             :     integer                     :: j, m               ! Indices
         483             :     integer                     :: t1, t2, tcnt
         484             :     integer                     :: ierr
         485             :     integer                     :: vid, nlat, nlon
         486             :     integer                     :: dimid_lat, dimid_lon
         487        9216 :     real(r8), allocatable           :: lat(:)
         488        9216 :     real(r8), allocatable           :: lon(:)
         489        9216 :     real(r8), allocatable           :: wrk(:,:,:), wrk_zonal(:,:)
         490             :     character(len=pio_max_name)  :: varname
         491        9216 :     real(r8), allocatable       :: locl_vmr(:,:,:)
         492             :     integer :: ndims, t, c, ncols
         493             :     type(interp_type) :: lon_wgts, lat_wgts
         494             :     real(r8) :: to_lats(pcols), to_lons(pcols)
         495             :     real(r8), parameter :: twopi=2._r8*pi, zero=0._r8
         496             :
         497        9216 :     t1 = tim_ndx(1)
         498        9216 :     t2 = tim_ndx(2)
         499        9216 :     tcnt = t2 - t1 + 1
         500       36864 :     allocate( locl_vmr(pcols,begchunk:endchunk,tcnt), stat=ierr )
         501        9216 :     if( ierr /= 0 ) then
         502           0 :        write(iulog,*) 'srf_emis_get: locl_emis allocation error = ',ierr
         503           0 :        call endrun
         504             :     end if
         505             :
         506     1290816 :     locl_vmr(:,:,:) = 0._r8
         507             :
         508        9216 :     initialization : if( initial ) then
         509             :        !-----------------------------------------------------------------------
         510             :        !       ... get grid dimensions from file
         511             :        !-----------------------------------------------------------------------
         512             :        !           latitudes
         513             :        !-----------------------------------------------------------------------
         514        9216 :        ierr = pio_inq_dimid( ncid, 'lat', dimid_lat )
         515        9216 :        ierr = pio_inq_dimlen( ncid, dimid_lat, nlat )
         516       27648 :        allocate( lat(nlat),stat=ierr )
         517        9216 :        if( ierr /= 0 ) then
         518           0 :           write(iulog,*) 'flbc_get: lat allocation error = ',ierr
         519           0 :           call endrun
         520             :        end if
         521        9216 :        ierr = pio_inq_varid( ncid, 'lat', vid )
         522        9216 :        ierr = pio_get_var( ncid, vid, lat )
         523     3336192 :        lat(:nlat) = lat(:nlat) * d2r
         524             :
         525             :        !-----------------------------------------------------------------------
         526             :        !           longitudes
         527             :        !-----------------------------------------------------------------------
         528        9216 :        call pio_seterrorhandling( ncid, PIO_BCAST_ERROR )
         529        9216 :        ierr = pio_inq_dimid( ncid, 'lon', dimid_lon )
         530        9216 :        call pio_seterrorhandling( ncid, PIO_INTERNAL_ERROR )
         531        9216 :        if (ierr == PIO_NOERR ) then
         532        9216 :           ierr = pio_inq_dimlen( ncid, dimid_lon, nlon )
         533       27648 :           allocate( lon(nlon),stat=ierr )
         534        9216 :           if( ierr /= 0 ) then
         535           0 :              write(iulog,*) 'flbc_get: lon allocation error = ',ierr
         536           0 :              call endrun
         537             :           end if
         538        9216 :           ierr = pio_inq_varid( ncid, 'lon', vid )
         539        9216 :           ierr = pio_get_var( ncid, vid, lon )
         540     2672640 :           lon(:nlon) = lon(:nlon) * d2r
         541             :        endif
         542             :     end if initialization
         543             :
         544             :     !-----------------------------------------------------------------------
         545             :     !       ... read data
         546             :     !-----------------------------------------------------------------------
         547        9216 :     varname = trim(lbcs%species) // '_LBC'
         548        9216 :     ierr = pio_inq_varid( ncid, trim(varname), vid )
         549        9216 :     ierr = pio_inq_varndims (ncid, vid, ndims)
         550             :
         551        9216 :     if (ndims==2) then
         552       36864 :        allocate( wrk_zonal(nlat,tcnt), stat=ierr )
         553        9216 :        if( ierr /= 0 ) then
         554           0 :           write(iulog,*) 'flbc_get: wrk_zonal allocation error = ',ierr
         555           0 :           call endrun
         556             :        end if
         557             :     else
         558           0 :        allocate( wrk(nlon,nlat,tcnt), stat=ierr )
         559           0 :        if( ierr /= 0 ) then
         560           0 :           write(iulog,*) 'flbc_get: wrk allocation error = ',ierr
         561           0 :           call endrun
         562             :        end if
         563             :     endif
         564             :
         565        9216 :     if (ndims==2) then
         566             :        ierr = pio_get_var( ncid, vid, (/ 1, t1/), &
         567       46080 :             (/ nlat, tcnt /), wrk_zonal )
         568             :     else
         569             :        ierr = pio_get_var( ncid, vid, (/ 1, 1, t1/), &
         570           0 :             (/ nlon, nlat, tcnt /), wrk )
         571             :     endif
         572             :
         573       46368 :     do c=begchunk,endchunk
         574       37152 :        ncols = get_ncols_p(c)
         575       37152 :        call get_rlat_all_p(c, pcols, to_lats)
         576       37152 :        call get_rlon_all_p(c, pcols, to_lons)
         577             :
         578       37152 :        call lininterp_init(lat, nlat, to_lats, ncols, 1, lat_wgts)
         579       37152 :        if (ndims==2) then
         580      111456 :          do m = 1,tcnt
         581      111456 :              call lininterp(wrk_zonal(:,m), nlat, locl_vmr(:,c,m), ncols, lat_wgts)
         582             :           end do
         583             :        else
         584           0 :           call lininterp_init(lon, nlon, to_lons, ncols, 2, lon_wgts, zero, twopi)
         585             :
         586           0 :           do m = 1,tcnt
         587           0 :              call lininterp(wrk(:,:,m), nlon, nlat, locl_vmr(:,c,m), ncols, lon_wgts, lat_wgts)
         588             :           end do
         589             :
         590             :
         591           0 :           call lininterp_finish(lon_wgts)
         592             :        end if
         593       46368 :        call lininterp_finish(lat_wgts)
         594             :
         595             :     end do
         596             :
         597        9216 :     if (ndims==2) then
         598        9216 :        deallocate( wrk_zonal,stat=ierr )
         599        9216 :        if( ierr /= 0 ) then
         600           0 :           write(iulog,*) 'flbc_get: Failed to deallocate wrk_zonal, ierr = ',ierr
         601           0 :           call endrun
         602             :        end if
         603             :     else
         604           0 :        deallocate(wrk, stat=ierr)
         605           0 :        if( ierr /= 0 ) then
         606           0 :           write(iulog,*) 'flbc_get: Failed to deallocate wrk, ierr = ',ierr
         607           0 :           call endrun
         608             :        end if
         609             :     end if
         610        9216 :     if (read_gmean) then
         611           0 :        varname = trim(lbcs%species) // '_LBC_mean'
         612           0 :        ierr = pio_inq_varid( ncid, trim(varname), vid )
         613           0 :        ierr = pio_get_var( ncid, vid, (/t1/), (/tcnt/), lbcs%vmr_mean(t1:t2) )
         614             :     endif
         615             :
         616             :
         617       27648 :     do m = t1,t2
         618     1290816 :        lbcs%vmr(:,:,m) = locl_vmr(:,:,m-t1+1)
         619             :     enddo
         620             :
         621        9216 :     deallocate(locl_vmr, stat=ierr )
         622        9216 :     if( ierr /= 0 ) then
         623           0 :        write(iulog,*) 'flbc_get: Failed to deallocate locl_vmr; ierr = ',ierr
         624           0 :        call endrun
         625             :     end if
         626             :
         627        9216 :   end subroutine flbc_get
         628             :
         629     1489176 :   subroutine flbc_set( vmr, ncol, lchnk, map )
         630             :     !--------------------------------------------------------
         631             :     !   ... set the lower bndy values
         632             :     !--------------------------------------------------------
         633             :
         634             :     implicit none
         635             :
         636             :     !--------------------------------------------------------
         637             :     !   ... dummy arguments
         638             :     !--------------------------------------------------------
         639             :     integer,  intent(in)    ::   ncol
         640             :     integer,  intent(in)    ::   lchnk
         641             :     integer,  intent(in)    ::   map(:)
         642             :     real(r8), intent(inout) ::   vmr(:,:,:)    ! lower bndy concentrations( mol/mol )
         643             :
         644             :     !--------------------------------------------------------
         645             :     !   ... local variables
         646             :     !--------------------------------------------------------
         647             :     integer  :: m, n
         648             :     integer  :: last, next
         649             :     real(r8) :: dels
         650             :
         651     1489176 :     if( flbc_cnt < 1 ) then
         652           0 :        return
         653             :     end if
         654             :
         655     1489176 :     call get_dels( dels, last, next )
         656             :
         657    10424232 :     do m = 1,flbc_cnt
         658    10424232 :        if ( flbcs(m)%spc_ndx > 0 ) then
         659     7445880 :           n = map( flbcs(m)%spc_ndx )
         660             :           ! If the GHG happens to be an advected specie, but not a chemical specie
         661             :           ! (e.g., CO2 when the carbon cycle is on in standard CAM), then n=0 and
         662             :           ! we need to skip setting the LBC.
         663     7445880 :           if (n > 0) then
         664    14891760 :              vmr(:ncol,pver,n) = flbcs(m)%vmr(:ncol,lchnk,last) &
         665   139220640 :                 + dels * (flbcs(m)%vmr(:ncol,lchnk,next) - flbcs(m)%vmr(:ncol,lchnk,last))
         666             :           end if
         667             :        endif
         668             :     end do
         669             :
         670        9216 :   end subroutine flbc_set
         671             :
         672     1495368 :   subroutine flbc_get_cfc11eq( lbc_vmr, ncol, lchnk )
         673             :
         674             :     !--------------------------------------------------------
         675             :     ! return the lower of cfclleq
         676             :     !--------------------------------------------------------
         677             :
         678             :     !--------------------------------------------------------
         679             :     ! dummy arguments
         680             :     !--------------------------------------------------------
         681             :     integer,  intent(in)  ::   ncol
         682             :     integer,  intent(in)  ::   lchnk
         683             :     real(r8), intent(out) ::   lbc_vmr(:)    ! lower bndy concentrations( mol/mol )
         684             :
         685             :     !--------------------------------------------------------
         686             :     !   ... local variables
         687             :     !--------------------------------------------------------
         688             :     integer  :: m, last, next
         689             :     real(r8) :: dels
         690             :
         691    25421256 :     lbc_vmr(:) = 0._r8
         692             :
         693     1495368 :     if (flbc_has_cfc11eq) then
         694     1495368 :        call get_dels( dels, last, next )
         695     1495368 :        m = ghg_indices(f11eq_ndx)
         696     2990736 :        lbc_vmr(:ncol) = flbcs(m)%vmr(:ncol,lchnk,last) &
         697    27959904 :             + dels * (flbcs(m)%vmr(:ncol,lchnk,next) - flbcs(m)%vmr(:ncol,lchnk,last))
         698             :     endif
         699             :
         700     1495368 :   end subroutine flbc_get_cfc11eq
         701             :
         702     3357024 :   subroutine get_dels( dels, last, next )
         703             :
         704             :     use intp_util, only: findplb
         705             :
         706             :     implicit none
         707             :
         708             :     real(r8), intent(out) :: dels
         709             :     integer,  intent(out) :: last
         710             :     integer,  intent(out) :: next
         711             :
         712             :     !--------------------------------------------------------
         713             :     !   ... local variables
         714             :     !--------------------------------------------------------
         715             :     integer  ::  wrk_date, wrk_sec
         716             :     integer  ::  tcnt, n
         717             :     real(r8)     ::  wrk_time
         718             :
         719             :     !--------------------------------------------------------
         720             :     !   ... setup the time interpolation
         721             :     !--------------------------------------------------------
         722     3357024 :     wrk_sec  = ncsec
         723     3357024 :     select case( flbc_timing%type )
         724             :     case( 'SERIAL' )
         725     3357024 :        wrk_date = ncdate
         726             :     case( 'CYCLICAL' )
         727           0 :        wrk_date = flbc_timing%cycle_yr*10000 + mod( ncdate,10000 )
         728             :     case( 'FIXED' )
         729           0 :        wrk_date = flbc_timing%fixed_ymd
         730     3357024 :        wrk_sec  = flbc_timing%fixed_tod
         731             :     end select
         732             :
         733     3357024 :     wrk_time = flt_date( wrk_date, wrk_sec )
         734             :
         735             :     !--------------------------------------------------------
         736             :     !   ... set time interpolation factor
         737             :     !--------------------------------------------------------
         738     3357024 :     if( flbc_timing%type /= 'CYCLICAL' ) then
         739     3357024 :        do n = tim_ndx(1)+1,tim_ndx(2)
         740     3357024 :           if( wrk_time <= times(n) ) then
         741     3357024 :              last = n - 1
         742     3357024 :              next = n
         743     3357024 :              exit
         744             :           end if
         745             :        end do
         746     3357024 :        if( n > ntimes ) then
         747           0 :           write(iulog,*) 'flbc_set: interp time is out of bounds'
         748           0 :           call endrun
         749             :        end if
         750     3357024 :        dels = (wrk_time - times(last))/(times(next) - times(last))
         751             :        !        write(iulog,*) ' '
         752             :        !        write(iulog,*) 'flbc_set: last,next,dels,ncdate,ncsec = ',last,next,dels,ncdate,ncsec
         753             :     else
         754           0 :        tcnt = tim_ndx(2) - tim_ndx(1) + 1
         755           0 :        call findplb( times(tim_ndx(1)), tcnt, wrk_time, n )
         756           0 :        if( n < tcnt ) then
         757           0 :           last = tim_ndx(1) + n - 1
         758           0 :           next = last + 1
         759           0 :           dels = (wrk_time - times(last))/(times(next) - times(last))
         760             :        else
         761           0 :           next = tim_ndx(1)
         762           0 :           last = tim_ndx(2)
         763           0 :           dels = wrk_time - times(last)
         764           0 :           if( dels < 0._r8 ) then
         765           0 :              dels = 365._r8 + dels
         766             :           end if
         767           0 :           dels = dels/(365._r8 + times(next) - times(last))
         768             :        end if
         769             :        !        write(iulog,*) ' '
         770             :        !        write(iulog,*) 'flbc_set: last,next,dels,ncdate,ncsec = ',last,next,dels,ncdate,ncsec
         771             :     end if
         772             :
         773     3357024 :     dels = max( min( 1._r8,dels ),0._r8 )
         774             :
         775     3357024 :   end subroutine get_dels
         776             :
         777      744960 :   subroutine flbc_gmean_vmr(co2vmr,ch4vmr,n2ovmr,f11vmr,f12vmr)
         778             :
         779             :      implicit none
         780             :
         781             :      real(r8), intent(inout) :: co2vmr
         782             :      real(r8), intent(inout) :: ch4vmr
         783             :      real(r8), intent(inout) :: n2ovmr
         784             :      real(r8), intent(inout) :: f11vmr
         785             :      real(r8), intent(inout) :: f12vmr
         786             :
         787             :      integer  :: last, next
         788             :      real(r8) :: dels
         789             :
         790      372480 :      if( flbc_cnt < 1 ) return
         791             :
         792      372480 :      call get_dels( dels, last, next )
         793             :
         794      372480 :      if (ghg_indices(co2_ndx)>0) &
         795      372480 :           co2vmr = global_mean_vmr(flbcs(ghg_indices(co2_ndx)), dels, last, next )
         796      372480 :      if (ghg_indices(ch4_ndx)>0) &
         797      372480 :           ch4vmr = global_mean_vmr(flbcs(ghg_indices(ch4_ndx)), dels, last, next )
         798      372480 :      if (ghg_indices(n2o_ndx)>0) &
         799      372480 :           n2ovmr = global_mean_vmr(flbcs(ghg_indices(n2o_ndx)), dels, last, next )
         800      372480 :      if (ghg_indices(f11_ndx)>0) then
         801      372480 :           f11vmr = global_mean_vmr(flbcs(ghg_indices(f11_ndx)), dels, last, next )
         802           0 :      elseif (ghg_indices(f11eq_ndx)>0) then
         803           0 :           f11vmr = global_mean_vmr(flbcs(ghg_indices(f11eq_ndx)), dels, last, next )
         804             :      endif
         805      372480 :      if (ghg_indices(f12_ndx)>0) &
         806      372480 :           f12vmr = global_mean_vmr(flbcs(ghg_indices(f12_ndx)), dels, last, next )
         807             :
         808             :   end subroutine flbc_gmean_vmr
         809             :
         810     1862400 :   function global_mean_vmr( flbcs, dels, last, next  )
         811             :     use gmean_mod,  only: gmean
         812             :     use phys_grid,  only: get_ncols_p
         813             :
         814             :     implicit none
         815             :
         816             :     type(flbc), intent(in) :: flbcs
         817             :     real(r8), intent(in) :: dels
         818             :     integer, intent(in) :: last
         819             :     integer, intent(in) :: next
         820             :     real(r8) :: global_mean_vmr
         821     3724800 :     real(r8) :: vmr_arr(pcols,begchunk:endchunk)
         822             :
         823             :     integer  :: lchnk, ncol !, n
         824             :
         825     1862400 :     if (flbcs%has_mean) then
         826           0 :        global_mean_vmr = flbcs%vmr_mean(last) &
         827           0 :             + dels * (flbcs%vmr_mean(next) - flbcs%vmr_mean(last))
         828             :     else
         829     9370200 :        do lchnk = begchunk, endchunk
         830     7507800 :           ncol = get_ncols_p(lchnk)
         831     7507800 :           vmr_arr(:ncol,lchnk) = flbcs%vmr(:ncol,lchnk,last) &
         832   134733000 :                + dels * (flbcs%vmr(:ncol,lchnk,next) - flbcs%vmr(:ncol,lchnk,last))
         833             :        enddo
         834     1862400 :        call gmean (vmr_arr, global_mean_vmr)
         835             :     endif
         836             :
         837     1862400 :   endfunction global_mean_vmr
         838             :
         839     1862400 : end module mo_flbc

Generated by: LCOV version 1.14