LCOV - code coverage report
Current view: | top level - dynamics/se - se_single_column_mod.F90 (source / functions) |  |  | Hit | Total | Coverage
Test: | coverage.info |  | Lines: | 0 | 177 | 0.0 %
Date: | 2024-12-17 22:39:59 |  | Functions: | 0 | 5 | 0.0 %

              Line data    Source code
           1             : module se_single_column_mod
           2             : !--------------------------------------------------------
           3             : !
           4             : ! Module for the SE single column model
           5             :
           6             : use shr_kind_mod,           only: r8=>shr_kind_r8
           7             : use element_mod,            only: element_t
           8             : use scamMod,                only: have_t, have_q, have_u, have_v, have_ps, have_numliq, &
           9             :                                   have_cldliq, have_numice, have_cldice, have_omega, use_camiop, &
          10             :                                   tobs, qobs,have_numliq, numliqobs, cldliqobs, numiceobs, cldiceobs, &
          11             :                                   wfld, psobs,uobs,vobs,tobs,divt,divQ,divT3d,divq3d,precobs,lhflxobs, &
          12             :                                   shflxobs, tground, have_ps, have_tg, have_lhflx, have_shflx, have_t, &
          13             :                                   have_omega, have_cldliq, have_divt, have_divq, have_divt3d, have_divq3d, &
          14             :                                   use_3dfrc,scmlat,scmlon
          15             : use constituents,           only: cnst_get_ind, pcnst
          16             : use dimensions_mod,         only: nelemd, np, nlev, qsize
          17             : use time_manager,           only: get_nstep, is_first_step, get_step_size, is_first_restart_step
          18             : use ppgrid,                 only: begchunk
          19             : use se_dyn_time_mod,        only: timelevel_qdp
          20             : use cam_history,            only: outfld
          21             :
          22             : implicit none
          23             :
          24             : private
          25             : save
          26             :
          27             : public scm_setinitial
          28             : public scm_setfield
          29             : public apply_SC_forcing
          30             : public iop_broadcast
          31             : public scm_dyn_grid_indicies
          32             :
          33             : integer, public :: indx_scm, ie_scm, i_scm, j_scm
          34             :
          35             : integer         :: tl_f, tl_fqdp, thelev
          36             :
          37             : !=========================================================================
          38             : contains
          39             : !=========================================================================
          40             :
          41           0 : subroutine scm_setinitial(elem)
          42             :
          43             :   use dyn_grid,     only: TimeLevel
          44             :   use control_mod,  only: qsplit
          45             :
          46             :   implicit none
          47             :
          48             :   type(element_t), intent(inout) :: elem(:)
          49             :
          50             :   integer              :: k
          51             :   integer              :: inumliq, inumice, icldliq, icldice
          52             :
          53           0 :   call scm_dyn_grid_indicies(elem,scmlat,scmlon,ie_scm,i_scm,j_scm,indx_scm)
          54             :
          55           0 :   tl_f = timelevel%n0
          56           0 :   call TimeLevel_Qdp(timelevel, qsplit, tl_fqdp)
          57             :
          58           0 :   if (.not. use_camiop .and. get_nstep()  ==  0) then
          59           0 :     call cnst_get_ind('NUMLIQ', inumliq, abort=.false.)
          60           0 :     call cnst_get_ind('NUMICE', inumice, abort=.false.)
          61           0 :     call cnst_get_ind('CLDLIQ', icldliq)
          62           0 :     call cnst_get_ind('CLDICE', icldice)
          63             :
          64             :     ! Find level where tobs is no longer zero
          65           0 :     thelev=minloc(abs(tobs), 1, mask=abs(tobs) > 0)
          66             :
          67           0 :     if (get_nstep()  <=  1) then
          68           0 :        do k=1,thelev-1
          69           0 :           tobs(k)=elem(ie_scm)%state%T(i_scm,j_scm,k,tl_f)
          70           0 :           qobs(k)=elem(ie_scm)%state%qdp(i_scm,j_scm,k,1,tl_fqdp)/elem(ie_scm)%state%dp3d(i_scm,j_scm,k,tl_f)
          71             :        enddo
          72             :     else
          73           0 :        tobs(:)=elem(ie_scm)%state%T(i_scm,j_scm,:,tl_f)
          74           0 :        qobs(:)=elem(ie_scm)%state%qdp(i_scm,j_scm,:,1,tl_fqdp)/elem(ie_scm)%state%dp3d(i_scm,j_scm,:,tl_f)
          75             :     endif
          76             :
          77           0 :     if (get_nstep()  ==  0) then
          78           0 :        do k=thelev, NLEV
          79           0 :           if (have_t) elem(ie_scm)%state%T(i_scm,j_scm,k,tl_f)=tobs(k)
          80           0 :           if (have_q) elem(ie_scm)%state%qdp(i_scm,j_scm,k,1,tl_fqdp)=qobs(k)*elem(ie_scm)%state%dp3d(i_scm,j_scm,k,tl_f)
          81             :        enddo
          82             :
          83           0 :        do k=1,NLEV
          84           0 :           if (have_ps) elem(ie_scm)%state%psdry(i_scm,j_scm) = psobs
          85           0 :           if (have_u) elem(ie_scm)%state%v(i_scm,j_scm,1,k,tl_f) = uobs(k)
          86           0 :           if (have_v) elem(ie_scm)%state%v(i_scm,j_scm,2,k,tl_f) = vobs(k)
          87           0 :           if (have_numliq) elem(ie_scm)%state%qdp(i_scm,j_scm,k,inumliq,tl_fqdp) = &
          88           0 :                numliqobs(k)*elem(ie_scm)%state%dp3d(i_scm,j_scm,k,tl_f)
          89           0 :           if (have_cldliq) elem(ie_scm)%state%qdp(i_scm,j_scm,k,icldliq,tl_fqdp) = &
          90           0 :                cldliqobs(k)*elem(ie_scm)%state%dp3d(i_scm,j_scm,k,tl_f)
          91           0 :           if (have_numice) elem(ie_scm)%state%qdp(i_scm,j_scm,k,inumice,tl_fqdp) = &
          92           0 :                numiceobs(k)*elem(ie_scm)%state%dp3d(i_scm,j_scm,k,tl_f)
          93           0 :           if (have_cldice) elem(ie_scm)%state%qdp(i_scm,j_scm,k,icldice,tl_fqdp) = &
          94           0 :                cldiceobs(k)*elem(ie_scm)%state%dp3d(i_scm,j_scm,k,tl_f)
          95           0 :           if (have_omega) elem(ie_scm)%derived%omega(i_scm,j_scm,k) = wfld(k)
          96             :        enddo
          97             :
          98             :     endif
          99             :
         100             :  endif
         101             :
         102           0 : end subroutine scm_setinitial
         103             :
         104           0 : subroutine scm_setfield(elem,iop_update_phase1)
         105             :
         106             : !---------------------------------------------------------
         107             : ! Purpose: Update various fields based on available data
         108             : !   provided by IOP file
         109             : !----------------------------------------------------------
         110             :
         111           0 :   use control_mod,  only: qsplit
         112             :   use dyn_grid,     only: TimeLevel
         113             :
         114             :   implicit none
         115             :
         116             :   logical, intent(in) :: iop_update_phase1
         117             :   type(element_t), intent(inout) :: elem(:)
         118             :
         119             :   integer              :: k
         120             :   integer              :: tl_f, tl_fqdp
         121             :
         122           0 :   tl_f = timelevel%n0
         123           0 :   call TimeLevel_Qdp(timelevel, qsplit, tl_fqdp)
         124             :
         125           0 :   if (have_ps .and. use_camiop .and. .not. iop_update_phase1) elem(ie_scm)%state%psdry(:,:) = psobs
         126           0 :   if (have_ps .and. .not. use_camiop) elem(ie_scm)%state%psdry(:,:) = psobs
         127           0 :   do k=1, NLEV
         128           0 :      if (have_omega .and. iop_update_phase1) elem(ie_scm)%derived%omega(:,:,k)=wfld(k)  !     set t to tobs at first
         129           0 :      if (k < thelev) then
         130           0 :         tobs(k) = elem(ie_scm)%state%T(i_scm,j_scm,k,tl_f)
         131           0 :         qobs(k) = elem(ie_scm)%state%qdp(i_scm,j_scm,k,1,tl_fqdp)/elem(ie_scm)%state%dp3d(i_scm,j_scm,k,tl_f)
         132           0 :         uobs(k) = elem(ie_scm)%state%v(i_scm,j_scm,1,k,tl_f)
         133           0 :         vobs(k) = elem(ie_scm)%state%v(i_scm,j_scm,2,k,tl_f)
         134             :      end if
         135             :   end do
         136             :
         137           0 : end subroutine scm_setfield
         138             :
         139           0 : subroutine apply_SC_forcing(elem,hvcoord,tl,n,t_before_advance)
         140             : !
         141           0 :     use scamMod,        only: single_column, use_3dfrc
         142             :     use hybvcoord_mod,  only: hvcoord_t
         143             :     use se_dyn_time_mod,only: TimeLevel_t
         144             :     use control_mod,    only: qsplit
         145             :     use apply_iop_forcing_mod, only:advance_iop_forcing, advance_iop_nudging
         146             :
         147             :     type (element_t), intent(inout), target :: elem(:)
         148             :     type (hvcoord_t), intent(in)            :: hvcoord
         149             :     type (TimeLevel_t), intent(in)          :: tl
         150             :     logical, intent(in)                     :: t_before_advance
         151             :     integer, intent(in)                     :: n
         152             :
         153             :     integer                                 :: k, m
         154             :     real (r8)                               :: dt
         155             :     logical                                 :: iop_nudge_tq = .false.
         156             :     real (r8), dimension(nlev,pcnst)        :: stateQ_in, q_update, q_phys_frc
         157             :     real (r8), dimension(nlev)              :: t_phys_frc, t_update, u_update, v_update
         158             :     real (r8), dimension(nlev)              :: t_in, u_in, v_in
         159             :     real (r8), dimension(nlev)              :: relaxt, relaxq
         160             :     real (r8), dimension(nlev)              :: tdiff_dyn, qdiff_dyn
         161             :
         162             : !-----------------------------------------------------------------------
         163             :
         164           0 :     tl_f = tl%n0
         165             :
         166           0 :     call TimeLevel_Qdp(tl, qsplit, tl_fqdp)
         167             :
         168           0 :     dt = get_step_size()
         169             :
         170             :     ! Set initial profiles for current column
         171           0 :     do m=1,pcnst
         172           0 :        stateQ_in(:nlev,m) = elem(ie_scm)%state%Qdp(i_scm,j_scm,:nlev,m,tl_fqdp)/elem(ie_scm)%state%dp3d(i_scm,j_scm,:nlev,tl_f)
         173             :     end do
         174           0 :     t_in(:nlev) = elem(ie_scm)%state%T(i_scm,j_scm,:nlev,tl_f)
         175           0 :     u_in(:nlev) = elem(ie_scm)%state%v(i_scm,j_scm,1,:nlev,tl_f)
         176           0 :     v_in(:nlev) = elem(ie_scm)%state%v(i_scm,j_scm,2,:nlev,tl_f)
         177             :
         178           0 :     t_phys_frc(:)   = elem(ie_scm)%derived%fT(i_scm,j_scm,:)
         179           0 :     q_phys_frc(:,:qsize) = elem(ie_scm)%derived%fQ(i_scm,j_scm,:,:qsize)/dt
         180             :
         181             :     ! Call the main subroutine to update t, q, u, and v according to
         182             :     !  large scale forcing as specified in IOP file.
         183             :     call advance_iop_forcing(dt,elem(ie_scm)%state%psdry(i_scm,j_scm),& ! In
         184             :          u_in,v_in,t_in,stateQ_in,t_phys_frc, q_phys_frc, hvcoord, &            ! In
         185           0 :          u_update,v_update,t_update,q_update)                      ! Out
         186             :
         187             :     ! Nudge to observations if desired, for T & Q only if in SCM mode
         188           0 :     if (iop_nudge_tq ) then
         189           0 :        call advance_iop_nudging(dt,elem(ie_scm)%state%psdry(i_scm,j_scm),& ! In
         190             :             t_update,q_update,u_update,v_update, hvcoord, &                ! Inout
         191           0 :             relaxt,relaxq)                                                 ! Out
         192             :     endif
         193             :
         194           0 :     if (use_3dfrc) then    ! vertical remap of dynamics not run need to update state%dp3d using new psdry
         195           0 :        do k=1,nlev
         196           0 :           elem(ie_scm)%state%dp3d(i_scm,j_scm,k,tl_f) = (hvcoord%hyai(k+1)-hvcoord%hyai(k))*hvcoord%ps0 + &
         197           0 :                (hvcoord%hybi(k+1)-hvcoord%hybi(k))*elem(ie_scm)%state%psdry(i_scm,j_scm)
         198             :        end do
         199             :     end if
         200             :
         201             :     ! Update qdp using new dp3d
         202           0 :     do m=1,pcnst
         203             :        ! Update the Qdp array
         204           0 :        elem(ie_scm)%state%Qdp(i_scm,j_scm,:nlev,m,tl_fqdp) = &
         205           0 :             q_update(:nlev,m) * elem(ie_scm)%state%dp3d(i_scm,j_scm,:nlev,tl_f)
         206             :     enddo
         207             :
         208             :     ! Update prognostic variables to the current values
         209           0 :     elem(ie_scm)%state%T(i_scm,j_scm,:,tl_f) = t_update(:)
         210           0 :     elem(ie_scm)%state%v(i_scm,j_scm,1,:,tl_f) = u_update(:)
         211           0 :     elem(ie_scm)%state%v(i_scm,j_scm,2,:,tl_f) = v_update(:)
         212             :
         213             :     ! Evaluate the differences in state information from observed
         214             :     !  (done for diganostic purposes only)
         215           0 :     do k = 1, nlev
         216           0 :        tdiff_dyn(k) = t_update(k)   - tobs(k)
         217           0 :        qdiff_dyn(k) = q_update(k,1) - qobs(k)
         218             :     end do
         219             :
         220             :     ! Add various diganostic outfld calls
         221           0 :     call outfld('TDIFF',tdiff_dyn,1,begchunk)
         222           0 :     call outfld('QDIFF',qdiff_dyn,1,begchunk)
         223           0 :     call outfld('TOBS',tobs,1,begchunk)
         224           0 :     call outfld('QOBS',qobs,1,begchunk)
         225           0 :     call outfld('DIVQ',divq,1,begchunk)
         226           0 :     call outfld('DIVT',divt,1,begchunk)
         227           0 :     call outfld('DIVQ3D',divq3d,1,begchunk)
         228           0 :     call outfld('DIVT3D',divt3d,1,begchunk)
         229           0 :     call outfld('PRECOBS',precobs,1,begchunk)
         230           0 :     call outfld('LHFLXOBS',lhflxobs,1,begchunk)
         231           0 :     call outfld('SHFLXOBS',shflxobs,1,begchunk)
         232             :
         233           0 :     call outfld('TRELAX',relaxt,1,begchunk)
         234           0 :     call outfld('QRELAX',relaxq,1,begchunk)
         235             :
         236             :
         237           0 :     end subroutine apply_SC_forcing
         238             : !=========================================================================
         239           0 :     subroutine iop_broadcast()
         240             :
         241             :       !---------------------------------------------------------
         242             :       ! Purpose: Broadcast relevant logical
         243             :       !   flags and data to all processors
         244             :       !----------------------------------------------------------
         245             :
         246           0 :       use spmd_utils,             only: mpi_logical, mpi_real8, masterproc, iam, mpicom, mstrid=>masterprocid
         247             :       use cam_abortutils,         only: endrun
         248             :
         249             :       integer :: ierr
         250             :       character(len=*), parameter :: sub = 'radiation_readnl'
         251             :
         252             : #ifdef SPMD
         253           0 :       call mpi_bcast(have_ps,1,mpi_logical,mstrid,mpicom,ierr)
         254           0 :       if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: have_ps")
         255           0 :       call mpi_bcast(have_tg,1,mpi_logical,mstrid,mpicom,ierr)
         256           0 :       if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: have_tg")
         257           0 :       call mpi_bcast(have_lhflx,1,mpi_logical,mstrid,mpicom,ierr)
         258           0 :       if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: have_lhflx")
         259           0 :       call mpi_bcast(have_shflx,1,mpi_logical,mstrid,mpicom,ierr)
         260           0 :       if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: have_shflx")
         261           0 :       call mpi_bcast(have_t,1,mpi_logical,mstrid,mpicom,ierr)
         262           0 :       if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: have_t")
         263           0 :       call mpi_bcast(have_q,1,mpi_logical,mstrid,mpicom,ierr)
         264           0 :       if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: have_q")
         265           0 :       call mpi_bcast(have_u,1,mpi_logical,mstrid,mpicom,ierr)
         266           0 :       if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: have_u")
         267           0 :       call mpi_bcast(have_v,1,mpi_logical,mstrid,mpicom,ierr)
         268           0 :       if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: have_v")
         269           0 :       call mpi_bcast(have_omega,1,mpi_logical,mstrid,mpicom,ierr)
         270           0 :       if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: have_omega")
         271           0 :       call mpi_bcast(have_cldliq,1,mpi_logical,mstrid,mpicom,ierr)
         272           0 :       if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: have_cldliq")
         273           0 :       call mpi_bcast(have_divt,1,mpi_logical,mstrid,mpicom,ierr)
         274           0 :       if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: have_divt")
         275           0 :       call mpi_bcast(have_divq,1,mpi_logical,mstrid,mpicom,ierr)
         276           0 :       if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: have_divq")
         277           0 :       call mpi_bcast(have_divt3d,1,mpi_logical,mstrid,mpicom,ierr)
         278           0 :       if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: have_divt3d")
         279           0 :       call mpi_bcast(have_divq3d,1,mpi_logical,mstrid,mpicom,ierr)
         280           0 :       if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: have_divq3d")
         281           0 :       call mpi_bcast(use_3dfrc,1,mpi_logical,mstrid,mpicom,ierr)
         282           0 :       if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: use_3dfrc")
         283             :
         284           0 :       call mpi_bcast(psobs,1,mpi_real8,mstrid,mpicom,ierr)
         285           0 :       if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: psobs")
         286           0 :       call mpi_bcast(tground,1,mpi_real8,mstrid,mpicom,ierr)
         287           0 :       if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: tground")
         288           0 :       call mpi_bcast(lhflxobs,1,mpi_real8,mstrid,mpicom,ierr)
         289           0 :       if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: lhflxobs")
         290           0 :       call mpi_bcast(shflxobs,1,mpi_real8,mstrid,mpicom,ierr)
         291           0 :       if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: shflxobs")
         292             :
         293           0 :       call mpi_bcast(tobs,nlev,mpi_real8,mstrid,mpicom,ierr)
         294           0 :       if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: tobs")
         295           0 :       call mpi_bcast(qobs,nlev,mpi_real8,mstrid,mpicom,ierr)
         296           0 :       if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: qobs")
         297           0 :       call mpi_bcast(uobs,nlev,mpi_real8,mstrid,mpicom,ierr)
         298           0 :       if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: uobs")
         299           0 :       call mpi_bcast(vobs,nlev,mpi_real8,mstrid,mpicom,ierr)
         300           0 :       if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: vobs")
         301           0 :       call mpi_bcast(cldliqobs,nlev,mpi_real8,mstrid,mpicom,ierr)
         302           0 :       if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: cldliqobs")
         303           0 :       call mpi_bcast(wfld,nlev,mpi_real8,mstrid,mpicom,ierr)
         304           0 :       if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: wfld")
         305             :
         306           0 :       call mpi_bcast(divt,nlev,mpi_real8,mstrid,mpicom,ierr)
         307           0 :       if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: divt")
         308           0 :       call mpi_bcast(divq,nlev,mpi_real8,mstrid,mpicom,ierr)
         309           0 :       if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: divq")
         310           0 :       call mpi_bcast(divt3d,nlev,mpi_real8,mstrid,mpicom,ierr)
         311           0 :       if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: divt3d")
         312           0 :       call mpi_bcast(divq3d,nlev,mpi_real8,mstrid,mpicom,ierr)
         313           0 :       if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: divq3d")
         314             :
         315             : #endif
         316             :
         317           0 :     end subroutine iop_broadcast
         318             :
         319             : !=========================================================================
         320           0 :     subroutine scm_dyn_grid_indicies(elem,scmlat,scmlon,ie_scm,i_scm,j_scm,indx_scm)
         321             :
         322             :       !---------------------------------------------------------
         323             :       ! Purpose: Determine closest column index in the IOP file
         324             :       !   based on the input scm latitude and longitude
         325             :       !----------------------------------------------------------
         326             :
         327             :       use shr_const_mod,          only: SHR_CONST_PI
         328             :       use cam_abortutils,         only: endrun
         329             :
         330             :       type(element_t), intent(in) :: elem(:)
         331             :       real (r8),       intent(in) :: scmlat,scmlon
         332             :       integer,         intent(out) :: ie_scm, j_scm, i_scm, indx_scm
         333             :
         334             :       integer :: i, j, indx, ie
         335             :       real(r8) :: scmposlon, minpoint, testlat, testlon, testval
         336             :       integer :: ierr
         337             :       real(r8), parameter :: rad2deg = 180.0_r8 / SHR_CONST_PI
         338             :       character(len=*), parameter :: sub = 'scm_dyn_grid_indicies'
         339             :
         340           0 :       ie_scm=0
         341           0 :       i_scm=0
         342           0 :       j_scm=0
         343           0 :       indx_scm=0
         344           0 :       minpoint = 1000
         345           0 :       scmposlon = mod(scmlon + 360._r8,360._r8)
         346           0 :       do ie=1, nelemd
         347             :          indx=1
         348           0 :          do j=1, np
         349           0 :             do i=1, np
         350           0 :                testlat=elem(ie)%spherep(i,j)%lat * rad2deg
         351           0 :                testlon=elem(ie)%spherep(i,j)%lon * rad2deg
         352           0 :                if (testlon  <  0._r8) testlon=testlon+360._r8
         353           0 :                testval=abs(scmlat-testlat)+abs(scmposlon-testlon)
         354           0 :                if (testval  <  minpoint) then
         355           0 :                   ie_scm=ie
         356           0 :                   indx_scm=indx
         357           0 :                   i_scm=i
         358           0 :                   j_scm=j
         359           0 :                   minpoint=testval
         360           0 :                   if (minpoint  <  1.e-7_r8) minpoint=0._r8
         361             :                endif
         362           0 :                indx=indx+1
         363             :             enddo
         364             :          enddo
         365             :       enddo
         366             :
         367           0 :       if (ie_scm == 0 .or. i_scm == 0 .or. j_scm == 0 .or. indx_scm == 0) then
         368           0 :          call endrun(sub//':FATAL: Could not find closest SCM point on input datafile')
         369             :       endif
         370             :
         371           0 :     end subroutine scm_dyn_grid_indicies
         372             :
         373             :  end module se_single_column_mod

Generated by: LCOV version 1.14