module mo_msis_ubc,4 !--------------------------------------------------------------- ! ... msis upper bndy values !--------------------------------------------------------------- use shr_kind_mod, only : r8 => shr_kind_r8 use constituents, only : pcnst use abortutils, only: endrun use cam_logfile, only: iulog implicit none private public :: msis_ubc_inti, get_msis_ubc, msis_timestep_init save integer :: msis_frq = 1 ! step frequency of msis retrieval integer :: stepsize ! timestep size (s) integer :: ndx_n, ndx_h, ndx_o, ndx_o2 ! n, h, o, o2 spc indicies integer :: msis_cnt = 0 ! count of msis species in simulation integer :: ndx(pcnst) = -1 real(r8), allocatable :: msis_ubc(:,:,:) ! module array for msis ub values (kg/kg) real(r8) :: r2d logical :: zonal_average = .false. ! use zonal averaged tgcm values contains subroutine msis_ubc_inti( zonal_avg, freq ),11 !------------------------------------------------------------------ ! ... initialize upper boundary values !------------------------------------------------------------------ use ppgrid, only : pcols, begchunk, endchunk use constituents, only : cnst_get_ind, cnst_fixed_ubc use time_manager, only : get_step_size use physconst, only : pi implicit none !------------------------------------------------------------------ ! ... dummy args !------------------------------------------------------------------ integer, intent(in) :: & freq ! frequency of msis retrieval logical, intent(in) :: & zonal_avg ! zonal averaging switch !------------------------------------------------------------------ ! ... local variables !------------------------------------------------------------------ integer :: astat real(r8) :: msis_switches(25) = 1._r8 zonal_average = zonal_avg msis_frq = max( freq,1 ) !------------------------------------------------------------------ ! ... check for msis species in simuation !------------------------------------------------------------------ call cnst_get_ind( 'H', ndx_h, abort=.false. ) if( ndx_h > 0 ) then if( cnst_fixed_ubc(ndx_h) ) then ndx(ndx_h) = ndx_h end if end if call cnst_get_ind( 'N', ndx_n, abort=.false. ) if( ndx_n > 0 ) then if( cnst_fixed_ubc(ndx_n) ) then ndx(ndx_n) = ndx_n end if end if call cnst_get_ind( 'O', ndx_o, abort=.false. ) if( ndx_o > 0 ) then if( cnst_fixed_ubc(ndx_o) ) then ndx(ndx_o) = ndx_o end if end if call cnst_get_ind( 'O2', ndx_o2, abort=.false. ) if( ndx_o2 > 0 ) then if( cnst_fixed_ubc(ndx_o2) ) then ndx(ndx_o2) = ndx_o2 end if end if !------------------------------------------------------------------ ! ... allocate msis ubc array !------------------------------------------------------------------ msis_cnt = count( ndx(:) /= -1 ) allocate( msis_ubc(pcols,6,begchunk:endchunk),stat=astat ) if( astat /= 0 ) then write(iulog,*) 'msis_ubc_inti: failed to allocate msis_ubc; error = ',astat call endrun end if if( zonal_average ) then msis_switches(7:8) = 0._r8 msis_switches(10:14) = 0._r8 end if !------------------------------------------------------------------ ! ... initialize msis switches !------------------------------------------------------------------ call tselec( msis_switches ) r2d = 180._r8/pi stepsize = get_step_size() end subroutine msis_ubc_inti subroutine msis_timestep_init( ap, f107, f107a ),16 !-------------------------------------------------------------------- ! ... get the upper boundary values for h, n, o, o2 and temp !-------------------------------------------------------------------- use ppgrid, only : pcols, begchunk, endchunk use pmgrid, only : plev, plevp use constituents, only : cnst_mw use time_manager, only : get_curr_date, get_nstep, get_curr_calday, & get_calday, is_first_step, is_first_restart_step use phys_grid, only : get_ncols_p, get_rlon_all_p, get_rlat_all_p use hycoef, only : hyai, ps0 use spmd_utils, only : masterproc implicit none !-------------------------------------------------------------------- ! ... dummy args !-------------------------------------------------------------------- real(r8), intent(in) :: ap real(r8), intent(in) :: f107 real(r8), intent(in) :: f107a !-------------------------------------------------------------------- ! ... local variables !-------------------------------------------------------------------- real(r8), parameter :: mass_switch = 48._r8 real(r8), parameter :: pa2mb = 1.e-2_r8 ! pascal to mb real(r8), parameter :: amu_fac = 1.65979e-24_r8 ! g/amu integer :: i, c, ncol integer :: yr, mon, day, tod, nstep integer :: yrday integer :: date integer :: offset real(r8) :: alt, latitude, longitude, solar_time, ut, rtod, doy real(r8) :: msis_press real(r8) :: msis_ap(7) real(r8) :: msis_temp(2) real(r8) :: msis_conc(9) real(r8) :: rlons(pcols) real(r8) :: rlats(pcols) real(r8) :: dnom(pcols) real(r8) :: pint(pcols) ! top interface pressure (Pa) nstep = get_nstep() !-------------------------------------------------------------------- ! ... get values from msis !-------------------------------------------------------------------- msis_retrieval : & if( is_first_step() .or. is_first_restart_step() .or. mod( nstep,msis_frq ) == 0 ) then offset = mod( nstep,msis_frq ) if( offset /= 0 ) then offset = -offset*stepsize end if call get_curr_date( yr, mon, day, tod, offset ) rtod = tod ut = rtod/3600._r8 date = 10000*yr + 100*mon + day doy = get_calday( date, tod ) msis_ap(:) = 0._r8 msis_ap(1) = ap pint(:) = ps0 * hyai(1) #ifdef MSIS_DIAGS if( masterproc ) then write(iulog,*) '====================================' write(iulog,*) 'msis_timestep_init: diagnostics' write(iulog,*) 'nstep,yr,mon,day,tod,date,ut,doy,offset,msis_frq = ',nstep, yr, mon, day, tod, date, ut, doy, offset, msis_frq write(iulog,*) '====================================' end if #endif chunk_loop : & do c = begchunk,endchunk ncol = get_ncols_p( c ) call get_rlat_all_p( c, ncol, rlats ) call get_rlon_all_p( c, ncol, rlons ) rlons(:ncol) = r2d * rlons(:ncol) rlats(:ncol) = r2d * rlats(:ncol) yrday = mod( yr,100 ) * 1000 + int( doy ) column_loop : & do i = 1,ncol solar_time = ut + rlons(i)/15._r8 msis_press = pint(i)*pa2mb call ghp7( yrday, rtod, alt, rlats(i), rlons(i), & solar_time, f107a, f107, msis_ap, msis_conc, & msis_temp, msis_press ) msis_ubc(i,1,c) = msis_temp(2) ! temp (K) #ifdef MSIS_DIAGS write(iulog,*) '====================================' write(iulog,*) 'msis_timestep_init: diagnostics for col,chnk = ',i,c write(iulog,*) 'yrday, rtod, alt,press = ',yrday,rtod,alt,msis_press write(iulog,*) 'msis_temp = ',msis_temp(2) #endif if( msis_cnt > 0 ) then msis_ubc(i,2,c) = msis_conc(7) ! h (molec/cm^3) msis_ubc(i,3,c) = msis_conc(8) ! n (molec/cm^3) msis_ubc(i,4,c) = msis_conc(2) ! o (molec/cm^3) msis_ubc(i,5,c) = msis_conc(4) ! o2 (molec/cm^3) msis_ubc(i,6,c) = msis_conc(6) ! total atm dens (g/cm^3) end if #ifdef MSIS_DIAGS write(iulog,*) 'msis h,n,o,o2,m = ',msis_ubc(i,2:6,c) write(iulog,*) '====================================' #endif end do column_loop !-------------------------------------------------------------------- ! ... transform from molecular density to mass mixing ratio !-------------------------------------------------------------------- if( msis_cnt > 0 ) then dnom(:ncol) = amu_fac/msis_ubc(:ncol,6,c) if( ndx(ndx_h) > 0 ) then msis_ubc(:ncol,2,c) = cnst_mw(ndx_h)*msis_ubc(:ncol,2,c)*dnom(:ncol) end if if( ndx(ndx_n) > 0 ) then msis_ubc(:ncol,3,c) = cnst_mw(ndx_n)*msis_ubc(:ncol,3,c)*dnom(:ncol) end if if( ndx(ndx_o) > 0 ) then msis_ubc(:ncol,4,c) = cnst_mw(ndx_o)*msis_ubc(:ncol,4,c)*dnom(:ncol) end if if( ndx(ndx_o2) > 0 ) then msis_ubc(:ncol,5,c) = cnst_mw(ndx_o2)*msis_ubc(:ncol,5,c)*dnom(:ncol) end if end if end do chunk_loop end if msis_retrieval end subroutine msis_timestep_init subroutine get_msis_ubc( lchunk, ncol, temp, mmr ),1 !-------------------------------------------------------------------- ! ... get the upper boundary values for h, n, o, o2 and temp !-------------------------------------------------------------------- use ppgrid, only : pcols implicit none !-------------------------------------------------------------------- ! ... dummy args !-------------------------------------------------------------------- integer, intent(in) :: lchunk ! chunk id integer, intent(in) :: ncol ! columns in chunk real(r8), intent(inout) :: temp(pcols) ! msis temperature at top interface (K) real(r8), intent(inout) :: mmr(pcols,pcnst) ! msis concentrations at top interface (kg/kg) !-------------------------------------------------------------------- ! ... set model ubc values from msis !-------------------------------------------------------------------- temp(:ncol) = msis_ubc(:ncol,1,lchunk) if( msis_cnt > 0 ) then if( ndx(ndx_h) > 0 ) then mmr(:ncol,ndx_h) = msis_ubc(:ncol,2,lchunk) end if if( ndx(ndx_n) > 0 ) then mmr(:ncol,ndx_n) = msis_ubc(:ncol,3,lchunk) end if if( ndx(ndx_o) > 0 ) then mmr(:ncol,ndx_o) = msis_ubc(:ncol,4,lchunk) end if if( ndx(ndx_o2) > 0 ) then mmr(:ncol,ndx_o2) = msis_ubc(:ncol,5,lchunk) end if end if end subroutine get_msis_ubc end module mo_msis_ubc