LCOV - code coverage report
Current view: top level - chemistry/mozart - mo_snoe.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 116 0.0 %
Date: 2024-12-17 17:57:11 Functions: 0 8 0.0 %

          Line data    Source code
       1             :       module mo_snoe
       2             : !----------------------------------------------------------------------
       3             : ! An empirical model of nitric oxide (NO) in the lower thermosphere
       4             : ! (100 - 150 km altitude), based on measurements from the Student
       5             : ! Nitric Oxide Explorer (SNOE). Model uses empirical orthogonal functions
       6             : ! (EOFs) derived from the SNOE dataset to describe spatial variability
       7             : ! in NO. Model NO is the sum of a mean distribution and EOFs multiplied
       8             : ! by coefficients based on geophysical parameters. These geophysical
       9             : ! parameters are day of year, Kp magnetic index and F10.7 solar uv index.
      10             : !
      11             : ! Model is utilized by calling subroutine snoe_3d(), which returns
      12             : ! a 3-D distribution of NO on geographic coordinates (lon/lat are
      13             : ! supplied by user). Altitude is fixed to SNOE grid (every 3.33 km).
      14             : !
      15             : ! 
      16             : !  DRM 4/03
      17             : !----------------------------------------------------------------------
      18             : 
      19             :       use shr_kind_mod,     only : r8 => shr_kind_r8
      20             :       use ppgrid,           only : pcols
      21             :       use physconst,        only : pi
      22             :       use mo_constants,     only : r2d, d2r
      23             :       use cam_abortutils,   only : endrun
      24             :       use cam_logfile,      only : iulog
      25             : 
      26             :       implicit none
      27             : 
      28             :       private
      29             : 
      30             :       public :: snoe_inti, snoe_timestep_init, set_no_ubc
      31             :       public :: ndx_no
      32             : 
      33             :       save
      34             : 
      35             :       integer,  parameter    :: nmodes  = 3
      36             :       real(r8), parameter    :: delz    = 104.6_r8             ! delta z (km)
      37             :       real(r8), parameter    :: re      = 6471._r8             ! radial distance from ED at 100 km altitude (km)
      38             :       real(r8), parameter    :: delx    = -399.1_r8            ! delta x (km)
      39             :       real(r8), parameter    :: dely    = -286.1_r8            ! delta y (km)
      40             :       real(r8), parameter    :: twopi   = 2._r8*pi, pid2=0.5_r8*pi
      41             :       real(r8), parameter    :: theta_n = d2r*(90._r8 - 78.98_r8)    ! co-latitude of CD North Pole (radians)
      42             :       real(r8), parameter    :: phi_n   = d2r*289.1_r8               ! longitude of CD North Pole (radians)
      43             : 
      44             :       integer :: nmlat
      45             :       integer :: nlev
      46             :       integer :: ndx_no
      47             : 
      48             :       
      49             : !----------------------------------------------------------------------
      50             : !       ... snoe mean and eof data
      51             : !----------------------------------------------------------------------
      52             :       real(r8), allocatable :: mlat(:,:)                       ! magnetic latitudes corresponding to geo latitudes (radians)
      53             :       real(r8), allocatable :: mlat2d(:)                       ! snoe latitudes (degrees)
      54             :       real(r8), allocatable :: lev(:)                          ! snoe levels (km)
      55             :       real(r8), allocatable :: no_mean(:,:)                    ! mean no
      56             :       real(r8), allocatable :: eofs(:,:,:)                     ! empirical orthogonal ftns
      57             :       real(r8), allocatable :: snoe_no(:,:,:)                  ! snoe no interpolated to model lons (molecules/cm^3)
      58             : 
      59             :       real(r8) :: cthetan
      60             :       real(r8) :: sthetan
      61             : 
      62             :       contains
      63             : 
      64           0 :       subroutine snoe_inti(snoe_ubc_file)
      65             : !----------------------------------------------------------------------
      66             : !       ... initialize snoe
      67             : !----------------------------------------------------------------------
      68             : 
      69             :       use ppgrid,       only : begchunk, endchunk
      70             :       use constituents, only : cnst_get_ind, cnst_fixed_ubc
      71             : 
      72             : !----------------------------------------------------------------------
      73             : !       ... dummy arguments
      74             : !----------------------------------------------------------------------
      75             :       character(len=*), intent(in) :: snoe_ubc_file
      76             : 
      77             : !----------------------------------------------------------------------
      78             : !       ... local variables
      79             : !----------------------------------------------------------------------
      80             :       integer  :: astat
      81             : 
      82             : !----------------------------------------------------------------------
      83             : !       ... do we have no with a fixed ubc ?
      84             : !----------------------------------------------------------------------
      85           0 :       call cnst_get_ind( 'NO', ndx_no, abort=.false. )
      86           0 :       if( ndx_no > 0 ) then
      87           0 :          if( .not. cnst_fixed_ubc(ndx_no) ) then
      88           0 :             return
      89             :          end if
      90             :       else
      91             :          return
      92             :       end if
      93             : 
      94             : 
      95             : 
      96           0 :       cthetan = cos( theta_n )  
      97           0 :       sthetan = sin( theta_n )
      98             : !----------------------------------------------------------------------
      99             : !       ... read snoe netcdf file
     100             : !----------------------------------------------------------------------
     101           0 :       call snoe_rdeof(snoe_ubc_file)
     102             :       allocate( snoe_no(pcols,nlev,begchunk:endchunk), &
     103           0 :                 mlat(pcols,begchunk:endchunk),stat=astat )
     104           0 :       if( astat /= 0 ) then
     105           0 :          write(iulog,*) 'snoe_inti: failed to allocate snoe_no,mlat; error = ',astat
     106           0 :          call endrun
     107             :       end if
     108             : 
     109             : !----------------------------------------------------------------------
     110             : !       ... get lon/lat transformed to magnetic coords
     111             : !----------------------------------------------------------------------
     112           0 :       call geo2mag
     113             : 
     114             :       end subroutine snoe_inti
     115             : 
     116           0 :       subroutine snoe_rdeof(snoe_ubc_file)
     117             : !----------------------------------------------------------------------
     118             : !       ... read in eofs from netcdf file
     119             : !----------------------------------------------------------------------
     120             : 
     121             :       use ioFileMod,     only : getfil
     122             :       use cam_pio_utils, only : cam_pio_openfile
     123             :       use pio,           only : file_desc_t, pio_get_var, pio_closefile, &
     124             :            pio_nowrite, pio_inq_varid, pio_inq_dimid, pio_inq_dimlen
     125             :       implicit none
     126             : 
     127             : !----------------------------------------------------------------------
     128             : !       ... dummy arguments
     129             : !----------------------------------------------------------------------
     130             :       character(len=*), intent(in) :: snoe_ubc_file
     131             : 
     132             : !----------------------------------------------------------------------
     133             : !       ... local variables
     134             : !----------------------------------------------------------------------
     135             :       integer :: istat, ierr
     136             :       integer :: dim_id, var_id 
     137             :       type(file_desc_t) :: ncid
     138             :       character(len=256) :: locfn
     139             : 
     140             : !----------------------------------------------------------------------
     141             : 
     142             : #ifdef SNOE_DIAGS
     143             :       write(iulog,*) 'snoe_rdeof: entered routine'
     144             : #endif
     145             : 
     146             : !----------------------------------------------------------------------
     147             : !       ... open the netcdf file
     148             : !----------------------------------------------------------------------
     149           0 :       call getfil(snoe_ubc_file, locfn, 0)
     150           0 :       call cam_pio_openfile( ncid, trim(locfn), PIO_NOWRITE)
     151             : 
     152             : !----------------------------------------------------------------------
     153             : !       ... read the snoe dimensions
     154             : !----------------------------------------------------------------------
     155           0 :       ierr = pio_inq_dimid( ncid, 'lat', dim_id )
     156           0 :       ierr = pio_inq_dimlen( ncid, dim_id, nmlat )
     157           0 :       ierr = pio_inq_dimid( ncid, 'lev', dim_id )
     158           0 :       ierr = pio_inq_dimlen( ncid, dim_id, nlev )
     159             : 
     160             : !----------------------------------------------------------------------
     161             : !       ... allocate snoe variables
     162             : !----------------------------------------------------------------------
     163             :       allocate( mlat2d(nmlat), lev(nlev), &
     164           0 :                 no_mean(nmlat,nlev), eofs(nmlat,nlev,nmodes), stat=istat )
     165           0 :       if( istat /= 0 ) then
     166           0 :          write(iulog,*) 'snoe_rdeof: failed to allocate mlat2d ... eofs; error = ',istat
     167           0 :          call endrun
     168             :       end if
     169             : 
     170             : !----------------------------------------------------------------------
     171             : !       ... read the snoe variables
     172             : !----------------------------------------------------------------------
     173           0 :       ierr = pio_inq_varid( ncid, 'NO', var_id )
     174           0 :       ierr = pio_get_var( ncid, var_id, no_mean )
     175             : 
     176           0 :       ierr = pio_inq_varid( ncid, 'EOF', var_id )
     177           0 :       ierr = pio_get_var( ncid, var_id, (/1,1,1/), (/nmlat, nlev, nmodes/), eofs )
     178             : 
     179           0 :       ierr = pio_inq_varid( ncid, 'lat', var_id )
     180           0 :       ierr = pio_get_var( ncid, var_id, mlat2d )
     181           0 :       mlat2d(:) = d2r*mlat2d(:)
     182             : 
     183           0 :       ierr = pio_inq_varid( ncid, 'z', var_id )
     184           0 :       ierr = pio_get_var( ncid, var_id, lev )
     185             : 
     186             : !----------------------------------------------------------------------
     187             : !       ... close the netcdf file
     188             : !----------------------------------------------------------------------
     189           0 :       call pio_closefile( ncid)
     190             : 
     191           0 :       end subroutine snoe_rdeof
     192             : 
     193           0 :       subroutine geo2mag
     194             : !----------------------------------------------------------------------
     195             : !       ... converts geographic latitude and longitude pair
     196             : !           to eccentric dipole (ED) geomagnetic coordinates
     197             : !----------------------------------------------------------------------
     198             : 
     199           0 :       use ppgrid,    only : begchunk, endchunk
     200             :       use phys_grid, only : get_ncols_p, get_rlon_all_p, get_rlat_all_p
     201             : 
     202             :       implicit none
     203             : 
     204             : !----------------------------------------------------------------------
     205             : !       ... local variables
     206             : !----------------------------------------------------------------------
     207             :       integer  :: c, i, j
     208             :       integer  :: ncol
     209             :       real(r8) :: cdlat
     210             :       real(r8) :: wrk
     211             :       real(r8) :: smaglat, cmaglat, cmaglon, smaglon
     212             :       real(r8) :: edlon, sedlon, cedlon, edlat, cedlat
     213             :       real(r8) :: singlat, cosglat
     214             :       real(r8) :: rlons(pcols)
     215             :       real(r8) :: rlats(pcols)
     216             : 
     217             : !----------------------------------------------------------------------
     218             : !       ... start with centered dipole (CD) coordinates
     219             : !----------------------------------------------------------------------
     220             : chunk_loop : &
     221           0 :       do c = begchunk,endchunk
     222           0 :          ncol = get_ncols_p( c )
     223           0 :          call get_rlon_all_p( c, ncol, rlons )
     224           0 :          call get_rlat_all_p( c, ncol, rlats )
     225             : column_loop : &
     226           0 :          do i = 1,ncol
     227           0 :             singlat = sin( rlats(i) )
     228           0 :             cosglat = cos( rlats(i) )
     229           0 :             wrk     = rlons(i) - phi_n
     230           0 :             cdlat = acos( singlat * cthetan + cosglat * sthetan * cos(wrk) )
     231           0 :             smaglat = sin( cdlat )
     232           0 :             cmaglat = cos( cdlat )
     233           0 :             cmaglon = -(singlat - cthetan * cmaglat) / (sthetan * smaglat)
     234           0 :             smaglon = cosglat * sin(wrk) / smaglat
     235             : !----------------------------------------------------------------------
     236             : !       ... convert CD coords to ED coords- equation (39 a,b) of Fraser-Smith
     237             : !----------------------------------------------------------------------
     238           0 :             sedlon = re * smaglat * smaglon - dely
     239           0 :             cedlon = re * smaglat * cmaglon - delx
     240           0 :             edlon  = atan2( sedlon, cedlon )            ! ED magnetic long. (degrees)
     241           0 :             cedlat = (re * cmaglat - delz) * cos(edlon)
     242           0 :             edlat  = atan2( cedlon, cedlat )            ! ED magnetic latitude (degrees)
     243             : !----------------------------------------------------------------------
     244             : !       ... convert co-latitudes into latitudes 
     245             : !----------------------------------------------------------------------
     246           0 :             if( edlat < 0._r8 ) then
     247           0 :                edlat = edlat + pi
     248             :             end if
     249           0 :             mlat(i,c) = pid2 - edlat
     250             :          end do column_loop
     251             :       end do chunk_loop
     252             : 
     253           0 :       end subroutine geo2mag 
     254             : 
     255           0 :       subroutine snoe_timestep_init( kp, f107 )
     256             : !----------------------------------------------------------------------
     257             : !       ... driver routine that provides access to empirical model
     258             : !           data returned is three dimensional (on geographic coordinates)
     259             : !----------------------------------------------------------------------
     260             : 
     261           0 :       use time_manager, only : get_curr_calday
     262             :       use ppgrid,       only : pcols, begchunk, endchunk
     263             :       use phys_grid,    only : get_ncols_p
     264             :       use spmd_utils,   only : masterproc
     265             : 
     266             :       implicit none
     267             : 
     268             : !----------------------------------------------------------------------
     269             : !       ... dummy arguments
     270             : !----------------------------------------------------------------------
     271             :       real(r8), intent(in)  :: kp                   ! solar activity index
     272             :       real(r8), intent(in)  :: f107                 ! solar activity index
     273             : 
     274             : !----------------------------------------------------------------------
     275             : !       ... local variables
     276             : !----------------------------------------------------------------------
     277             :       integer                  :: astat, c
     278             :       integer                  :: ncol
     279             :       real(r8)                 :: doy                ! day of year
     280           0 :       real(r8), allocatable    :: zm(:,:)            ! zonal mean nitric oxide distribution (molecules/cm^3)
     281             : 
     282           0 :       allocate( zm(nmlat,nlev),stat=astat )
     283           0 :       if( astat /= 0 ) then
     284           0 :          write(iulog,*) 'snoe_3d: failed to allocate zm; error = ',astat
     285           0 :          call endrun
     286             :       end if
     287           0 :       doy = aint( get_curr_calday() )
     288             : #ifdef SNOE_DIAGS
     289             :       if( masterproc ) then
     290             :          write(iulog,*) ' '
     291             :          write(iulog,*) 'set_snoe_no: doy,kp,f107 = ',doy,kp,f107
     292             :          write(iulog,*) ' '
     293             :       end if
     294             : #endif
     295             :       !----------------------------------------------------------------------
     296             :       ! ... obtain SNOE zonal mean data in geomagnetic coordinates
     297             :       !----------------------------------------------------------------------
     298           0 :       call snoe_zm( doy, kp, f107, zm )
     299             : 
     300             :       !----------------------------------------------------------------------
     301             :       ! ... map mean to model longitudes
     302             :       !----------------------------------------------------------------------
     303           0 :       do c = begchunk,endchunk
     304           0 :          ncol = get_ncols_p( c )
     305           0 :          call snoe_zmto3d( c, ncol, zm, nmlat, nlev )
     306             :       end do
     307           0 :       deallocate( zm )
     308             : 
     309           0 :       end subroutine snoe_timestep_init
     310             : 
     311           0 :       subroutine set_no_ubc( lchunk, ncol, zint, mmr, rho )
     312             : !----------------------------------------------------------------------
     313             : !       ... set no mixing ratio at the model top interface level
     314             : !----------------------------------------------------------------------
     315             : 
     316           0 :       use constituents, only : pcnst, cnst_mw
     317             : 
     318             :       implicit none
     319             : 
     320             : !----------------------------------------------------------------------
     321             : !       ... dummy arguments
     322             : !----------------------------------------------------------------------
     323             :       integer,  intent(in)    :: lchunk
     324             :       integer,  intent(in)    :: ncol
     325             :       real(r8), intent(in)    :: zint(pcols)          ! geopot height (km)
     326             :       real(r8), intent(in)    :: rho(pcols)           ! total atm density (kg/m^3)
     327             :       real(r8), intent(inout) :: mmr(pcols,pcnst)     ! concentration at top interface (kg/kg)
     328             : 
     329             : !----------------------------------------------------------------------
     330             : !       ... local variables
     331             : !----------------------------------------------------------------------
     332             :       real(r8), parameter :: amu_fac  = 1.65979e-27_r8 ! kg/amu
     333             :       real(r8), parameter :: cm3_2_m3  = 1.e6_r8
     334             :       integer    :: astat, i, k, ks, ks1
     335             :       real(r8)   :: zinterp, zfac, mfac
     336             : 
     337             : !----------------------------------------------------------------------
     338             : !       ... map to model levels
     339             : !----------------------------------------------------------------------
     340           0 :       if( ndx_no > 0 ) then
     341             : column_loop : &
     342           0 :          do i = 1,ncol
     343           0 :             zinterp = zint(i)
     344           0 :             if( zinterp >= lev(1) ) then
     345           0 :                mmr(i,ndx_no) = snoe_no(i,1,lchunk)
     346           0 :             else if( zint(i) < lev(nlev) ) then
     347           0 :                mmr(i,ndx_no) = 0._r8
     348             :             else
     349           0 :                do ks = 2,nlev
     350           0 :                   if( zinterp >= lev(ks) ) then
     351           0 :                      ks1 = ks - 1
     352           0 :                      zfac = (zinterp - lev(ks))/(lev(ks1) - lev(ks))
     353           0 :                      mmr(i,ndx_no) = snoe_no(i,ks,lchunk) &
     354           0 :                                      + zfac*(snoe_no(i,ks1,lchunk) - snoe_no(i,ks,lchunk))
     355           0 :                      exit
     356             :                   end if
     357             :                end do
     358             :             end if
     359             :          end do column_loop
     360           0 :          mfac = amu_fac * cm3_2_m3 * cnst_mw(ndx_no)
     361           0 :          mmr(:ncol,ndx_no) = mmr(:ncol,ndx_no) * mfac /rho(:ncol)
     362             :       end if
     363             : 
     364           0 :       end subroutine set_no_ubc 
     365             : 
     366           0 :       subroutine snoe_zm( doy, kp, f107, zm )
     367             : !----------------------------------------------------------------------
     368             : !       ... calculates zonal mean nitric oxide distribution on a given day 
     369             : !           and solar conditions (represented by the f10.7 and kp indices)
     370             : !----------------------------------------------------------------------
     371             : 
     372             :       implicit none
     373             : 
     374             : !----------------------------------------------------------------------
     375             : !       ... dummy arguments
     376             : !----------------------------------------------------------------------
     377             :       real(r8), intent(in)  :: doy
     378             :       real(r8), intent(in)  :: kp 
     379             :       real(r8), intent(in)  :: f107
     380             :       real(r8), intent(out) :: zm(:,:)
     381             : 
     382             : !----------------------------------------------------------------------
     383             : !       ... local variables
     384             : !----------------------------------------------------------------------
     385             :       integer  :: k
     386             :       real(r8) :: theta0         ! day number in degrees
     387             :       real(r8) :: dec            ! solar declination angle
     388             :       real(r8) :: m1, m2, m3     ! coefficients for first 3 eofs
     389             : 
     390             : #ifdef SNOE_DIAGS
     391             :       write(iulog,*) 'snoe_zm: doy, kp, f107 = ',doy,kp,f107
     392             : #endif
     393             : 
     394             : !----------------------------------------------------------------------
     395             : !       ... calculate coefficients (m1 to m3) for eofs based on
     396             : !           geophysical parametes eof1 - kp 
     397             : !----------------------------------------------------------------------
     398             : 
     399           0 :       m1 =  kp * 0.785760_r8 - 1.94262_r8
     400             : 
     401             : !----------------------------------------------------------------------
     402             : !       ... eof2 - declination
     403             : !----------------------------------------------------------------------
     404           0 :       theta0 = twopi * (doy - 1._r8) / 365._r8
     405             : 
     406             :       dec = .006918_r8 &
     407             :           - .399912_r8 * cos(theta0)   + .070257_r8 * sin(theta0) &
     408             :           - .006758_r8 * cos(2._r8*theta0) + .000907_r8 * sin(2._r8*theta0) & 
     409           0 :           - .002697_r8 * cos(3._r8*theta0) + .001480_r8 * sin(3._r8*theta0)
     410             : 
     411           0 :       dec = dec * r2d
     412             : 
     413             : #ifdef SNOE_DIAGS
     414             :       write(iulog,*) 'snoe_zm: dec = ',dec
     415             : #endif
     416           0 :       m2 = -.319782_r8 + dec*(.0973109_r8 + dec*(.000489814_r8 - dec*.000103608_r8))
     417             :       
     418             : !----------------------------------------------------------------------
     419             : !       ... eof3 - f107 
     420             : !----------------------------------------------------------------------
     421           0 :       m3 =  log10(f107) * 6.44069_r8 - 13.9832_r8
     422             : 
     423             : #ifdef SNOE_DIAGS
     424             :       write(iulog,*) 'snoe_zm: m1, m2, m3 = ',m1,m2,m3
     425             : #endif
     426             : 
     427             : !----------------------------------------------------------------------
     428             : !       ... zonal mean distrib. is sum of mean and eofs
     429             : !----------------------------------------------------------------------
     430           0 :       do k = 1,nlev
     431           0 :          zm(:,k) = no_mean(:,k) - m1 * eofs(:,k,1) + m2 * eofs(:,k,2) - m3 * eofs(:,k,3) 
     432             :       end do
     433             : 
     434           0 :       end subroutine snoe_zm 
     435             : 
     436           0 :       subroutine snoe_zmto3d( lchunk, ncol, zm, nmlat, nlev )
     437             : !----------------------------------------------------------------------
     438             : !       ... interpolate zonal mean on magnetic grid 
     439             : !           to 3d field in geographic coords
     440             : !----------------------------------------------------------------------
     441             : 
     442             :       implicit none
     443             : 
     444             : !----------------------------------------------------------------------
     445             : !       ... dummy arguments
     446             : !----------------------------------------------------------------------
     447             :       integer, intent(in)  :: lchunk
     448             :       integer, intent(in)  :: ncol
     449             :       integer, intent(in)  :: nmlat
     450             :       integer, intent(in)  :: nlev
     451             :       real(r8), intent(in) :: zm(nmlat,nlev)             ! zonal mean snoe no concentration
     452             : 
     453             : !----------------------------------------------------------------------
     454             : !       ... local variables
     455             : !----------------------------------------------------------------------
     456             :       integer :: k
     457             : 
     458           0 :       do k = 1,nlev
     459           0 :          call interpol( nmlat, mlat2d, zm(1,k), ncol, mlat(1,lchunk), snoe_no(1,k,lchunk) )
     460             :       end do
     461             : 
     462           0 :       end subroutine snoe_zmto3d
     463             : 
     464           0 :       subroutine interpol( nin, xin, yin, nout, xout, yout )
     465             : !-----------------------------------------------------------------------
     466             : !       ... linear interpolation
     467             : !           does not extrapolate, but repeats edge values
     468             : !-----------------------------------------------------------------------
     469             : 
     470             :       implicit none
     471             : 
     472             : !-----------------------------------------------------------------------
     473             : !       ... dummy arguments
     474             : !-----------------------------------------------------------------------
     475             :       integer, intent(in) :: nin, nout
     476             :       real(r8), intent(in)    :: xin(nin)
     477             :       real(r8), intent(in)    :: yin(nin)
     478             :       real(r8), intent(in)    :: xout(nout)
     479             :       real(r8), intent(out)   :: yout(nout)
     480             : 
     481             : !-----------------------------------------------------------------------
     482             : !       ... local variables
     483             : !-----------------------------------------------------------------------
     484             :       integer :: i, j
     485             : 
     486           0 :       do j = 1,nout
     487           0 :         if( xout(j) < xin(1) ) then
     488           0 :           yout(j) = yin(1)
     489             :         else
     490           0 :           if( xout(j) > xin(nin) ) then
     491           0 :             yout(j) = yin(nin)
     492             :           else
     493           0 :             do i = 1, nin-1
     494           0 :               if ((xout(j) >= xin(i)) .and. (xout(j) < xin(i+1)) ) then
     495             :                 yout(j) =  yin(i) &
     496           0 :                            + (yin(i+1) - yin(i)) * (xout(j) - xin(i)) / (xin(i+1) - xin(i))
     497             :               end if
     498             :             end do
     499             :           end if
     500             :         end if
     501             :       end do
     502             : 
     503           0 :       end subroutine interpol
     504             : 
     505             :       end module mo_snoe

Generated by: LCOV version 1.14