#ifdef AIX @PROCESS ALIAS_SIZE(805306368) #endif module datm_comp_mod 1,16 ! !USES: use shr_const_mod use shr_sys_mod use shr_kind_mod , only: IN=>SHR_KIND_IN, R8=>SHR_KIND_R8, & CS=>SHR_KIND_CS, CL=>SHR_KIND_CL use shr_file_mod , only: shr_file_getunit, shr_file_getlogunit, shr_file_getloglevel, & shr_file_setlogunit, shr_file_setloglevel, shr_file_setio, & shr_file_freeunit use shr_cal_mod , only: shr_cal_date2eday use shr_mpi_mod , only: shr_mpi_bcast use mct_mod use esmf_mod use perf_mod use shr_strdata_mod use shr_dmodel_mod use shr_pcdf_mod use datm_shr_mod use seq_cdata_mod use seq_infodata_mod use seq_timemgr_mod use seq_flds_indices , only: nflds_a2x, & nflds_x2a use seq_flds_mod , only: seq_flds_a2x_fields, & seq_flds_x2a_fields ! ! !PUBLIC TYPES: implicit none private ! except !-------------------------------------------------------------------------- ! Public interfaces !-------------------------------------------------------------------------- public :: datm_comp_init public :: datm_comp_run public :: datm_comp_final !-------------------------------------------------------------------------- ! Private data !-------------------------------------------------------------------------- !--- other --- character(CS) :: myModelName = 'atm' ! user defined model name integer(IN) :: mpicom integer(IN) :: COMPID ! mct comp id integer(IN) :: my_task ! my task in mpi communicator mpicom integer(IN) :: npes ! total number of tasks integer(IN),parameter :: master_task=0 ! task number of master task integer(IN) :: logunit ! logging unit number character(CL) :: atm_mode ! mode integer(IN) :: dbug = 0 ! debug level (higher is more) logical :: firstcall = .true. ! first call logical logical :: scmMode = .false. ! single column mode real(R8) :: scmLat = shr_const_SPVAL ! single column lat real(R8) :: scmLon = shr_const_SPVAL ! single column lon integer :: phase ! phase of method logical :: read_restart ! start from restart real(R8) :: orbEccen ! orb eccentricity (unit-less) real(R8) :: orbMvelpp ! orb moving vernal eq (radians) real(R8) :: orbLambm0 ! orb mean long of perhelion (radians) real(R8) :: orbObliqr ! orb obliquity (radians) real(R8) :: tbotmax ! units detector real(R8) :: tdewmax ! units detector real(R8) :: anidrmax ! existance detector integer(IN) :: iradsw ! radiation logical character(CL) :: factorFn ! file containing correction factors character(len=*),parameter :: rpfile = 'rpointer.atm' character(len=*),parameter :: nullstr = 'undefined' real(R8),parameter :: aerodep_spval = 1.e29_r8 ! special aerosol deposition real(R8),parameter :: tKFrz = SHR_CONST_TKFRZ real(R8),parameter :: degtorad = SHR_CONST_PI/180.0_R8 real(R8),parameter :: pstd = SHR_CONST_PSTD ! standard pressure ~ Pa real(R8),parameter :: stebol = SHR_CONST_STEBOL ! Stefan-Boltzmann constant ~ W/m^2/K^4 real(R8),parameter :: rdair = SHR_CONST_RDAIR ! dry air gas constant ~ J/K/kg real(R8),parameter :: avg_c0 = 61.846_R8 real(R8),parameter :: avg_c1 = 1.107_R8 real(R8),parameter :: amp_c0 = -21.841_R8 real(R8),parameter :: amp_c1 = -0.447_R8 real(R8),parameter :: phs_c0 = 0.298_R8 real(R8),parameter :: dLWarc = -5.000_R8 real(R8) ,save :: dTarc(12) data dTarc / 0.49_R8, 0.06_R8,-0.73_R8, -0.89_R8,-0.77_R8,-1.02_R8, & & -1.99_R8,-0.91_R8, 1.72_R8, 2.30_R8, 1.81_R8, 1.06_R8/ integer(IN) :: kz,ku,kv,ktbot,kptem,kshum,kdens,kpbot,kpslv,klwdn integer(IN) :: krc,krl,ksc,ksl,kswndr,kswndf,kswvdr,kswvdf,kswnet,kco2p,kco2d integer(IN) :: kbid,kbod,kbiw,koid,kood,koiw,kdw1,kdw2,kdw3,kdw4,kdd1,kdd2,kdd3,kdd4 integer(IN) :: kanidr,kanidf,kavsdr,kavsdf integer(IN) :: stbot,swind,sz,spbot,sshum,stdew,srh,slwdn,sswdn,sswdndf,sswdndr integer(IN) :: sprecc,sprecl,sprecn,sco2p,sco2d,sswup,sprec type(shr_strdata_type) :: SDATM type(mct_rearr) :: rearr type(mct_avect) :: avstrm ! av of data from stream integer(IN), pointer :: imask(:) real(R8), pointer :: yc(:) real(R8), pointer :: windFactor(:) real(R8), pointer :: winddFactor(:) real(R8), pointer :: qsatFactor(:) integer(IN),parameter :: ktrans = 56 character(16),parameter :: avofld(1:ktrans) = & (/"Sa_z ","Sa_u ","Sa_v ","Sa_tbot ", & "Sa_ptem ","Sa_shum ","Sa_dens ","Sa_pbot ", & "Sa_pslv ","Faxa_lwdn ","Faxa_rainc ","Faxa_rainl ", & "Faxa_snowc ","Faxa_snowl ","Faxa_swndr ","Faxa_swvdr ", & "Faxa_swndf ","Faxa_swvdf ","Faxa_swnet ","Sa_co2prog ", & "Sa_co2diag ","Faxa_bcphidry ","Faxa_bcphodry ","Faxa_bcphiwet ", & "Faxa_ocphidry ","Faxa_ocphodry ","Faxa_ocphiwet ","Faxa_dstwet1 ", & "Faxa_dstwet2 ","Faxa_dstwet3 ","Faxa_dstwet4 ","Faxa_dstdry1 ", & "Faxa_dstdry2 ","Faxa_dstdry3 ","Faxa_dstdry4 ", & "Sx_tref ","Sx_qref ","Sx_avsdr ","Sx_anidr ", & "Sx_avsdf ","Sx_anidf ","Sx_t ","So_t ", & "Sx_snowh ","Sx_lfrac ","Sx_ifrac ","Sx_ofrac ", & "Faxx_taux ","Faxx_tauy ","Faxx_lat ","Faxx_sen ", & "Faxx_lwup ","Faxx_evap ","Faxx_fco2_lnd ","Faxx_fco2_ocn ", & "Faxx_fdms " /) character(16),parameter :: avifld(1:ktrans) = & (/"z ","u ","v ","tbot ", & "ptem ","shum ","dens ","pbot ", & "pslv ","lwdn ","rainc ","rainl ", & "snowc ","snowl ","swndr ","swvdr ", & "swndf ","swvdf ","swnet ","co2prog ", & "co2diag ","bcphidry ","bcphodry ","bcphiwet ", & "ocphidry ","ocphodry ","ocphiwet ","dstwet1 ", & "dstwet2 ","dstwet3 ","dstwet4 ","dstdry1 ", & "dstdry2 ","dstdry3 ","dstdry4 ", & "tref ","qref ","avsdr ","anidr ", & "avsdf ","anidf ","ts ","to ", & "snowh ","lfrac ","ifrac ","ofrac ", & "taux ","tauy ","lat ","sen ", & "lwup ","evap ","co2lnd ","co2ocn ", & "dms " /) integer(IN),parameter :: ktranss = 18 character(16),parameter :: stofld(1:ktranss) = & (/"strm_tbot ","strm_wind ","strm_z ","strm_pbot ", & "strm_shum ","strm_tdew ","strm_rh ","strm_lwdn ", & "strm_swdn ","strm_swdndf ","strm_swdndr ","strm_precc ", & "strm_precl ","strm_precn ","strm_co2prog ","strm_co2diag ", & "strm_swup ","strm_prec " /) character(16),parameter :: stifld(1:ktranss) = & (/"tbot ","wind ","z ","pbot ", & "shum ","tdew ","rh ","lwdn ", & "swdn ","swdndf ","swdndr ","precc ", & "precl ","precn ","co2prog ","co2diag ", & "swup ","prec " /) save !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CONTAINS !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !=============================================================================== !BOP =========================================================================== ! ! !IROUTINE: datm_comp_init ! ! !DESCRIPTION: ! initialize data atm model ! ! !REVISION HISTORY: ! ! !INTERFACE: ------------------------------------------------------------------ subroutine datm_comp_init( EClock, cdata, x2a, a2x, NLFilename ) 2,49 implicit none ! !INPUT/OUTPUT PARAMETERS: type(ESMF_Clock) , intent(in) :: EClock type(seq_cdata) , intent(inout) :: cdata type(mct_aVect) , intent(inout) :: x2a, a2x character(len=*), optional , intent(in) :: NLFilename ! Namelist filename !EOP !--- local variables --- integer(IN) :: n,k ! generic counters integer(IN) :: ierr ! error code integer(IN) :: gsize ! global size integer(IN) :: lsize ! local size integer(IN) :: shrlogunit, shrloglev ! original log unit and level integer(IN) :: nunit ! unit number integer(IN) :: kmask ! field reference integer(IN) :: klat ! field reference integer(IN) :: kfld ! fld index integer(IN) :: cnt ! counter logical :: atm_present ! flag logical :: atm_prognostic ! flag type(seq_infodata_type), pointer :: infodata type(mct_gsMap) , pointer :: gsMap type(mct_gGrid) , pointer :: ggrid character(CL) :: filePath ! generic file path character(CL) :: fileName ! generic file name character(CS) :: timeName ! domain file: time variable name character(CS) :: lonName ! domain file: lon variable name character(CS) :: latName ! domain file: lat variable name character(CS) :: maskName ! domain file: mask variable name character(CS) :: areaName ! domain file: area variable name integer(IN) :: yearFirst ! first year to use in data stream integer(IN) :: yearLast ! last year to use in data stream integer(IN) :: yearAlign ! data year that aligns with yearFirst character(CL) :: atm_in ! dshr atm namelist character(CL) :: decomp ! decomp strategy character(CL) :: rest_file ! restart filename character(CL) :: rest_file_strm ! restart filename for streams character(CL) :: restfilm ! model restart file namelist character(CL) :: restfils ! stream restart file namelist logical :: exists ! filename existance integer(IN) :: nu ! unit number integer(IN) :: idt ! integer timestep integer(IN) :: CurrentYMD ! model date integer(IN) :: CurrentTOD ! model sec into model date integer(IN) :: stepno ! step number real(R8) :: nextsw_cday ! calendar of next atm sw character(CL) :: flds_strm logical :: presaero ! true => send valid prescribe aero fields to coupler !----- define namelist ----- namelist / datm_nml / & atm_in, decomp, iradsw, factorFn, restfilm, restfils, presaero !--- formats --- character(*), parameter :: F00 = "('(datm_comp_init) ',8a)" character(*), parameter :: F0L = "('(datm_comp_init) ',a, l)" character(*), parameter :: F01 = "('(datm_comp_init) ',a,5i8)" character(*), parameter :: F02 = "('(datm_comp_init) ',a,4es13.6)" character(*), parameter :: F03 = "('(datm_comp_init) ',a,i8,a)" character(*), parameter :: F04 = "('(datm_comp_init) ',2a,2i8,'s')" character(*), parameter :: F05 = "('(datm_comp_init) ',a,2f10.4)" character(*), parameter :: F90 = "('(datm_comp_init) ',73('='))" character(*), parameter :: F91 = "('(datm_comp_init) ',73('-'))" character(*), parameter :: subName = "(datm_comp_init) " !------------------------------------------------------------------------------- call t_startf('DATM_INIT') ! Set cdata pointers call seq_cdata_setptrs(cdata, ID=COMPID, mpicom=mpicom, & gsMap=gsmap, dom=ggrid, infodata=infodata) call seq_infodata_getData(infodata,atm_phase=phase) if (phase == 1) then ! Determine communicator groups and sizes call mpi_comm_rank(mpicom, my_task, ierr) call mpi_comm_size(mpicom, npes, ierr) !--- open log file --- if (my_task == master_task) then logUnit = shr_file_getUnit() call shr_file_setIO('atm_modelio.nml',logUnit) else logUnit = 6 endif endif !---------------------------------------------------------------------------- ! Reset shr logging to my log file !---------------------------------------------------------------------------- call shr_file_getLogUnit (shrlogunit) call shr_file_getLogLevel(shrloglev) call shr_file_setLogUnit (logUnit) if (phase == 1) then !---------------------------------------------------------------------------- ! Set a Few Defaults !---------------------------------------------------------------------------- call seq_infodata_getData(infodata,single_column=scmMode, & & scmlat=scmlat, scmlon=scmLon) call seq_infodata_GetData(infodata,orb_eccen=orbEccen,orb_mvelpp=orbMvelpp, & orb_lambm0=orbLambm0,orb_obliqr=orbObliqr ) atm_present = .false. atm_prognostic = .false. call seq_infodata_GetData(infodata,read_restart=read_restart) !---------------------------------------------------------------------------- ! Read datm_in !---------------------------------------------------------------------------- call t_startf('datm_readnml') filename = "datm_in" atm_in = "unset" decomp = "1d" iradsw = 0 factorFn = 'null' restfilm = trim(nullstr) restfils = trim(nullstr) presaero = .false. if (my_task == master_task) then nunit = shr_file_getUnit() ! get unused unit number open (nunit,file=trim(filename),status="old",action="read") read (nunit,nml=datm_nml,iostat=ierr) close(nunit) call shr_file_freeUnit(nunit) if (ierr > 0) then write(logunit,F01) 'ERROR: reading input namelist, '//trim(filename)//' iostat=',ierr call shr_sys_abort(subName//': namelist read error '//trim(filename)) end if write(logunit,F00)' atm_in = ',trim(atm_in) write(logunit,F00)' decomp = ',trim(decomp) write(logunit,F01)' iradsw = ',iradsw write(logunit,F00)' factorFn = ',trim(factorFn) write(logunit,F00)' restfilm = ',trim(restfilm) write(logunit,F00)' restfils = ',trim(restfils) write(logunit,F0L)' presaero = ',presaero endif call shr_mpi_bcast(atm_in,mpicom,'atm_in') call shr_mpi_bcast(decomp,mpicom,'decomp') call shr_mpi_bcast(iradsw,mpicom,'iradsw') call shr_mpi_bcast(factorFn,mpicom,'factorFn') call shr_mpi_bcast(restfilm,mpicom,'restfilm') call shr_mpi_bcast(restfils,mpicom,'restfils') call shr_mpi_bcast(presaero,mpicom,'presaero') rest_file = trim(restfilm) rest_file_strm = trim(restfils) !---------------------------------------------------------------------------- ! Read dshr namelist !---------------------------------------------------------------------------- call shr_strdata_readnml(SDATM,trim(atm_in),mpicom=mpicom) !---------------------------------------------------------------------------- ! Validate mode !---------------------------------------------------------------------------- atm_mode = trim(SDATM%dataMode) ! check that we know how to handle the mode if (trim(atm_mode) == 'NULL' .or. & trim(atm_mode) == 'TN460' .or. & trim(atm_mode) == 'CORE2' .or. & trim(atm_mode) == 'CLMNCEP' .or. & trim(atm_mode) == 'CPLHIST' .or. & trim(atm_mode) == 'COPYALL') then if (my_task == master_task) & write(logunit,F00) ' atm mode = ',trim(atm_mode) else write(logunit,F00) ' ERROR illegal atm mode = ',trim(atm_mode) call shr_sys_abort() endif call t_stopf('datm_readnml') !---------------------------------------------------------------------------- ! Initialize datasets !---------------------------------------------------------------------------- call t_startf('datm_strdata_init') if (trim(atm_mode) /= 'NULL') then atm_present = .true. if (scmmode) then if (my_task == master_task) & write(logunit,F05) ' scm lon lat = ',scmlon,scmlat call shr_strdata_init(SDATM,mpicom,compid,name='atm', & scmmode=scmmode,scmlon=scmlon,scmlat=scmlat) else call shr_strdata_init(SDATM,mpicom,compid,name='atm') endif !--- overwrite mask and frac --- k = mct_aVect_indexRA(SDATM%grid%data,'mask') SDATM%grid%data%rAttr(k,:) = 1.0_R8 k = mct_aVect_indexRA(SDATM%grid%data,'frac') SDATM%grid%data%rAttr(k,:) = 1.0_R8 !--- set data needed for cosz t-interp method --- call seq_timemgr_EClockGetData( EClock, dtime=idt ) call shr_strdata_setOrbs(SDATM,orbEccen,orbMvelpp,orbLambm0,orbObliqr,idt) endif if (my_task == master_task) then call shr_strdata_print(SDATM,'ATM data') endif call t_stopf('datm_strdata_init') !---------------------------------------------------------------------------- ! Set flag to specify data components !---------------------------------------------------------------------------- call seq_infodata_PutData(infodata, & atm_present=atm_present, atm_prognostic=atm_prognostic, & atm_nx=SDATM%nxg, atm_ny=SDATM%nyg ) call seq_infodata_PutData( infodata, atm_aero=presaero) !---------------------------------------------------------------------------- ! Initialize MCT global seg map, 1d decomp !---------------------------------------------------------------------------- call t_startf('datm_initgsmaps') if (my_task == master_task) write(logunit,F00) ' initialize gsmaps' call shr_sys_flush(logunit) call shr_dmodel_gsmapcreate(gsmap,SDATM%nxg*SDATM%nyg,compid,mpicom,decomp) lsize = mct_gsmap_lsize(gsmap,mpicom) if (atm_present) then call mct_rearr_init(SDATM%gsmap,gsmap,mpicom,rearr) endif call t_stopf('datm_initgsmaps') !---------------------------------------------------------------------------- ! Initialize MCT domain !---------------------------------------------------------------------------- call t_startf('datm_initmctdom') if (my_task == master_task) write(logunit,F00) 'copy domains' call shr_sys_flush(logunit) if (atm_present) call shr_dmodel_rearrGGrid(SDATM%grid, ggrid, gsmap, rearr, mpicom) call t_stopf('datm_initmctdom') !---------------------------------------------------------------------------- ! Initialize MCT attribute vectors !---------------------------------------------------------------------------- call t_startf('datm_initmctavs') if (my_task == master_task) write(logunit,F00) 'allocate AVs' call shr_sys_flush(logunit) call mct_aVect_init(a2x, rList=seq_flds_a2x_fields, lsize=lsize) call mct_aVect_zero(a2x) kz = mct_aVect_indexRA(a2x,'Sa_z') ku = mct_aVect_indexRA(a2x,'Sa_u') kv = mct_aVect_indexRA(a2x,'Sa_v') ktbot = mct_aVect_indexRA(a2x,'Sa_tbot') kptem = mct_aVect_indexRA(a2x,'Sa_ptem') kshum = mct_aVect_indexRA(a2x,'Sa_shum') kdens = mct_aVect_indexRA(a2x,'Sa_dens') kpbot = mct_aVect_indexRA(a2x,'Sa_pbot') kpslv = mct_aVect_indexRA(a2x,'Sa_pslv') klwdn = mct_aVect_indexRA(a2x,'Faxa_lwdn') krc = mct_aVect_indexRA(a2x,'Faxa_rainc') krl = mct_aVect_indexRA(a2x,'Faxa_rainl') ksc = mct_aVect_indexRA(a2x,'Faxa_snowc') ksl = mct_aVect_indexRA(a2x,'Faxa_snowl') kswndr= mct_aVect_indexRA(a2x,'Faxa_swndr') kswndf= mct_aVect_indexRA(a2x,'Faxa_swndf') kswvdr= mct_aVect_indexRA(a2x,'Faxa_swvdr') kswvdf= mct_aVect_indexRA(a2x,'Faxa_swvdf') kswnet= mct_aVect_indexRA(a2x,'Faxa_swnet') kco2p = mct_aVect_indexRA(a2x,'Sa_co2prog',perrWith='quiet') kco2d = mct_aVect_indexRA(a2x,'Sa_co2diag',perrWith='quiet') kbid = mct_aVect_indexRA(a2x,'Faxa_bcphidry') kbod = mct_aVect_indexRA(a2x,'Faxa_bcphodry') kbiw = mct_aVect_indexRA(a2x,'Faxa_bcphiwet') koid = mct_aVect_indexRA(a2x,'Faxa_ocphidry') kood = mct_aVect_indexRA(a2x,'Faxa_ocphodry') koiw = mct_aVect_indexRA(a2x,'Faxa_ocphiwet') kdd1 = mct_aVect_indexRA(a2x,'Faxa_dstdry1') kdd2 = mct_aVect_indexRA(a2x,'Faxa_dstdry2') kdd3 = mct_aVect_indexRA(a2x,'Faxa_dstdry3') kdd4 = mct_aVect_indexRA(a2x,'Faxa_dstdry4') kdw1 = mct_aVect_indexRA(a2x,'Faxa_dstwet1') kdw2 = mct_aVect_indexRA(a2x,'Faxa_dstwet2') kdw3 = mct_aVect_indexRA(a2x,'Faxa_dstwet3') kdw4 = mct_aVect_indexRA(a2x,'Faxa_dstwet4') call mct_aVect_init(x2a, rList=seq_flds_x2a_fields, lsize=lsize) call mct_aVect_zero(x2a) kanidr = mct_aVect_indexRA(x2a,'Sx_anidr') kanidf = mct_aVect_indexRA(x2a,'Sx_anidf') kavsdr = mct_aVect_indexRA(x2a,'Sx_avsdr') kavsdf = mct_aVect_indexRA(x2a,'Sx_avsdf') !--- figure out what's on the streams --- cnt = 0 flds_strm = '' do n = 1,SDATM%nstreams do k = 1,ktranss kfld = mct_aVect_indexRA(SDATM%avs(n),trim(stifld(k)),perrWith='quiet') if (kfld > 0) then cnt = cnt + 1 if (cnt == 1) then flds_strm = trim(stofld(k)) else flds_strm = trim(flds_strm)//':'//trim(stofld(k)) endif endif enddo enddo if (my_task == master_task) write(logunit,F00) ' flds_strm = ',trim(flds_strm) call shr_sys_flush(logunit) call mct_aVect_init(avstrm, rList=flds_strm, lsize=lsize) call mct_aVect_zero(avstrm) stbot = mct_aVect_indexRA(avstrm,'strm_tbot',perrWith='quiet') swind = mct_aVect_indexRA(avstrm,'strm_wind',perrWith='quiet') sz = mct_aVect_indexRA(avstrm,'strm_z',perrWith='quiet') spbot = mct_aVect_indexRA(avstrm,'strm_pbot',perrWith='quiet') sshum = mct_aVect_indexRA(avstrm,'strm_shum',perrWith='quiet') stdew = mct_aVect_indexRA(avstrm,'strm_tdew',perrWith='quiet') srh = mct_aVect_indexRA(avstrm,'strm_rh',perrWith='quiet') slwdn = mct_aVect_indexRA(avstrm,'strm_lwdn',perrWith='quiet') sswdn = mct_aVect_indexRA(avstrm,'strm_swdn',perrWith='quiet') sswdndf= mct_aVect_indexRA(avstrm,'strm_swdndf',perrWith='quiet') sswdndr= mct_aVect_indexRA(avstrm,'strm_swdndr',perrWith='quiet') sprecc = mct_aVect_indexRA(avstrm,'strm_precc',perrWith='quiet') sprecl = mct_aVect_indexRA(avstrm,'strm_precl',perrWith='quiet') sprecn = mct_aVect_indexRA(avstrm,'strm_precn',perrWith='quiet') sco2p = mct_aVect_indexRA(avstrm,'strm_co2p',perrWith='quiet') sco2d = mct_aVect_indexRA(avstrm,'strm_co2d',perrWith='quiet') sswup = mct_aVect_indexRA(avstrm,'strm_swup',perrWith='quiet') sprec = mct_aVect_indexRA(avstrm,'strm_prec',perrWith='quiet') allocate(imask(lsize)) allocate(yc(lsize)) allocate(windFactor(lsize)) allocate(winddFactor(lsize)) allocate(qsatFactor(lsize)) kmask = mct_aVect_indexRA(ggrid%data,'mask') imask(:) = nint(ggrid%data%rAttr(kmask,:)) klat = mct_aVect_indexRA(ggrid%data,'lat') yc(:) = ggrid%data%rAttr(klat,:) call t_stopf('datm_initmctavs') !---------------------------------------------------------------------------- ! Read restart !---------------------------------------------------------------------------- if (read_restart) then if (trim(rest_file) == trim(nullstr) .and. & trim(rest_file_strm) == trim(nullstr)) then if (my_task == master_task) then write(logunit,F00) ' restart filenames from rpointer' call shr_sys_flush(logunit) inquire(file=trim(rpfile),exist=exists) if (.not.exists) then write(logunit,F00) ' ERROR: rpointer file does not exist' call shr_sys_abort(trim(subname)//' ERROR: rpointer file missing') endif nu = shr_file_getUnit() open(nu,file=trim(rpfile),form='formatted') read(nu,'(a)') rest_file read(nu,'(a)') rest_file_strm close(nu) call shr_file_freeUnit(nu) inquire(file=trim(rest_file_strm),exist=exists) endif call shr_mpi_bcast(rest_file,mpicom,'rest_file') call shr_mpi_bcast(rest_file_strm,mpicom,'rest_file_strm') else ! use namelist already read if (my_task == master_task) then write(logunit,F00) ' restart filenames from namelist ' call shr_sys_flush(logunit) inquire(file=trim(rest_file_strm),exist=exists) endif endif call shr_mpi_bcast(exists,mpicom,'exists') ! if (my_task == master_task) write(logunit,F00) ' reading ',trim(rest_file) ! call shr_pcdf_readwrite('read',trim(rest_file),mpicom,gsmap,rf1=somtp,rf1n='somtp') if (exists) then if (my_task == master_task) write(logunit,F00) ' reading ',trim(rest_file_strm) call shr_strdata_restRead(trim(rest_file_strm),SDATM,mpicom) else if (my_task == master_task) write(logunit,F00) ' file not found, skipping ',trim(rest_file_strm) endif call shr_sys_flush(logunit) endif if (read_restart) then call seq_timemgr_EClockGetData( EClock, curr_ymd=CurrentYMD, curr_tod=CurrentTOD) call seq_timemgr_EClockGetData( EClock, stepno=stepno, dtime=idt ) nextsw_cday = datm_shr_getNextRadCDay( CurrentYMD, CurrentTOD, stepno, idt, iradsw ) else call seq_timemgr_EClockGetData( EClock, curr_cday=nextsw_cday, stepno=stepno ) endif call seq_infodata_PutData(infodata, nextsw_cday=nextsw_cday ) else call seq_timemgr_EClockGetData( EClock, curr_ymd=CurrentYMD, curr_tod=CurrentTOD) call seq_timemgr_EClockGetData( EClock, stepno=stepno, dtime=idt) nextsw_cday = datm_shr_getNextRadCDay( CurrentYMD, CurrentTOD, stepno, idt, iradsw ) call seq_infodata_PutData(infodata, nextsw_cday=nextsw_cday ) endif !---------------------------------------------------------------------------- ! Set initial atm state, needed for CCSM atm initialization !---------------------------------------------------------------------------- call t_adj_detailf(+2) call datm_comp_run( EClock, cdata, x2a, a2x) call t_adj_detailf(-2) !---------------------------------------------------------------------------- ! Reset shr logging to original values !---------------------------------------------------------------------------- if (my_task == master_task) write(logunit,F00) 'datm_comp_init done' call shr_sys_flush(logunit) call shr_file_setLogUnit (shrlogunit) call shr_file_setLogLevel(shrloglev) call shr_sys_flush(logunit) call t_stopf('DATM_INIT') end subroutine datm_comp_init !=============================================================================== !BOP =========================================================================== ! ! !IROUTINE: datm_comp_run ! ! !DESCRIPTION: ! run method for dead atm model ! ! !REVISION HISTORY: ! ! !INTERFACE: ------------------------------------------------------------------ subroutine datm_comp_run( EClock, cdata, x2a, a2x) 2,37 implicit none ! !INPUT/OUTPUT PARAMETERS: type(ESMF_Clock) ,intent(in) :: EClock type(seq_cdata) ,intent(inout) :: cdata type(mct_aVect) ,intent(inout) :: x2a ! driver -> dead type(mct_aVect) ,intent(inout) :: a2x ! dead -> driver !EOP !--- local --- type(mct_gsMap) , pointer :: gsMap type(mct_gGrid) , pointer :: ggrid integer(IN) :: CurrentYMD ! model date integer(IN) :: CurrentTOD ! model sec into model date integer(IN) :: yy,mm,dd ! year month day integer(IN) :: n ! indices integer(IN) :: lsize ! size of attr vect integer(IN) :: shrlogunit, shrloglev ! original log unit and level logical :: mssrmlf ! remove old data integer(IN) :: idt ! integer timestep real(R8) :: dt ! timestep logical :: write_restart ! restart now character(CL) :: case_name ! case name character(CL) :: rest_file ! restart_file character(CL) :: rest_file_strm ! restart_file integer(IN) :: nu ! unit number integer(IN) :: stepno ! step number real(R8) :: nextsw_cday ! calendar of next atm sw integer(IN) :: eday ! elapsed day real(R8) :: rday ! elapsed day real(R8) :: cosFactor ! cosine factor real(R8) :: factor ! generic/temporary correction factor real(R8) :: avg_alb ! average albedo real(R8) :: tMin ! minimum temperature !--- temporaries real(R8) :: uprime,vprime,swndr,swndf,swvdr,swvdf,ratio_rvrf real(R8) :: tbot,pbot,rtmp,vp,ea,e,qsat,frac,qsatT type(seq_infodata_type), pointer :: infodata character(*), parameter :: F00 = "('(datm_comp_run) ',8a)" character(*), parameter :: F04 = "('(datm_comp_run) ',2a,2i8,'s')" character(*), parameter :: subName = "(datm_comp_run) " !------------------------------------------------------------------------------- call t_startf('DATM_RUN') call t_startf('datm_run1') !---------------------------------------------------------------------------- ! Reset shr logging to my log file !---------------------------------------------------------------------------- call shr_file_getLogUnit (shrlogunit) call shr_file_getLogLevel(shrloglev) call shr_file_setLogUnit (logUnit) call seq_cdata_setptrs(cdata, gsMap=gsmap, dom=ggrid) call seq_cdata_setptrs(cdata, infodata=infodata) call seq_timemgr_EClockGetData( EClock, curr_ymd=CurrentYMD, curr_tod=CurrentTOD) call seq_timemgr_EClockGetData( EClock, curr_yr=yy, curr_mon=mm, curr_day=dd) call seq_timemgr_EClockGetData( EClock, stepno=stepno, dtime=idt) dt = idt * 1.0_r8 write_restart = seq_timemgr_RestartAlarmIsOn(EClock) call t_stopf('datm_run1') !-------------------- ! ADVANCE ATM !-------------------- call t_barrierf('datm_BARRIER',mpicom) call t_startf('datm') nextsw_cday = datm_shr_getNextRadCDay( CurrentYMD, CurrentTOD, stepno, idt, iradsw ) call seq_infodata_PutData(infodata, nextsw_cday=nextsw_cday ) !--- copy all fields from streams to a2x as default --- if (trim(atm_mode) /= 'NULL') then call t_startf('datm_strdata_advance') call shr_strdata_advance(SDATM,currentYMD,currentTOD,mpicom,'datm') call t_stopf('datm_strdata_advance') call t_barrierf('datm_scatter_BARRIER',mpicom) call t_startf('datm_scatter') if (trim(atm_mode) /= 'COPYALL') then lsize = mct_avect_lsize(a2x) do n = 1,lsize a2x%rAttr(kbid,n) = aerodep_spval a2x%rAttr(kbod,n) = aerodep_spval a2x%rAttr(kbiw,n) = aerodep_spval a2x%rAttr(koid,n) = aerodep_spval a2x%rAttr(kood,n) = aerodep_spval a2x%rAttr(koiw,n) = aerodep_spval a2x%rAttr(kdd1,n) = aerodep_spval a2x%rAttr(kdd2,n) = aerodep_spval a2x%rAttr(kdd3,n) = aerodep_spval a2x%rAttr(kdd4,n) = aerodep_spval a2x%rAttr(kdw1,n) = aerodep_spval a2x%rAttr(kdw2,n) = aerodep_spval a2x%rAttr(kdw3,n) = aerodep_spval a2x%rAttr(kdw4,n) = aerodep_spval enddo endif do n = 1,SDATM%nstreams call shr_dmodel_translateAV(SDATM%avs(n),a2x,avifld,avofld,rearr) enddo do n = 1,SDATM%nstreams call shr_dmodel_translateAV(SDATM%avs(n),avstrm,stifld,stofld,rearr) enddo call t_stopf('datm_scatter') else call mct_aVect_zero(a2x) endif call t_startf('datm_mode') select case (trim(atm_mode)) case('COPYALL') ! do nothing extra case('CPLHIST') ! do nothing extra case('TN460') if (firstcall) then if (sprec < 1 .or. sswdn < 1 .or. sswup < 1) then write(logunit,F00) ' ERROR: prec swdn and swup must be in streams for TN460' call shr_sys_abort(trim(subname)//' ERROR: prec swdn and swup must be in streams for TN460') endif call datm_shr_TN460getFactors(factorFn,windFactor,qsatFactor, & mpicom,compid,gsmap,ggrid,SDATM%nxg,SDATM%nyg) endif call shr_cal_date2eday(currentYMD,eday) rday = mod(eday,365) + real(currentTOD)/SHR_CONST_CDAY cosfactor = cos((2.0_R8*SHR_CONST_PI*rday)/365 - phs_c0) lsize = mct_avect_lsize(a2x) do n = 1,lsize a2x%rAttr(kz,n) = 10.0_R8 !--- correction to NCEP winds based on QSCAT --- a2x%rAttr(ku,n) = a2x%rAttr(ku,n)*windFactor(n) a2x%rAttr(kv,n) = a2x%rAttr(kv,n)*windFactor(n) !--- density, tbot, & pslv taken directly from input stream, set pbot --- ! a2x%rAttr(kdens,n) = <copied from input streams bundle> ! a2x%rAttr(ktbot,n) = <copied from input streams bundle> ! a2x%rAttr(kpslv,n) = <copied from input streams bundle> a2x%rAttr(kpbot,n) = a2x%rAttr(kpslv,n) !--- correction to NCEP Arctic & Antarctic air T & potential T --- if ( yc(n) < -60.0_R8 ) then tMin = (avg_c0 + avg_c1*yc(n)) + (amp_c0 + amp_c1*yc(n))*cosFactor + tKFrz a2x%rAttr(ktbot,n) = max(a2x%rAttr(ktbot,n), tMin) else if ( yc(n) > 60.0_R8 ) then factor = MIN(1.0_R8, 0.1_R8*(yc(n)-60.0_R8) ) a2x%rAttr(ktbot,n) = a2x%rAttr(ktbot,n) + factor * dTarc(mm) endif a2x%rAttr(kptem,n) = a2x%rAttr(ktbot,n) !--- correction to NCEP relative humidity for heat budget balance --- qsatT = 640380.0_R8/ exp(5107.4_R8/a2x%rAttr(ktbot,n)) a2x%rAttr(kshum,n) = a2x%rAttr(kshum,n) - & (qsatT)*qsatFactor(n)/(100.0_R8*a2x%rAttr(kdens,n)) !------------------------------------------------------------------------- ! PRECIPITATION DATA !------------------------------------------------------------------------- avstrm%rAttr(sprec,n) = avstrm%rAttr(sprec,n)/86400.0_R8 ! convert mm/day to kg/m^2/s avstrm%rAttr(sprec,n) = (avstrm%rAttr(sprec,n)*1.14168_R8)+7.44923e-07_R8 ! correction to GXGXS for water budget a2x%rAttr(krc,n) = 0.0_R8 ! default zero a2x%rAttr(ksc,n) = 0.0_R8 if (a2x%rAttr(ktbot,n) < tKFrz ) then ! assign precip to rain/snow components a2x%rAttr(krl,n) = 0.0_R8 a2x%rAttr(ksl,n) = avstrm%rAttr(sprec,n) else a2x%rAttr(krl,n) = avstrm%rAttr(sprec,n) a2x%rAttr(ksl,n) = 0.0_R8 endif !------------------------------------------------------------------------- ! RADIATION DATA !------------------------------------------------------------------------- !--- fabricate required swdn components from net swdn --- a2x%rAttr(kswvdr,n) = avstrm%rAttr(sswdn,n)*(0.28_R8) a2x%rAttr(kswndr,n) = avstrm%rAttr(sswdn,n)*(0.31_R8) a2x%rAttr(kswvdf,n) = avstrm%rAttr(sswdn,n)*(0.24_R8) a2x%rAttr(kswndf,n) = avstrm%rAttr(sswdn,n)*(0.17_R8) !--- compute net short-wave based on LY08 latitudinally-varying albedo --- if (firstcall) then a2x%rAttr(kswnet,n) = avstrm%rAttr(sswdn,n)-avstrm%rAttr(sswup,n) else avg_alb = (x2a%rAttr(kavsdr,n) + x2a%rAttr(kanidr,n) + & x2a%rAttr(kavsdf,n) + x2a%rAttr(kanidf,n)) * 0.25_R8 a2x%rAttr(kswnet,n) = avstrm%rAttr(sswdn,n)*(1.0_R8 - avg_alb) endif !--- corrections to GISS sswdn for heat budget balancing --- factor = 1.0_R8 if ( -60.0_R8 < yc(n) .and. yc(n) < -50.0_R8 ) then factor = 1.0_R8 - (yc(n) + 60.0_R8)*(0.05_R8/10.0_R8) else if ( -50.0_R8 < yc(n) .and. yc(n) < 30.0_R8 ) then factor = 0.95_R8 else if ( 30.0_R8 < yc(n) .and. yc(n) < 40._R8 ) then factor = 1.0_R8 - (40.0_R8 - yc(n))*(0.05_R8/10.0_R8) endif a2x%rAttr(kswnet,n) = a2x%rAttr(kswnet,n)*factor a2x%rAttr(kswvdr,n) = a2x%rAttr(kswvdr,n)*factor a2x%rAttr(kswndr,n) = a2x%rAttr(kswndr,n)*factor a2x%rAttr(kswvdf,n) = a2x%rAttr(kswvdf,n)*factor a2x%rAttr(kswndf,n) = a2x%rAttr(kswndf,n)*factor !--- correction to GISS lwdn in Arctic --- if ( yc(n) > 60._R8 ) then factor = MIN(1.0_R8, 0.1_R8*(yc(n)-60.0_R8) ) a2x%rAttr(klwdn,n) = a2x%rAttr(klwdn,n) + factor * dLWarc endif enddo ! lsize case('CORE2') if (firstcall) then if (sprec < 1 .or. sswdn < 1) then write(logunit,F00) ' ERROR: prec and swdn must be in streams for CORE2' call shr_sys_abort(trim(subname)//' ERROR: prec and swdn must be in streams for CORE2') endif call datm_shr_CORE2getFactors(factorFn,windFactor,winddFactor,qsatFactor, & mpicom,compid,gsmap,ggrid,SDATM%nxg,SDATM%nyg) endif call shr_cal_date2eday(currentYMD,eday) rday = mod(eday,365) + real(currentTOD)/SHR_CONST_CDAY cosfactor = cos((2.0_R8*SHR_CONST_PI*rday)/365 - phs_c0) lsize = mct_avect_lsize(a2x) do n = 1,lsize a2x%rAttr(kz,n) = 10.0_R8 !--- correction to NCEP winds based on QSCAT --- uprime = a2x%rAttr(ku,n)*windFactor(n) vprime = a2x%rAttr(kv,n)*windFactor(n) a2x%rAttr(ku,n) = uprime*cos(winddFactor(n)*degtorad)- & vprime*sin(winddFactor(n)*degtorad) a2x%rAttr(kv,n) = uprime*sin(winddFactor(n)*degtorad)+ & vprime*cos(winddFactor(n)*degtorad) !--- density, tbot, & pslv taken directly from input stream, set pbot --- ! a2x%rAttr(kdens,n) = <copied from input streams bundle> ! a2x%rAttr(ktbot,n) = <copied from input streams bundle> ! a2x%rAttr(kpslv,n) = <copied from input streams bundle> a2x%rAttr(kpbot,n) = a2x%rAttr(kpslv,n) !--- correction to NCEP Arctic & Antarctic air T & potential T --- if ( yc(n) < -60.0_R8 ) then tMin = (avg_c0 + avg_c1*yc(n)) + (amp_c0 + amp_c1*yc(n))*cosFactor + tKFrz a2x%rAttr(ktbot,n) = max(a2x%rAttr(ktbot,n), tMin) else if ( yc(n) > 60.0_R8 ) then factor = MIN(1.0_R8, 0.1_R8*(yc(n)-60.0_R8) ) a2x%rAttr(ktbot,n) = a2x%rAttr(ktbot,n) + factor * dTarc(mm) endif a2x%rAttr(kptem,n) = a2x%rAttr(ktbot,n) !--- correction to NCEP relative humidity for heat budget balance --- a2x%rAttr(kshum,n) = a2x%rAttr(kshum,n) + qsatFactor(n) !------------------------------------------------------------------------- ! PRECIPITATION DATA !------------------------------------------------------------------------- avstrm%rAttr(sprec,n) = avstrm%rAttr(sprec,n)/86400.0_R8 ! convert mm/day to kg/m^2/s ! only correct satellite products, do not correct Serreze Arctic data if ( yc(n) < 58. ) then avstrm%rAttr(sprec,n) = avstrm%rAttr(sprec,n)*1.14168_R8 endif if ( yc(n) >= 58. .and. yc(n) < 68. ) then factor = MAX(0.0_R8, 1.0_R8 - 0.1_R8*(yc(n)-58.0_R8) ) avstrm%rAttr(sprec,n) = avstrm%rAttr(sprec,n)*(factor*(1.14168_R8 - 1.0_R8) + 1.0_R8) endif a2x%rAttr(krc,n) = 0.0_R8 ! default zero a2x%rAttr(ksc,n) = 0.0_R8 if (a2x%rAttr(ktbot,n) < tKFrz ) then ! assign precip to rain/snow components a2x%rAttr(krl,n) = 0.0_R8 a2x%rAttr(ksl,n) = avstrm%rAttr(sprec,n) else a2x%rAttr(krl,n) = avstrm%rAttr(sprec,n) a2x%rAttr(ksl,n) = 0.0_R8 endif !------------------------------------------------------------------------- ! RADIATION DATA !------------------------------------------------------------------------- !--- fabricate required swdn components from net swdn --- a2x%rAttr(kswvdr,n) = avstrm%rAttr(sswdn,n)*(0.28_R8) a2x%rAttr(kswndr,n) = avstrm%rAttr(sswdn,n)*(0.31_R8) a2x%rAttr(kswvdf,n) = avstrm%rAttr(sswdn,n)*(0.24_R8) a2x%rAttr(kswndf,n) = avstrm%rAttr(sswdn,n)*(0.17_R8) !--- compute net short-wave based on LY08 latitudinally-varying albedo --- avg_alb = ( 0.069 - 0.011*cos(2.0_R8*yc(n)*degtorad ) ) a2x%rAttr(kswnet,n) = avstrm%rAttr(sswdn,n)*(1.0_R8 - avg_alb) !--- corrections to GISS sswdn for heat budget balancing --- factor = 1.0_R8 if ( -60.0_R8 < yc(n) .and. yc(n) < -50.0_R8 ) then factor = 1.0_R8 - (yc(n) + 60.0_R8)*(0.05_R8/10.0_R8) else if ( -50.0_R8 < yc(n) .and. yc(n) < 30.0_R8 ) then factor = 0.95_R8 else if ( 30.0_R8 < yc(n) .and. yc(n) < 40._R8 ) then factor = 1.0_R8 - (40.0_R8 - yc(n))*(0.05_R8/10.0_R8) endif a2x%rAttr(kswnet,n) = a2x%rAttr(kswnet,n)*factor a2x%rAttr(kswvdr,n) = a2x%rAttr(kswvdr,n)*factor a2x%rAttr(kswndr,n) = a2x%rAttr(kswndr,n)*factor a2x%rAttr(kswvdf,n) = a2x%rAttr(kswvdf,n)*factor a2x%rAttr(kswndf,n) = a2x%rAttr(kswndf,n)*factor !--- correction to GISS lwdn in Arctic --- if ( yc(n) > 60._R8 ) then factor = MIN(1.0_R8, 0.1_R8*(yc(n)-60.0_R8) ) a2x%rAttr(klwdn,n) = a2x%rAttr(klwdn,n) + factor * dLWarc endif enddo ! lsize case('CLMNCEP') if (firstcall) then if (swind < 1 .or. stbot < 1) then write(logunit,F00) ' ERROR: wind and tbot must be in streams for CLMNCEP' call shr_sys_abort(trim(subname)//' ERROR: wind and tbot must be in streams for CLMNCEP') endif rtmp = maxval(a2x%rAttr(ktbot,:)) call shr_mpi_max(rtmp,tbotmax,mpicom,'datm_tbot',all=.true.) rtmp = maxval(x2a%rAttr(kanidr,:)) call shr_mpi_max(rtmp,anidrmax,mpicom,'datm_ani',all=.true.) if (stdew > 0) then rtmp = maxval(avstrm%rAttr(stdew,:)) call shr_mpi_max(rtmp,tdewmax,mpicom,'datm_tdew',all=.true.) endif if (my_task == master_task) & write(logunit,*) trim(subname),' max values = ',tbotmax,tdewmax,anidrmax endif lsize = mct_avect_lsize(a2x) do n = 1,SDATM%nstreams call shr_dmodel_translateAV(SDATM%avs(n),avstrm,stifld,stofld,rearr) enddo do n = 1,lsize !--- bottom layer height --- if (sz < 1) a2x%rAttr(kz,n) = 30.0_R8 !--- temperature --- if (tbotmax < 50.0_R8) a2x%rAttr(ktbot,n) = a2x%rAttr(ktbot,n) + tkFrz a2x%rAttr(kptem,n) = a2x%rAttr(ktbot,n) !--- pressure --- if (spbot < 1) a2x%rAttr(kpbot,n) = pstd a2x%rAttr(kpslv,n) = a2x%rAttr(kpbot,n) !--- u, v wind velocity --- a2x%rAttr(ku,n) = avstrm%rAttr(swind,n)/sqrt(2.0_R8) a2x%rAttr(kv,n) = a2x%rAttr(ku,n) !--- specific humidity --- tbot = a2x%rAttr(ktbot,n) pbot = a2x%rAttr(kpbot,n) if (sshum > 0) then e = datm_shr_esat(tbot,tbot) qsat = (0.622_R8 * e)/(pbot - 0.378_R8 * e) if (qsat < a2x%rAttr(kshum,n)) then a2x%rAttr(kshum,n) = qsat endif else if (srh > 0) then e = avstrm%rAttr(srh,n) * 0.01_R8 * datm_shr_esat(tbot,tbot) qsat = (0.622_R8 * e)/(pbot - 0.378_R8 * e) a2x%rAttr(kshum,n) = qsat else if (stdew > 0) then if (tdewmax < 50.0_R8) avstrm%rAttr(stdew,n) = avstrm%rAttr(stdew,n) + tkFrz e = datm_shr_esat(avstrm%rAttr(stdew,n),tbot) qsat = (0.622_R8 * e)/(pbot - 0.378_R8 * e) a2x%rAttr(kshum,n) = qsat else call shr_sys_abort(subname//'ERROR: cannot compute shum') endif !--- density --- vp = (a2x%rAttr(kshum,n)*pbot) / (0.622_R8 + 0.0378_R8 * a2x%rAttr(kshum,n)) a2x%rAttr(kdens,n) = (pbot - 0.0378_R8 * vp) / (tbot*rdair) !--- downward longwave --- if (slwdn < 1) then e = a2x%rAttr(kpslv,n) * a2x%rAttr(kshum,n) / (0.622_R8 + 0.378_R8 * a2x%rAttr(kshum,n)) ea = 0.70_R8 + 5.95e-05_R8 * 0.01_R8 * e * exp(1500.0_R8/tbot) a2x%rAttr(klwdn,n) = ea * stebol * tbot**4 endif !--- shortwave radiation --- if (sswdndf > 0 .and. sswdndr > 0) then a2x%rAttr(kswndr,n) = avstrm%rAttr(sswdndr,n) * 0.50_R8 a2x%rAttr(kswvdr,n) = avstrm%rAttr(sswdndr,n) * 0.50_R8 a2x%rAttr(kswndf,n) = avstrm%rAttr(sswdndf,n) * 0.50_R8 a2x%rAttr(kswvdf,n) = avstrm%rAttr(sswdndf,n) * 0.50_R8 elseif (sswdn > 0) then ! relationship between incoming NIR or VIS radiation and ratio of ! direct to diffuse radiation calculated based on one year's worth of ! hourly CAM output from CAM version cam3_5_55 swndr = avstrm%rAttr(sswdn,n) * 0.50_R8 ratio_rvrf = min(0.99_R8,max(0.29548_R8 + 0.00504_R8*swndr & -1.4957e-05_R8*swndr**2 + 1.4881e-08_R8*swndr**3,0.01_R8)) a2x%rAttr(kswndr,n) = ratio_rvrf*swndr swndf = avstrm%rAttr(sswdn,n) * 0.50_R8 a2x%rAttr(kswndf,n) = (1._R8 - ratio_rvrf)*swndf swvdr = avstrm%rAttr(sswdn,n) * 0.50_R8 ratio_rvrf = min(0.99_R8,max(0.17639_R8 + 0.00380_R8*swvdr & -9.0039e-06_R8*swvdr**2 + 8.1351e-09_R8*swvdr**3,0.01_R8)) a2x%rAttr(kswvdr,n) = ratio_rvrf*swvdr swvdf = avstrm%rAttr(sswdn,n) * 0.50_R8 a2x%rAttr(kswvdf,n) = (1._R8 - ratio_rvrf)*swvdf else call shr_sys_abort(subName//'ERROR: cannot compute short-wave down') endif !--- swnet: a diagnostic quantity --- if (anidrmax < 1.0e-8 .or. anidrmax > SHR_CONST_SPVAL * 0.9_R8) then a2x%rAttr(kswnet,n) = 0.0_R8 else a2x%rAttr(kswnet,n) = (1.0_R8-x2a%rAttr(kanidr,n))*a2x%rAttr(kswndr,n) + & (1.0_R8-x2a%rAttr(kavsdr,n))*a2x%rAttr(kswvdr,n) + & (1.0_R8-x2a%rAttr(kanidf,n))*a2x%rAttr(kswndf,n) + & (1.0_R8-x2a%rAttr(kavsdf,n))*a2x%rAttr(kswvdf,n) endif !--- rain and snow --- if (sprecc > 0 .and. sprecl > 0) then a2x%rAttr(krc,n) = avstrm%rAttr(sprecc,n) a2x%rAttr(krl,n) = avstrm%rAttr(sprecl,n) elseif (sprecn > 0) then a2x%rAttr(krc,n) = avstrm%rAttr(sprecn,n)*0.1_R8 a2x%rAttr(krl,n) = avstrm%rAttr(sprecn,n)*0.9_R8 else call shr_sys_abort(subName//'ERROR: cannot compute rain and snow') endif !--- split precip between rain & snow --- !--- note: aribitrarily small negative values cause CLM to crash --- frac = (tbot - tkFrz)*0.5_R8 ! ramp near freezing frac = min(1.0_R8,max(0.0_R8,frac)) ! bound in [0,1] a2x%rAttr(ksc,n) = max(0.0_R8, a2x%rAttr(krc,n)*(1.0_R8 - frac) ) a2x%rAttr(ksl,n) = max(0.0_R8, a2x%rAttr(krl,n)*(1.0_R8 - frac) ) a2x%rAttr(krc,n) = max(0.0_R8, a2x%rAttr(krc,n)*( frac) ) a2x%rAttr(krl,n) = max(0.0_R8, a2x%rAttr(krl,n)*( frac) ) enddo end select call t_stopf('datm_mode') if (write_restart) then call t_startf('datm_restart') call seq_infodata_GetData( infodata, case_name=case_name) write(rest_file,"(2a,i4.4,a,i2.2,a,i2.2,a,i5.5,a)") & trim(case_name), '.datm.r.', yy,'-',mm,'-',dd,'-',currentTOD,'.nc' write(rest_file_strm,"(2a,i4.4,a,i2.2,a,i2.2,a,i5.5,a)") & trim(case_name), '.datm.rs1.', yy,'-',mm,'-',dd,'-',currentTOD,'.bin' if (my_task == master_task) then nu = shr_file_getUnit() open(nu,file=trim(rpfile),form='formatted') write(nu,'(a)') rest_file write(nu,'(a)') rest_file_strm close(nu) call shr_file_freeUnit(nu) endif ! if (my_task == master_task) write(logunit,F04) ' writing ',trim(rest_file),currentYMD,currentTOD ! call shr_pcdf_readwrite('write',trim(rest_file),mpicom,gsmap,clobber=.true., & ! rf1=somtp,rf1n='somtp') if (my_task == master_task) write(logunit,F04) ' writing ',trim(rest_file_strm),currentYMD,currentTOD call shr_strdata_restWrite(trim(rest_file_strm),SDATM,mpicom,trim(case_name),'SDATM strdata') call shr_sys_flush(logunit) call t_stopf('datm_restart') endif call t_stopf('datm') !---------------------------------------------------------------------------- ! Log output for model date ! Reset shr logging to original values !---------------------------------------------------------------------------- call t_startf('datm_run2') if (my_task == master_task) then write(logunit,F04) trim(myModelName),': model date ', CurrentYMD,CurrentTOD call shr_sys_flush(logunit) end if firstcall = .false. call shr_file_setLogUnit (shrlogunit) call shr_file_setLogLevel(shrloglev) call shr_sys_flush(logunit) call t_stopf('datm_run2') call t_stopf('DATM_RUN') end subroutine datm_comp_run !=============================================================================== !BOP =========================================================================== ! ! !IROUTINE: datm_comp_final ! ! !DESCRIPTION: ! finalize method for dead atm model ! ! !REVISION HISTORY: ! ! !INTERFACE: ------------------------------------------------------------------ ! subroutine datm_comp_final() 1 implicit none !EOP !--- formats --- character(*), parameter :: F00 = "('(datm_comp_final) ',8a)" character(*), parameter :: F91 = "('(datm_comp_final) ',73('-'))" character(*), parameter :: subName = "(datm_comp_final) " !------------------------------------------------------------------------------- ! !------------------------------------------------------------------------------- call t_startf('DATM_FINAL') if (my_task == master_task) then write(logunit,F91) write(logunit,F00) trim(myModelName),': end of main integration loop' write(logunit,F91) end if call t_stopf('DATM_FINAL') end subroutine datm_comp_final !=============================================================================== !=============================================================================== end module datm_comp_mod