physpkg.f90
来自「CCSM Research Tools: Community Atmospher」· F90 代码 · 共 363 行
F90
363 行
#include <misc.h>#include <params.h>subroutine physpkg (phys_state, gw, ztodt, & phys_tend, cldo, cldn, tcwato, tcwatn, & qcwato, qcwatn, lcwato,lcwatn)!----------------------------------------------------------------------- ! ! Purpose: ! Loop over time, calling driving routines for physics! ! Method: ! COUP_CSM and must be checked in order to invoke the proper calling! sequence for running the CSM model! ! Author: ! Original version: CCM3!----------------------------------------------------------------------- use precision use pmgrid, only: plon, plat, masterproc use ppgrid, only: pcols, pver use buffer, only: pblht, tpert, qpert, qrs, qrl use comsrf#ifdef COUP_CSM use ccsm_msg, only: ccsmave, dorecv, dosend, ccsmsnd, ccsmrcv#else use atm_lndMod, only: atmlnd_drv#endif#ifdef SPMD use mpishorthand#endif use phys_grid, only: get_ncols_p, get_lat_all_p, get_lon_all_p use physics_types, only: physics_state, physics_tend use comsrf use diagnostics, only: diag_surf use time_manager, only: get_nstep, is_first_step, is_first_restart_step, & is_end_curr_month, get_curr_date!----------------------------------------------------------------------- implicit none!-----------------------------------------------------------------------#include <comctl.h>!-----------------------------------------------------------------------#include <comsol.h>!-----------------------------------------------------------------------!! Input arguments! real(r8), intent(in) :: gw(plat) ! Gaussian weights real(r8), intent(in) :: ztodt ! physics time step unless nstep=0!! Input/Output arguments! type(physics_state), intent(inout), dimension(begchunk:endchunk) :: phys_state type(physics_tend ), intent(out ), dimension(begchunk:endchunk) :: phys_tend!! These 3 things are in buffer! real(r8), intent(inout) :: cldo(pcols, pver, begchunk:endchunk) ! old cloud real(r8), intent(inout) :: cldn(pcols, pver, begchunk:endchunk) ! new cloud real(r8), intent(inout) :: tcwato(pcols, pver, begchunk:endchunk) ! old temperature real(r8), intent(inout) :: tcwatn(pcols, pver, begchunk:endchunk) ! new temperature real(r8), intent(inout) :: qcwato(pcols, pver, begchunk:endchunk) ! old moisture real(r8), intent(inout) :: qcwatn(pcols, pver, begchunk:endchunk) ! new moisture real(r8), intent(inout) :: lcwato(pcols, pver, begchunk:endchunk) ! cloud liquid water real(r8), intent(inout) :: lcwatn(pcols, pver, begchunk:endchunk) ! cloud liquid water!!---------------------------Local workspace-----------------------------! integer :: i,m,lat,c,lchnk ! indices integer :: lats(pcols) ! array of latitude indices integer :: lons(pcols) ! array of longitude indices integer :: ncol ! number of columns integer :: nstep ! current timestep number integer :: ncdate ! current date in integer format [yyyymmdd] integer :: ncsec ! current time of day [seconds] integer :: yr, mon, day ! year, month, and day components of a date real(r8) :: tsgave ! TS global average#ifdef SPMD real(r8) :: tsgridpt_glob(plon,plat) ! TS global summed at each grid point#endif real(r8), save :: tsgridpt(plon,plat) ! TS summed at each grid point real(r8), save :: tszonal(plat) ! TS summed along each latitude integer, save :: numts ! number of samples for monthly ave real(r8) :: timewtic(pcols,begchunk:endchunk) real(r8) :: timewtoc(pcols,begchunk:endchunk)!*** BAB's FV kludge real(r8) :: tin(pcols, pver, begchunk:endchunk) ! input T, to compute FV output T!----------------------------------------------------------------------- call t_startf ('physpkg_st') nstep = get_nstep()!-----------------------------------------------------------------------! Advance time information!----------------------------------------------------------------------- call advnce () call t_stopf ('physpkg_st')!!-----------------------------------------------------------------------! Tendency physics before flux coupler invokation!-----------------------------------------------------------------------! call t_startf ('bc_physics')!$OMP PARALLEL DO PRIVATE (C) do c=begchunk, endchunk call t_startf ('tphysbc') call tphysbc (ztodt, pblht(1,c), tpert(1,c), & srfflx_state2d(c)%ts, & qpert(1,1,c), surface_state2d(c)%precl, & surface_state2d(c)%precc, surface_state2d(c)%precsl,& surface_state2d(c)%precsc, & srfflx_state2d(c)%asdir, srfflx_state2d(c)%asdif, & srfflx_state2d(c)%aldir, srfflx_state2d(c)%aldif, & snowhland(1,c), & qrs(1,1,c), qrl(1,1,c), surface_state2d(c)%flwds, & fsns(1,c), fsnt(1,c), & flns(1,c), flnt(1,c), srfflx_state2d(c)%lwup, & surface_state2d(c)%srfrad, surface_state2d(c)%sols, & surface_state2d(c)%soll, surface_state2d(c)%solsd, & surface_state2d(c)%solld, & cldo(1,1,c), cldn(1,1,c), tcwato(1,1,c), & tcwatn(1,1,c), qcwato(1,1,c), & qcwatn(1,1,c), lcwato(1,1,c), lcwatn(1,1,c), & phys_state(c), phys_tend(c), & icefrac(1,c),landfrac(1,c),ocnfrac(1,c), tin(1,1,c), & prcsnw(1,c)) call t_stopf ('tphysbc') end do call t_stopf ('bc_physics')#if ( ! defined COUP_CSM )!!-----------------------------------------------------------------------! Determine surface quantities - no flux coupler!-----------------------------------------------------------------------!!! zero surface fluxes at beginning of each time step. Land Ocean and Ice! processes will will write into process specific flux variables! at the end of the time step these separate fluxes will be combined over the! entire grid call srfflx_state_reset(srfflx_state2d) if (.not. aqua_planet) then!! Call land model driving routine!#ifdef TIMING_BARRIERS call t_startf ('sync_tphysbc_lnd') call mpibarrier (mpicom) call t_stopf ('sync_tphysbc_lnd')#endif call t_startf ('atmlnd_drv') call atmlnd_drv(nstep, iradsw, eccen, obliqr, lambm0,& mvelpp,surface_state2d,srfflx_parm2d) call t_stopf ('atmlnd_drv') call update_srf_fluxes(srfflx_state2d,srfflx_parm2d,landfrac) end if ! end of not aqua_planet if block!! Set ocean surface quantities - ocn model internal to atm!#if (defined COUP_SOM) call t_startf('somoce') call somoce (ztodt) call t_stopf('somoce')#else call t_startf('camoce') call camoce(surface_state2d,srfflx_parm2d)!!subprocesses only work on grid points that have some fractional value!for the subprocess type. (ie. camocn only works on grid points that have! > 0. fraction ocean in that box. Setup temp diagnostic variable that! can be used to time weight those boxes that are operated on only for! a portion of the run.! call t_startf('physpkg_st') timewtoc(:,:)=0. do lchnk=begchunk, endchunk do i=1,pcols if (ocnfrac(i,lchnk)> 0.) timewtoc(i,lchnk)=1. end do end do call t_stopf('physpkg_st') call t_stopf('camoce') call update_srf_fluxes(srfflx_state2d,srfflx_parm2d,ocnfrac)!! Set ice surface quantities - icn model internal to atm! call t_startf('camice') call camice(surface_state2d,srfflx_parm2d) call t_stopf('camice') call t_startf('physpkg_st') timewtic(:,:)=0. do lchnk=begchunk, endchunk do i=1,pcols if (icefrac(i,lchnk)> 0.) timewtic(i,lchnk)=1. end do end do call t_stopf('physpkg_st') call update_srf_fluxes(srfflx_state2d,srfflx_parm2d,icefrac)#endif#endif#if ( defined COUP_CSM )!!-----------------------------------------------------------------------! Determine surface quantities using csm flux coupler!-----------------------------------------------------------------------!! If send data to flux coupler only on radiation time steps:! if (flxave) then!! Average the precipitation input to lsm between radiation calls.! call ccsmave(iradsw, nstep, dosw)!! Use solar radiation flag to determine data exchange steps ! with flux coupler. This processes are not independent since ! instantaneous radiative fluxes are passed, valid over the ! interval to the next radiation calculation. The same ! considerations apply to the long and shortwave fluxes, so ! the intervals must be the same. Data is received from the ! coupler one step after it is sent.! if (nstep == 0) then dorecv = .true. dosend = .true. else if (nstep == 1) then dorecv = .false. dosend = .false. else if ( (nstep == 2) .and. (iradsw == 1) ) then dorecv = .true. dosend = dosw else dorecv = dosend dosend = dosw end if endif!! If send data to flux coupler on every time step! if (.not. flxave) then if (nstep /= 1) then dorecv = .true. dosend = .true. else dorecv = .false. dosend = .false. endif endif!! Send/recv data to/from the csm flux coupler.! if (dosend) call ccsmsnd ( ) if (dorecv) call ccsmrcv ( )#endif!!-----------------------------------------------------------------------! Tendency physics after coupler ! Not necessary at terminal timestep.!-----------------------------------------------------------------------! call t_startf ('ac_physics')!$OMP PARALLEL DO PRIVATE (C, NCOL) do c=begchunk,endchunk ncol = get_ncols_p(c)!! surface diagnostics for history files! call diag_surf (c, ncol, srfflx_state2d(c)%shf, srfflx_state2d(c)%lhf, srfflx_state2d(c)%cflx, & srfflx_state2d(c)%tref, trefmxav(1,c), trefmnav(1,c), srfflx_state2d(c)%wsx, srfflx_state2d(c)%wsy, & icefrac(1,c), ocnfrac(1,c), surface_state2d(c)%tssub, srfflx_state2d(c)%ts, sicthk(1,c), & snowhland(1,c),snowhice(1,c), tsnam, landfrac(1,c) ) call t_startf ('tphysac') call tphysac (ztodt, pblht(1,c), qpert(1,1,c), tpert(1,c), srfflx_state2d(c)%shf, & srfflx_state2d(c)%wsx,srfflx_state2d(c)%wsy, srfflx_state2d(c)%cflx, sgh(1,c), srfflx_state2d(c)%lhf, & landfrac(1,c), snowhland(1,c),srfflx_state2d(c)%tref, surface_state2d(c)%precc, surface_state2d(c)%precl, & tin(1,1,c), phys_state(c), phys_tend(c), ocnfrac(1,c)) call t_stopf ('tphysac') end do ! Chunk loop call t_stopf('ac_physics')!!-----------------------------------------------------------------------! Calculate the monthly averaged TS! NOTE: the following is only valid if restart on month boundary! Initialize partial sums of global avg ts to 0.! Sum TS pointwise for this timestep and save for monthly ave TS.!!-----------------------------------------------------------------------! call t_startf('global_ts') if (is_first_step() .or. is_first_restart_step()) then tsgridpt(:,:) = 0. numts = 0 endif! do c=begchunk, endchunk ncol = get_ncols_p(c) call get_lat_all_p(c, ncol, lats) call get_lon_all_p(c, ncol, lons) do i=1,ncol tsgridpt(lons(i),lats(i)) = tsgridpt(lons(i),lats(i)) + srfflx_state2d(c)%ts(i)*gw(lats(i)) enddo enddo! numts = numts + 1 ! Increment number of time samples! if (is_end_curr_month()) then#ifdef SPMD#ifdef TIMING_BARRIERS call t_startf ('sync_tszonal') call mpibarrier (mpicom) call t_stopf ('sync_tszonal')#endif call mpisum(tsgridpt, tsgridpt_glob, plon*plat, mpir8, 0, mpicom) if (masterproc) tsgridpt(:,:) = tsgridpt_glob(:,:) #endif if (masterproc) then call get_curr_date(yr, mon, day, ncsec) ncdate = yr*10000 + mon*100 + day tsgave = 0. do lat=1,plat tszonal(lat) = 0. do i=1,plon tszonal(lat) = tszonal(lat) + tsgridpt(i,lat) end do end do do lat=1,plat tsgave = tsgave + tszonal(lat) end do if (numts.gt.0) tsgave = tsgave/(2.*plon*numts) write(6,800) ' DATE= ', ncdate, ' SEC= ', ncsec, ' TSave= ', tsgave, ' SAMPLES= ', numts800 format (a7,i8.8,a6,i5.5,a8,f10.5,a10,i8) endif tszonal(:) = 0. numts = 0 end if! call t_stopf ('global_ts') return end subroutine physpkg
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?