module lnd_comp_mct 2,2 !--------------------------------------------------------------------------- !BOP ! ! !MODULE: lnd_comp_mct ! ! Interface of the active land model component of CCSM the CLM (Community Land Model) ! with the main CCSM driver. This is a thin interface taking CCSM driver information ! in MCT (Model Coupling Toolkit) format and converting it to use by CLM. ! ! !DESCRIPTION: ! ! !USES: use shr_kind_mod , only : r8 => shr_kind_r8 use mct_mod , only : mct_aVect ! ! !PUBLIC MEMBER FUNCTIONS: implicit none SAVE private ! By default make data private ! ! !PUBLIC MEMBER FUNCTIONS: ! public :: lnd_init_mct ! clm initialization public :: lnd_run_mct ! clm run phase public :: lnd_final_mct ! clm finalization/cleanup ! ! !PUBLIC DATA MEMBERS: None ! ! !REVISION HISTORY: ! Author: Mariana Vertenstein ! Dec/18/2009 Make sure subroutines have documentation. Erik Kluzek ! ! !PRIVATE MEMBER FUNCTIONS: private :: lnd_SetgsMap_mct ! Set the land model MCT GS map private :: lnd_chkAerDep_mct ! Check if aerosol deposition data is input or not private :: lnd_domain_mct ! Set the land model domain information private :: lnd_export_mct ! export land data to CCSM coupler private :: lnd_import_mct ! import data from the CCSM coupler to the land model #ifdef RTM private :: rof_SetgsMap_mct ! Set the river runoff model MCT GS map private :: rof_domain_mct ! Set the river runoff model domain information private :: rof_export_mct ! Export the river runoff model data to the CCSM coupler #endif private :: sno_export_mct private :: sno_import_mct ! ! !PRIVATE DATA MEMBERS: ! ! Time averaged flux fields ! type(mct_aVect) :: l2x_l_SNAP ! Snapshot of land to coupler data on the land grid type(mct_aVect) :: l2x_l_SUM ! Summation of land to coupler data on the land grid type(mct_aVect) :: l2x_l_clm ! Internal clm grid type(mct_aVect) :: x2l_l_clm ! Internal clm grid type(mct_aVect) :: s2x_s_SNAP ! Snapshot of sno to coupler data on the land grid type(mct_aVect) :: s2x_s_SUM ! Summation of sno to coupler data on the land grid ! ! Time averaged counter for flux fields ! integer :: avg_count ! Number of times snapshots of above flux data summed together integer :: avg_count_sno ! ! Atmospheric mode ! logical :: atm_prognostic ! Flag if active atmosphere component or not !EOP !=============================================================== contains !=============================================================== !--------------------------------------------------------------------------- !BOP ! ! !IROUTINE: lnd_init_mct ! ! !INTERFACE: subroutine lnd_init_mct( EClock, cdata_l, x2l_l, l2x_l, & 1,76 cdata_r, r2x_r, & cdata_s, x2s_s, s2x_s, & NLFilename ) ! ! !DESCRIPTION: ! Initialize land surface model and obtain relevant atmospheric model arrays ! back from (i.e. albedos, surface temperature and snow cover over land). ! ! !USES: use abortutils , only : endrun use areaMod , only : map1dl_a2l, map1dl_l2a, map_maparrayl use clm_time_manager , only : get_nstep, get_step_size, set_timemgr_init, & set_nextsw_cday use clm_atmlnd , only : clm_l2a, clm_mapa2l use clm_comp , only : clm_init1, clm_init2, clm_init3 use clm_varctl , only : finidat,single_column, set_clmvarctl, iulog, noland use clm_varpar , only : rtmlon, rtmlat use clm_varorb , only : eccen, obliqr, lambm0, mvelpp use controlMod , only : control_setNL use decompMod , only : get_proc_bounds, get_proc_bounds_atm use domainMod , only : adomain use shr_kind_mod , only : r8 => shr_kind_r8 use shr_file_mod , only : shr_file_setLogUnit, shr_file_setLogLevel, & shr_file_getLogUnit, shr_file_getLogLevel, & shr_file_getUnit, shr_file_setIO use seq_cdata_mod , only : seq_cdata, seq_cdata_setptrs use seq_timemgr_mod , only : seq_timemgr_EClockGetData use seq_infodata_mod , only : seq_infodata_type, seq_infodata_GetData, seq_infodata_PutData, & seq_infodata_start_type_start, seq_infodata_start_type_cont, & seq_infodata_start_type_brnch use mct_mod , only : mct_aVect, mct_gsMap, mct_gGrid, mct_aVect_init, mct_aVect_zero use spmdMod , only : masterproc, spmd_init use seq_flds_mod use seq_flds_indices use clm_glclnd , only : clm_maps2x, clm_s2x, atm_s2x, create_clm_s2x use clm_varctl , only : create_glacier_mec_landunit use ESMF_mod implicit none ! ! !ARGUMENTS: type(ESMF_Clock), intent(in) :: EClock ! Input synchronization clock type(seq_cdata), intent(inout) :: cdata_l ! Input land-model driver data type(mct_aVect), intent(inout) :: x2l_l, l2x_l ! land model import and export states type(seq_cdata), intent(inout) :: cdata_r ! Input runoff-model driver data type(mct_aVect), intent(inout) :: r2x_r ! River export state type(seq_cdata), intent(inout) :: cdata_s ! Input snow-model (land-ice) driver data type(mct_aVect), intent(inout) :: x2s_s, s2x_s ! Snow-model import and export states character(len=*), optional, intent(in) :: NLFilename ! Namelist filename to read ! ! !LOCAL VARIABLES: integer :: LNDID ! Land identifyer integer :: mpicom_lnd ! MPI communicator type(mct_gsMap), pointer :: GSMap_lnd ! Land model MCT GS map type(mct_gGrid), pointer :: dom_l ! Land model domain type(mct_gsMap), pointer :: GSMap_rof ! Runoff model MCT GS map type(mct_gGrid), pointer :: dom_r ! Runoff model domain type(mct_gsMap), pointer :: GSMap_sno type(mct_gGrid), pointer :: dom_s type(seq_infodata_type), pointer :: infodata ! CCSM driver level info data integer :: lsize ! size of attribute vector integer :: g,i,j ! indices integer :: dtime_sync ! coupling time-step from the input synchronization clock integer :: dtime_clm ! clm time-step logical :: exists ! true if file exists real(r8) :: scmlat ! single-column latitude real(r8) :: scmlon ! single-column longitude real(r8) :: nextsw_cday ! calday from clock of next radiation computation character(len=SHR_KIND_CL) :: caseid ! case identifier name character(len=SHR_KIND_CL) :: ctitle ! case description title character(len=SHR_KIND_CL) :: starttype ! start-type (startup, continue, branch, hybrid) character(len=SHR_KIND_CL) :: calendar ! calendar type name character(len=SHR_KIND_CL) :: hostname ! hostname of machine running on character(len=SHR_KIND_CL) :: version ! Model version character(len=SHR_KIND_CL) :: username ! user running the model integer :: nsrest ! clm restart type integer :: perpetual_ymd ! perpetual date integer :: ref_ymd ! reference date (YYYYMMDD) integer :: ref_tod ! reference time of day (sec) integer :: start_ymd ! start date (YYYYMMDD) integer :: start_tod ! start time of day (sec) integer :: stop_ymd ! stop date (YYYYMMDD) integer :: stop_tod ! stop time of day (sec) logical :: brnch_retain_casename ! flag if should retain the case name on a branch start type logical :: perpetual_run ! flag if should cycle over a perpetual date or not integer :: lbnum ! input to memory diagnostic integer :: shrlogunit,shrloglev ! old values for log unit and log level integer :: begg_l, endg_l, begg_a, endg_a character(len=32), parameter :: sub = 'lnd_init_mct' character(len=*), parameter :: format = "('("//trim(sub)//") :',A)" ! ! !REVISION HISTORY: ! Author: Mariana Vertenstein ! !EOP !----------------------------------------------------------------------- ! Set cdata data call seq_cdata_setptrs(cdata_l, ID=LNDID, mpicom=mpicom_lnd, & gsMap=GSMap_lnd, dom=dom_l, infodata=infodata) call seq_cdata_setptrs(cdata_r, & gsMap=gsMap_rof, dom=dom_r) ! Initialize clm MPI communicator call spmd_init( mpicom_lnd ) #if (defined _MEMTRACE) if(masterproc) then lbnum=1 call memmon_dump_fort('memmon.out','lnd_init_mct:start::',lbnum) endif #endif ! Initialize io log unit call shr_file_getLogUnit (shrlogunit) if (masterproc) then inquire(file='lnd_modelio.nml',exist=exists) if (exists) then iulog = shr_file_getUnit() call shr_file_setIO('lnd_modelio.nml',iulog) end if write(iulog,format) "CLM land model initialization" else iulog = shrlogunit end if call shr_file_getLogLevel(shrloglev) call shr_file_setLogUnit (iulog) ! Use infodata to set orbital values call seq_infodata_GetData( infodata, orb_eccen=eccen, orb_mvelpp=mvelpp, & orb_lambm0=lambm0, orb_obliqr=obliqr ) ! Consistency check on namelist filename call control_setNL( 'lnd_in' ) ! Initialize clm ! clm_init1 reads namelist, grid and surface data ! clm_init2 and clm_init3 performs rest of initialization call seq_timemgr_EClockGetData(EClock, & start_ymd=start_ymd, & start_tod=start_tod, ref_ymd=ref_ymd, & ref_tod=ref_tod, stop_ymd=stop_ymd, & stop_tod=stop_tod, & calendar=calendar ) call seq_infodata_GetData(infodata, perpetual=perpetual_run, & perpetual_ymd=perpetual_ymd, case_name=caseid, & case_desc=ctitle, single_column=single_column, & scmlat=scmlat, scmlon=scmlon, & brnch_retain_casename=brnch_retain_casename, & start_type=starttype, model_version=version, & hostname=hostname, username=username & ) call set_timemgr_init( calendar_in=calendar, start_ymd_in=start_ymd, start_tod_in=start_tod, & ref_ymd_in=ref_ymd, ref_tod_in=ref_tod, stop_ymd_in=stop_ymd, & stop_tod_in=stop_tod, perpetual_run_in=perpetual_run, & perpetual_ymd_in=perpetual_ymd ) if ( trim(starttype) == trim(seq_infodata_start_type_start)) then nsrest = 0 else if (trim(starttype) == trim(seq_infodata_start_type_cont) ) then nsrest = 1 else if (trim(starttype) == trim(seq_infodata_start_type_brnch)) then nsrest = 3 else call endrun( sub//' ERROR: unknown starttype' ) end if call set_clmvarctl( caseid_in=caseid, ctitle_in=ctitle, & brnch_retain_casename_in=brnch_retain_casename, & single_column_in=single_column, scmlat_in=scmlat, & scmlon_in=scmlon, nsrest_in=nsrest, version_in=version, & hostname_in=hostname, username_in=username ) ! Read namelist, grid and surface data call clm_init1( ) ! If no land then exit out of initialization if ( noland) then call seq_infodata_PutData( infodata, lnd_present =.false.) call seq_infodata_PutData( infodata, lnd_prognostic=.false.) call seq_infodata_PutData( infodata, rof_present =.false.) return end if ! Determine if aerosol and dust deposition come from atmosphere component call lnd_chkAerDep_mct( infodata ) ! Initialize lnd gsMap and domain call lnd_SetgsMap_mct( mpicom_lnd, LNDID, gsMap_lnd ) lsize = mct_gsMap_lsize(gsMap_lnd, mpicom_lnd) call lnd_domain_mct( lsize, gsMap_lnd, dom_l ) ! Initialize lnd attribute vectors coming from driver call mct_aVect_init(x2l_l, rList=seq_flds_x2l_fields, lsize=lsize) call mct_aVect_zero(x2l_l) call mct_aVect_init(l2x_l, rList=seq_flds_l2x_fields, lsize=lsize) call mct_aVect_zero(l2x_l) call mct_aVect_init(l2x_l_SNAP, rList=seq_flds_l2x_fluxes, lsize=lsize) call mct_aVect_zero(l2x_l_SNAP) call mct_aVect_init(l2x_l_SUM , rList=seq_flds_l2x_fluxes, lsize=lsize) call mct_aVect_zero(l2x_l_SUM ) if (masterproc) then write(iulog,format)'time averaging the following flux fields over the coupling interval' write(iulog,format) trim(seq_flds_l2x_fluxes) end if ! Finish initializing clm call clm_init2() call clm_init3() ! Check that clm internal dtime aligns with clm coupling interval call seq_timemgr_EClockGetData(EClock, dtime=dtime_sync ) dtime_clm = get_step_size() if (masterproc) write(iulog,*)'dtime_sync= ',dtime_sync,& ' dtime_clm= ',dtime_clm,' mod = ',mod(dtime_sync,dtime_clm) if (mod(dtime_sync,dtime_clm) /= 0) then write(iulog,*)'clm dtime ',dtime_clm,' and Eclock dtime ',& dtime_sync,' never align' call endrun( sub//' ERROR: time out of sync' ) end if ! Create new attribute vectors for the clm internal grid (dst) call get_proc_bounds_atm(begg_a, endg_a) ! clm grid - driver (src) call get_proc_bounds (begg_l, endg_l) ! clm grid - internal (dst) call mct_aVect_init(x2l_l_clm, rList=seq_flds_x2l_fields, lsize=endg_l-begg_l+1) call mct_aVect_zero(x2l_l_clm) call mct_aVect_init(l2x_l_clm, rList=seq_flds_l2x_fields, lsize=endg_l-begg_l+1) call mct_aVect_zero(l2x_l_clm) ! Create land export state then map this from the ! clm internal grid (dst) to the clm driver grid (src) call lnd_export_mct( clm_l2a, l2x_l_clm, begg_l, endg_l ) call map_maparrayl(begg_l, endg_l, begg_a, endg_a, nflds_l2x, & l2x_l_clm, l2x_l, map1dl_l2a) ! Reset landfrac on atmosphere grid to have the right domain do g = begg_a,endg_a l2x_l%rAttr(index_l2x_Sl_landfrac,g-begg_a+1) = adomain%frac(g) end do #ifdef RTM ! Initialize rof gsMap call rof_SetgsMap_mct( mpicom_lnd, LNDID, gsMap_rof ) lsize = mct_gsMap_lsize(gsMap_rof, mpicom_lnd) ! Initialize rof domain call rof_domain_mct( lsize, gsMap_rof, dom_r ) ! Initialize rtm attribute vectors call mct_aVect_init(r2x_r, rList=seq_flds_r2x_fields, lsize=lsize) call mct_aVect_zero(r2x_r) ! Create mct river runoff export state call rof_export_mct( r2x_r ) #endif if (create_glacier_mec_landunit) then call seq_cdata_setptrs(cdata_s, gsMap=gsMap_sno, dom=dom_s) ! Initialize sno gsMap (same as gsMap_lnd) call lnd_SetgsMap_mct( mpicom_lnd, LNDID, gsMap_sno ) lsize = mct_gsMap_lsize(gsMap_sno, mpicom_lnd) ! Initialize sno domain (same as lnd domain) call lnd_domain_mct( lsize, gsMap_sno, dom_s ) ! Initialize sno attribute vectors call mct_aVect_init(x2s_s, rList=seq_flds_x2s_fields, lsize=lsize) call mct_aVect_zero(x2s_s) call mct_aVect_init(s2x_s, rList=seq_flds_s2x_fields, lsize=lsize) call mct_aVect_zero(s2x_s) call mct_aVect_init(s2x_s_SUM , rList=seq_flds_s2x_fluxes, lsize=lsize) call mct_aVect_zero(s2x_s_SUM ) call mct_aVect_init(s2x_s_SNAP , rList=seq_flds_s2x_fluxes, lsize=lsize) call mct_aVect_zero(s2x_s_SNAP ) ! Create mct sno export state call create_clm_s2x(clm_s2x) call clm_maps2x(clm_s2x, atm_s2x) call sno_export_mct( atm_s2x, s2x_s ) endif ! create_glacier_mec_landunit ! Initialize averaging counter avg_count = 0 ! Set land modes call seq_infodata_PutData( infodata, lnd_prognostic=.true.) call seq_infodata_PutData( infodata, lnd_nx = adomain%ni, lnd_ny = adomain%nj) #ifdef RTM call seq_infodata_PutData( infodata, rof_present=.true.) call seq_infodata_PutData( infodata, rof_nx = rtmlon, rof_ny = rtmlat) #else call seq_infodata_PutData( infodata, rof_present=.false.) #endif if (create_glacier_mec_landunit) then call seq_infodata_PutData( infodata, sno_present=.true.) call seq_infodata_PutData( infodata, sno_nx = adomain%ni, sno_ny = adomain%nj) else call seq_infodata_PutData( infodata, sno_present=.false.) endif call seq_infodata_GetData(infodata, nextsw_cday=nextsw_cday ) call set_nextsw_cday( nextsw_cday ) ! Determine atmosphere modes call seq_infodata_GetData(infodata, atm_prognostic=atm_prognostic) if (masterproc) then if ( atm_prognostic )then write(iulog,format) 'Atmospheric input is from a prognostic model' else write(iulog,format) 'Atmospheric input is from a data model' end if end if ! Reset shr logging to original values call shr_file_setLogUnit (shrlogunit) call shr_file_setLogLevel(shrloglev) #if (defined _MEMTRACE) if(masterproc) then write(iulog,*) TRIM(Sub) // ':end::' lbnum=1 call memmon_dump_fort('memmon.out','lnd_int_mct:end::',lbnum) call memmon_reset_addr() endif #endif end subroutine lnd_init_mct !--------------------------------------------------------------------------- !BOP ! ! !IROUTINE: lnd_run_mct ! ! !INTERFACE: subroutine lnd_run_mct( EClock, cdata_l, x2l_l, l2x_l, & 1,66 cdata_r, r2x_r, & cdata_s, x2s_s, s2x_s ) ! ! !DESCRIPTION: ! Run clm model ! ! !USES: use shr_kind_mod ,only : r8 => shr_kind_r8 use areaMod ,only : map1dl_a2l, map1dl_l2a, map_maparrayl use clm_atmlnd ,only : clm_l2a, atm_a2l, clm_a2l, clm_mapa2l use clm_comp ,only : clm_run1, clm_run2 use clm_time_manager,only : get_curr_date, get_nstep, get_curr_calday, get_step_size, & advance_timestep, set_nextsw_cday,update_rad_dtime use domainMod ,only : adomain use decompMod ,only : get_proc_bounds_atm, get_proc_bounds use abortutils ,only : endrun use clm_varctl ,only : iulog use shr_file_mod ,only : shr_file_setLogUnit, shr_file_setLogLevel, & shr_file_getLogUnit, shr_file_getLogLevel use seq_cdata_mod ,only : seq_cdata, seq_cdata_setptrs use seq_timemgr_mod ,only : seq_timemgr_EClockGetData, seq_timemgr_StopAlarmIsOn, & seq_timemgr_RestartAlarmIsOn, seq_timemgr_EClockDateInSync use seq_infodata_mod,only : seq_infodata_type, seq_infodata_GetData use spmdMod ,only : masterproc, mpicom use perf_mod ,only : t_startf, t_stopf, t_barrierf use mct_mod ,only : mct_aVect, mct_aVect_accum, mct_aVect_copy, mct_aVect_avg, & mct_aVect_zero use mct_mod , only : mct_gGrid, mct_gGrid_exportRAttr, mct_gGrid_lsize use clm_varctl ,only : create_glacier_mec_landunit use clm_glclnd ,only : clm_maps2x, clm_mapx2s, clm_s2x, atm_s2x, atm_x2s, clm_x2s use clm_glclnd ,only : create_clm_s2x, unpack_clm_x2s use seq_flds_indices use ESMF_mod implicit none ! ! !ARGUMENTS: type(ESMF_Clock) , intent(in) :: EClock ! Input synchronization clock from driver type(seq_cdata) , intent(in) :: cdata_l ! Input driver data for land model type(mct_aVect) , intent(inout) :: x2l_l ! Import state to land model type(mct_aVect) , intent(inout) :: l2x_l ! Export state from land model type(seq_cdata) , intent(in) :: cdata_r ! Input driver data for runoff model type(mct_aVect) , intent(inout) :: r2x_r ! Export state from runoff model type(seq_cdata) , intent(in) :: cdata_s ! Input driver data for snow model (land-ice) type(mct_aVect) , intent(inout) :: x2s_s ! Import state for snow model type(mct_aVect) , intent(inout) :: s2x_s ! Export state for snow model ! !LOCAL VARIABLES: integer :: ymd_sync ! Sync date (YYYYMMDD) integer :: yr_sync ! Sync current year integer :: mon_sync ! Sync current month integer :: day_sync ! Sync current day integer :: tod_sync ! Sync current time of day (sec) integer :: ymd ! CLM current date (YYYYMMDD) integer :: yr ! CLM current year integer :: mon ! CLM current month integer :: day ! CLM current day integer :: tod ! CLM current time of day (sec) integer :: dtime ! time step increment (sec) integer :: nstep ! time step index logical :: rstwr_sync ! .true. ==> write restart file before returning logical :: rstwr ! .true. ==> write restart file before returning logical :: nlend_sync ! Flag signaling last time-step logical :: nlend ! .true. ==> last time-step logical :: dosend ! true => send data back to driver logical :: doalb ! .true. ==> do albedo calculation on this time step real(r8):: nextsw_cday ! calday from clock of next radiation computation real(r8):: caldayp1 ! clm calday plus dtime offset integer :: shrlogunit,shrloglev ! old values for share log unit and log level integer :: begg, endg ! Beginning and ending gridcell index numbers integer :: lbnum ! input to memory diagnostic type(seq_infodata_type),pointer :: infodata ! CCSM information from the driver type(mct_gGrid), pointer :: dom_l ! Land model domain data real(r8), pointer :: data(:) ! temporary integer :: g,i,lsize ! counters integer :: begg_l, endg_l, begg_a, endg_a ! bounds logical,save :: first_call = .true. ! first call work character(len=32) :: rdate ! date char string for restart file names character(len=32), parameter :: sub = "lnd_run_mct" logical :: glcrun_alarm ! if true, sno data is averaged and sent to glc this step logical :: update_glc2sno_fields ! if true, update glacier_mec fields ! ! !REVISION HISTORY: ! Author: Mariana Vertenstein ! !EOP !--------------------------------------------------------------------------- #if (defined _MEMTRACE) if(masterproc) then lbnum=1 call memmon_dump_fort('memmon.out','lnd_run_mct:start::',lbnum) endif #endif ! Reset shr logging to my log file call shr_file_getLogUnit (shrlogunit) call shr_file_getLogLevel(shrloglev) call shr_file_setLogUnit (iulog) ! Determine time of next atmospheric shortwave calculation call seq_cdata_setptrs(cdata_l, infodata=infodata, dom=dom_l) call seq_timemgr_EClockGetData(EClock, & curr_ymd=ymd, curr_tod=tod_sync, & curr_yr=yr_sync, curr_mon=mon_sync, curr_day=day_sync) call seq_infodata_GetData(infodata, nextsw_cday=nextsw_cday ) call set_nextsw_cday( nextsw_cday ) dtime = get_step_size() write(rdate,'(i4.4,"-",i2.2,"-",i2.2,"-",i5.5)') yr_sync,mon_sync,day_sync,tod_sync nlend_sync = seq_timemgr_StopAlarmIsOn( EClock ) rstwr_sync = seq_timemgr_RestartAlarmIsOn( EClock ) call get_proc_bounds_atm(begg_a, endg_a) call get_proc_bounds (begg_l, endg_l) if (first_call) then lsize = mct_gGrid_lsize(dom_l) allocate(data(lsize)) call mct_gGrid_exportRattr(dom_l,"ascale",data,lsize) do g = begg_a,endg_a i = 1 + (g - begg_a) adomain%asca(g) = data(i) end do deallocate(data) endif ! Map MCT to land data type call t_startf ('lc_lnd_import') call lnd_import_mct( x2l_l, atm_a2l, begg_a, endg_a ) call t_stopf ('lc_lnd_import') call map_maparrayl(begg_a, endg_a, begg_l, endg_l, nflds_x2l, & x2l_l, x2l_l_clm, map1dl_a2l) call t_startf ('lc_lnd_import') call lnd_import_mct( x2l_l_clm, clm_a2l, begg_l, endg_l ) call t_stopf ('lc_lnd_import') ! Perform downscaling if appropriate call t_startf ('lc_clm_mapa2l') call clm_mapa2l(atm_a2l, clm_a2l) call t_stopf ('lc_clm_mapa2l') if (create_glacier_mec_landunit) then ! Receive sno data call t_startf ('lc_sno_import') call sno_import_mct( x2s_s, atm_x2s ) call t_stopf ('lc_sno_import') ! Map to clm (only when state and/or fluxes need to be updated) update_glc2sno_fields = .false. call seq_infodata_GetData(infodata, glc_g2supdate = update_glc2sno_fields) if (update_glc2sno_fields) then call t_startf ('lc_clm_mapa2s') call clm_mapx2s(atm_x2s, clm_x2s) call t_stopf ('lc_clm_mapa2s') call unpack_clm_x2s(clm_x2s) endif ! update_glc2sno endif ! create_glacier_mec_landunit ! Loop over time steps in coupling interval dosend = .false. do while(.not. dosend) ! Determine if dosend ! When time is not updated at the beginning of the loop - then return only if ! are in sync with clock before time is updated call get_curr_date( yr, mon, day, tod ) ymd = yr*10000 + mon*100 + day tod = tod dosend = (seq_timemgr_EClockDateInSync( EClock, ymd, tod)) ! Determine doalb based on nextsw_cday sent from atm model nstep = get_nstep() caldayp1 = get_curr_calday(offset=dtime) if (nstep == 0) then doalb = .false. else if (nstep == 1) then doalb = (abs(nextsw_cday- caldayp1) < 1.e-10_r8) else doalb = (nextsw_cday >= -0.5_r8) end if call update_rad_dtime(doalb) ! Determine if time to write cam restart and stop rstwr = .false. if (rstwr_sync .and. dosend) rstwr = .true. nlend = .false. if (nlend_sync .and. dosend) nlend = .true. ! Run clm call t_barrierf('sync_clm_run1', mpicom) call t_startf ('clm_run1') call clm_run1( doalb, nextsw_cday ) call t_stopf ('clm_run1') call t_barrierf('sync_clm_run2', mpicom) call t_startf ('clm_run2') call clm_run2( nextsw_cday, rstwr, nlend, rdate ) call t_stopf ('clm_run2') ! Map land data type to MCT call t_startf ('lc_lnd_export') call lnd_export_mct( clm_l2a, l2x_l_clm, begg_l, endg_l ) call map_maparrayl(begg_l, endg_l, begg_a, endg_a, nflds_l2x, & l2x_l_clm, l2x_l, map1dl_l2a) ! Reset landfrac on atmosphere grid to have the right domain do g = begg_a,endg_a l2x_l%rAttr(index_l2x_Sl_landfrac,g-begg_a+1) = adomain%frac(g) end do call t_stopf ('lc_lnd_export') ! Compute snapshot attribute vector for accumulation ! don't accumulate on first coupling freq ts0 and ts1 ! for consistency with ccsm3 when flxave is off nstep = get_nstep() if (nstep <= 1) then call mct_aVect_copy( l2x_l, l2x_l_SUM ) avg_count = 1 else call mct_aVect_copy( l2x_l, l2x_l_SNAP ) call mct_aVect_accum( aVin=l2x_l_SNAP, aVout=l2x_l_SUM ) avg_count = avg_count + 1 endif if (create_glacier_mec_landunit) then ! Map sno data type to MCT call create_clm_s2x(clm_s2x) call t_startf ('lc_clm_maps2a') call clm_maps2x(clm_s2x, atm_s2x) call t_stopf ('lc_clm_maps2a') call t_startf ('lc_sno_export') call sno_export_mct( atm_s2x, s2x_s ) call t_stopf ('lc_sno_export') if (nstep <= 1) then call mct_aVect_copy( s2x_s, s2x_s_SUM ) avg_count_sno = 1 else call mct_aVect_copy( s2x_s, s2x_s_SNAP ) call mct_aVect_accum( aVin=s2x_s_SNAP, aVout=s2x_s_SUM ) avg_count_sno = avg_count_sno + 1 endif endif ! create_glacier_mec_landunit ! Advance clm time step call t_startf ('lc_clm2_adv_timestep') call advance_timestep() call t_stopf ('lc_clm2_adv_timestep') end do ! Finish accumulation of attribute vector and average and zero out partial sum and counter call mct_aVect_avg ( l2x_l_SUM, avg_count) call mct_aVect_copy( l2x_l_SUM, l2x_l ) call mct_aVect_zero( l2x_l_SUM) avg_count = 0 if (create_glacier_mec_landunit) then call seq_infodata_GetData(infodata, glcrun_alarm = glcrun_alarm ) if (glcrun_alarm) then call mct_aVect_avg ( s2x_s_SUM, avg_count_sno) call mct_aVect_copy( s2x_s_SUM, s2x_s ) call mct_aVect_zero( s2x_s_SUM) avg_count_sno = 0 endif endif #ifdef RTM ! Create river runoff output state call t_startf ('lc_rof_export') call rof_export_mct( r2x_r ) call t_stopf ('lc_rof_export') #endif ! Check that internal clock is in sync with master clock call get_curr_date( yr, mon, day, tod, offset=-dtime ) ymd = yr*10000 + mon*100 + day tod = tod if ( .not. seq_timemgr_EClockDateInSync( EClock, ymd, tod ) )then call seq_timemgr_EclockGetData( EClock, curr_ymd=ymd_sync, curr_tod=tod_sync ) write(iulog,*)' clm ymd=',ymd ,' clm tod= ',tod write(iulog,*)'sync ymd=',ymd_sync,' sync tod= ',tod_sync call endrun( sub//":: CLM clock not in sync with Master Sync clock" ) end if ! Reset shr logging to my original values call shr_file_setLogUnit (shrlogunit) call shr_file_setLogLevel(shrloglev) #if (defined _MEMTRACE) if(masterproc) then lbnum=1 call memmon_dump_fort('memmon.out','lnd_run_mct:end::',lbnum) call memmon_reset_addr() endif #endif first_call = .false. end subroutine lnd_run_mct !--------------------------------------------------------------------------- !BOP ! ! !IROUTINE: lnd_final_mct ! ! !INTERFACE: subroutine lnd_final_mct( ) 1 ! ! !DESCRIPTION: ! Finalize land surface model ! !------------------------------------------------------------------------------ ! implicit none ! !ARGUMENTS: ! ! !REVISION HISTORY: ! Author: Mariana Vertenstein ! !EOP !--------------------------------------------------------------------------- ! fill this in end subroutine lnd_final_mct !================================================================================= !--------------------------------------------------------------------------- !BOP ! ! !IROUTINE: lnd_SetgsMap_mct ! ! !INTERFACE: subroutine lnd_SetgsMap_mct( mpicom_lnd, LNDID, gsMap_lnd ) 2,5 !------------------------------------------------------------------- ! ! !DESCRIPTION: ! ! Set the MCT GS map for the land model ! !------------------------------------------------------------------- ! !USES: use shr_kind_mod , only : r8 => shr_kind_r8 use decompMod , only : get_proc_bounds_atm, adecomp use domainMod , only : adomain use mct_mod , only : mct_gsMap, mct_gsMap_init implicit none ! !ARGUMENTS: integer , intent(in) :: mpicom_lnd ! MPI communicator for the clm land model integer , intent(in) :: LNDID ! Land model identifyer number type(mct_gsMap), intent(out) :: gsMap_lnd ! Resulting MCT GS map for the land model ! ! !LOCAL VARIABLES: integer,allocatable :: gindex(:) ! Number the local grid points integer :: i, j, n, gi ! Indices integer :: lsize,gsize ! GS Map size integer :: ier ! Error code integer :: begg, endg ! Beginning/Ending grid cell index ! ! !REVISION HISTORY: ! Author: Mariana Vertenstein ! !EOP !--------------------------------------------------------------------------- ! Build the land grid numbering for MCT ! NOTE: Numbering scheme is: West to East and South to North ! starting at south pole. Should be the same as what's used in SCRIP call get_proc_bounds_atm(begg, endg) allocate(gindex(begg:endg),stat=ier) ! number the local grid do n = begg, endg gindex(n) = adecomp%gdc2glo(n) end do lsize = endg-begg+1 gsize = adomain%ni*adomain%nj call mct_gsMap_init( gsMap_lnd, gindex, mpicom_lnd, LNDID, lsize, gsize ) deallocate(gindex) end subroutine lnd_SetgsMap_mct !================================================================================= !--------------------------------------------------------------------------- !BOP ! ! !IROUTINE: lnd_chkAerDep_mct ! ! !INTERFACE: subroutine lnd_chkAerDep_mct( infodata ) 1,12 ! ! !DESCRIPTION: ! Check infodata to see if aerosol deposition data is sent to the land model. ! If data is NOT sent, read in CLM version of datasets that have this information. ! !------------------------------------------------------------------------------ ! !USES: use shr_const_mod , only : spval => SHR_CONST_SPVAL use shr_sys_mod , only : shr_sys_flush use clm_varctl , only : iulog use clm_varctl , only : set_caerdep_from_file, set_dustdep_from_file use abortutils , only : endrun use seq_flds_indices , only : index_x2l_Faxa_bcphidry, index_x2l_Faxa_bcphodry, & index_x2l_Faxa_bcphiwet, & index_x2l_Faxa_ocphidry, index_x2l_Faxa_ocphodry, & index_x2l_Faxa_ocphiwet, & index_x2l_Faxa_dstdry1, index_x2l_Faxa_dstdry2, & index_x2l_Faxa_dstdry3, index_x2l_Faxa_dstdry4, & index_x2l_Faxa_dstwet1, index_x2l_Faxa_dstwet2, & index_x2l_Faxa_dstwet3, index_x2l_Faxa_dstwet4 use seq_infodata_mod , only : seq_infodata_type, seq_infodata_GetData use spmdMod , only : masterproc use aerdepMod , only : aerdepini implicit none ! ! !ARGUMENTS: type(seq_infodata_type),pointer :: infodata ! CCSM information from the driver ! ! !LOCAL VARIABLES: logical :: caerdep_filled = .true. ! Flag if carbon aerosol deposition is filled logical :: dustdep_filled = .true. ! Flag if dust deposition is filled logical :: atm_aero ! Flag if aerosol data sent from atm model ! ! !REVISION HISTORY: ! Author: Erik Kluzek ! !EOP !--------------------------------------------------------------------------- call seq_infodata_GetData(infodata, atm_aero=atm_aero ) if ( .not. atm_aero )then caerdep_filled = .false. dustdep_filled = .false. end if if ( caerdep_filled )then if ( masterproc ) & write(iulog,*) "Using aerosol deposition sent from atmosphere model" else if ( masterproc ) then write(iulog,*) "WARNING: carbon aerosol deposition data NOT sent in from atmosphere model" write(iulog,*) "WARNING: Reading carbon aerosol deposition from CLM input file" end if end if if ( dustdep_filled )then if ( masterproc ) & write(iulog,*) "Using dust deposition sent from atmosphere model" else if ( masterproc ) then write(iulog,*) "WARNING: dust deposition data NOT sent in from atmosphere model" write(iulog,*) "WARNING: Reading dust deposition from CLM input file" end if end if call shr_sys_flush( iulog ) set_caerdep_from_file = .not. caerdep_filled set_dustdep_from_file = .not. dustdep_filled if ( .not. atm_aero )then call aerdepini( ) end if end subroutine lnd_chkAerDep_mct !================================================================================= !--------------------------------------------------------------------------- !BOP ! ! !IROUTINE: lnd_export_mct ! ! !INTERFACE: subroutine lnd_export_mct( l2a, l2x_l, begg, endg ) 2,6 ! ! !DESCRIPTION: ! ! Convert the data to be sent from the clm model to the coupler from clm data types ! to MCT data types. ! !--------------------------------------------------------------------------- ! !USES: use shr_kind_mod , only : r8 => shr_kind_r8 use clm_time_manager , only : get_nstep use clm_atmlnd , only : lnd2atm_type use domainMod , only : adomain use seq_drydep_mod , only : n_drydep use seq_flds_indices implicit none ! !ARGUMENTS: type(lnd2atm_type), intent(inout) :: l2a ! clm land to atmosphere exchange data type type(mct_aVect) , intent(inout) :: l2x_l ! Land to coupler export state on land grid integer , intent(in) :: begg ! beginning grid cell index integer , intent(in) :: endg ! ending grid cell index ! ! !LOCAL VARIABLES: integer :: g,i ! Indices ! ! !REVISION HISTORY: ! Author: Mariana Vertenstein ! !EOP !--------------------------------------------------------------------------- l2x_l%rAttr(:,:) = 0.0_r8 ! ccsm sign convention is that fluxes are positive downward do g = begg,endg i = 1 + (g-begg) l2x_l%rAttr(index_l2x_Sl_landfrac,i) = 0._r8 ! Will be filled in later l2x_l%rAttr(index_l2x_Sl_t,i) = l2a%t_rad(g) l2x_l%rAttr(index_l2x_Sl_snowh,i) = l2a%h2osno(g) l2x_l%rAttr(index_l2x_Sl_avsdr,i) = l2a%albd(g,1) l2x_l%rAttr(index_l2x_Sl_anidr,i) = l2a%albd(g,2) l2x_l%rAttr(index_l2x_Sl_avsdf,i) = l2a%albi(g,1) l2x_l%rAttr(index_l2x_Sl_anidf,i) = l2a%albi(g,2) l2x_l%rAttr(index_l2x_Sl_tref,i) = l2a%t_ref2m(g) l2x_l%rAttr(index_l2x_Sl_qref,i) = l2a%q_ref2m(g) l2x_l%rAttr(index_l2x_Fall_taux,i) = -l2a%taux(g) l2x_l%rAttr(index_l2x_Fall_tauy,i) = -l2a%tauy(g) l2x_l%rAttr(index_l2x_Fall_lat,i) = -l2a%eflx_lh_tot(g) l2x_l%rAttr(index_l2x_Fall_sen,i) = -l2a%eflx_sh_tot(g) l2x_l%rAttr(index_l2x_Fall_lwup,i) = -l2a%eflx_lwrad_out(g) l2x_l%rAttr(index_l2x_Fall_evap,i) = -l2a%qflx_evap_tot(g) l2x_l%rAttr(index_l2x_Fall_swnet,i) = l2a%fsa(g) if (index_l2x_Fall_nee /= 0) then l2x_l%rAttr(index_l2x_Fall_nee,i) = -l2a%nee(g) end if ! optional fields for dust. The index = 0 is a good way to flag it, ! but I have set it up so that l2a doesn't have ram1,fv,flxdst[1-4] if ! progsslt or dust aren't running. #if ( defined DUST || defined PROGSSLT ) if (index_l2x_Sl_ram1 /= 0 ) l2x_l%rAttr(index_l2x_Sl_ram1,i) = l2a%ram1(g) if (index_l2x_Sl_fv /= 0 ) l2x_l%rAttr(index_l2x_Sl_fv,i) = l2a%fv(g) #endif #if ( defined DUST ) if (index_l2x_Fall_flxdst1 /= 0 ) l2x_l%rAttr(index_l2x_Fall_flxdst1,i)= -l2a%flxdst(g,1) if (index_l2x_Fall_flxdst2 /= 0 ) l2x_l%rAttr(index_l2x_Fall_flxdst2,i)= -l2a%flxdst(g,2) if (index_l2x_Fall_flxdst3 /= 0 ) l2x_l%rAttr(index_l2x_Fall_flxdst3,i)= -l2a%flxdst(g,3) if (index_l2x_Fall_flxdst4 /= 0 ) l2x_l%rAttr(index_l2x_Fall_flxdst4,i)= -l2a%flxdst(g,4) #endif if ( index_l2x_Sl_ddvel /= 0 ) l2x_l%rAttr(index_l2x_Sl_ddvel:index_l2x_Sl_ddvel+n_drydep-1,i) = l2a%ddvel(g,:n_drydep) #ifdef VOC if (index_l2x_Fall_flxvoc1 /= 0 ) l2x_l%rAttr(index_l2x_Fall_flxvoc1,i)= -l2a%flxvoc(g,1) if (index_l2x_Fall_flxvoc2 /= 0 ) l2x_l%rAttr(index_l2x_Fall_flxvoc2,i)= -l2a%flxvoc(g,2) if (index_l2x_Fall_flxvoc3 /= 0 ) l2x_l%rAttr(index_l2x_Fall_flxvoc3,i)= -l2a%flxvoc(g,3) if (index_l2x_Fall_flxvoc4 /= 0 ) l2x_l%rAttr(index_l2x_Fall_flxvoc4,i)= -l2a%flxvoc(g,4) if (index_l2x_Fall_flxvoc5 /= 0 ) l2x_l%rAttr(index_l2x_Fall_flxvoc5,i)= -l2a%flxvoc(g,5) #endif end do end subroutine lnd_export_mct !==================================================================================== !--------------------------------------------------------------------------- !BOP ! ! !IROUTINE: lnd_import_mct ! ! !INTERFACE: subroutine lnd_import_mct( x2l_l, a2l, begg, endg ) 2,13 ! ! !DESCRIPTION: ! ! Convert the input data from the coupler to the land model from MCT import state ! into internal clm data types. ! !--------------------------------------------------------------------------- ! !USES: use shr_kind_mod , only: r8 => shr_kind_r8 use clm_atmlnd , only: atm2lnd_type use clm_varctl , only: co2_type, co2_ppmv use clm_varcon , only: rair, o2_molar_const #if (defined C13) use clm_varcon , only: c13ratio #endif use shr_const_mod , only: SHR_CONST_TKFRZ use abortutils , only: endrun use clm_varctl , only: set_caerdep_from_file, set_dustdep_from_file use clm_varctl , only: iulog use mct_mod , only: mct_aVect use seq_flds_indices implicit none ! !ARGUMENTS: type(mct_aVect) , intent(inout) :: x2l_l ! Driver MCT import state to land model type(atm2lnd_type), intent(inout) :: a2l ! clm internal input data type integer , intent(in) :: begg integer , intent(in) :: endg ! ! !LOCAL VARIABLES: integer :: g,i,nstep,ier ! indices, number of steps, and error code real(r8) :: forc_rainc ! rainxy Atm flux mm/s real(r8) :: e ! vapor pressure (Pa) real(r8) :: qsat ! saturation specific humidity (kg/kg) real(r8) :: forc_rainl ! rainxy Atm flux mm/s real(r8) :: forc_snowc ! snowfxy Atm flux mm/s real(r8) :: forc_snowl ! snowfxl Atm flux mm/s real(r8) :: co2_ppmv_diag ! temporary real(r8) :: co2_ppmv_prog ! temporary real(r8) :: co2_ppmv_val ! temporary integer :: co2_type_idx ! integer flag for co2_type options real(r8) :: esatw ! saturation vapor pressure over water (Pa) real(r8) :: esati ! saturation vapor pressure over ice (Pa) real(r8) :: a0,a1,a2,a3,a4,a5,a6 ! coefficients for esat over water real(r8) :: b0,b1,b2,b3,b4,b5,b6 ! coefficients for esat over ice real(r8) :: tdc, t ! Kelvins to Celcius function and its input character(len=32), parameter :: sub = 'lnd_import_mct' ! Constants to compute vapor pressure parameter (a0=6.107799961_r8 , a1=4.436518521e-01_r8, & a2=1.428945805e-02_r8, a3=2.650648471e-04_r8, & a4=3.031240396e-06_r8, a5=2.034080948e-08_r8, & a6=6.136820929e-11_r8) parameter (b0=6.109177956_r8 , b1=5.034698970e-01_r8, & b2=1.886013408e-02_r8, b3=4.176223716e-04_r8, & b4=5.824720280e-06_r8, b5=4.838803174e-08_r8, & b6=1.838826904e-10_r8) ! ! function declarations ! tdc(t) = min( 50._r8, max(-50._r8,(t-SHR_CONST_TKFRZ)) ) esatw(t) = 100._r8*(a0+t*(a1+t*(a2+t*(a3+t*(a4+t*(a5+t*a6)))))) esati(t) = 100._r8*(b0+t*(b1+t*(b2+t*(b3+t*(b4+t*(b5+t*b6)))))) ! ! !REVISION HISTORY: ! Author: Mariana Vertenstein ! 27 February 2008: Keith Oleson; Forcing height change ! !EOP !--------------------------------------------------------------------------- co2_type_idx = 0 if (co2_type == 'prognostic') then co2_type_idx = 1 else if (co2_type == 'diagnostic') then co2_type_idx = 2 end if if (co2_type == 'prognostic' .and. index_x2l_Sa_co2prog == 0) then call endrun( sub//' ERROR: must have nonzero index_x2l_Sa_co2prog for co2_type equal to prognostic' ) else if (co2_type == 'diagnostic' .and. index_x2l_Sa_co2diag == 0) then call endrun( sub//' ERROR: must have nonzero index_x2l_Sa_co2diag for co2_type equal to diagnostic' ) end if ! Note that the precipitation fluxes received from the coupler ! are in units of kg/s/m^2. To convert these precipitation rates ! in units of mm/sec, one must divide by 1000 kg/m^3 and multiply ! by 1000 mm/m resulting in an overall factor of unity. ! Below the units are therefore given in mm/s. do g = begg,endg i = 1 + (g - begg) ! Determine required receive fields a2l%forc_hgt(g) = x2l_l%rAttr(index_x2l_Sa_z,i) ! zgcmxy Atm state m a2l%forc_u(g) = x2l_l%rAttr(index_x2l_Sa_u,i) ! forc_uxy Atm state m/s a2l%forc_v(g) = x2l_l%rAttr(index_x2l_Sa_v,i) ! forc_vxy Atm state m/s a2l%forc_th(g) = x2l_l%rAttr(index_x2l_Sa_ptem,i) ! forc_thxy Atm state K a2l%forc_q(g) = x2l_l%rAttr(index_x2l_Sa_shum,i) ! forc_qxy Atm state kg/kg a2l%forc_pbot(g) = x2l_l%rAttr(index_x2l_Sa_pbot,i) ! ptcmxy Atm state Pa a2l%forc_t(g) = x2l_l%rAttr(index_x2l_Sa_tbot,i) ! forc_txy Atm state K a2l%forc_lwrad(g) = x2l_l%rAttr(index_x2l_Faxa_lwdn,i) ! flwdsxy Atm flux W/m^2 forc_rainc = x2l_l%rAttr(index_x2l_Faxa_rainc,i) ! mm/s forc_rainl = x2l_l%rAttr(index_x2l_Faxa_rainl,i) ! mm/s forc_snowc = x2l_l%rAttr(index_x2l_Faxa_snowc,i) ! mm/s forc_snowl = x2l_l%rAttr(index_x2l_Faxa_snowl,i) ! mm/s a2l%forc_solad(g,2) = x2l_l%rAttr(index_x2l_Faxa_swndr,i) ! forc_sollxy Atm flux W/m^2 a2l%forc_solad(g,1) = x2l_l%rAttr(index_x2l_Faxa_swvdr,i) ! forc_solsxy Atm flux W/m^2 a2l%forc_solai(g,2) = x2l_l%rAttr(index_x2l_Faxa_swndf,i) ! forc_solldxy Atm flux W/m^2 a2l%forc_solai(g,1) = x2l_l%rAttr(index_x2l_Faxa_swvdf,i) ! forc_solsdxy Atm flux W/m^2 ! atmosphere coupling, if using prognostic aerosols if ( .not. set_caerdep_from_file ) then a2l%forc_aer(g,1) = x2l_l%rAttr(index_x2l_Faxa_bcphidry,i) a2l%forc_aer(g,2) = x2l_l%rAttr(index_x2l_Faxa_bcphodry,i) a2l%forc_aer(g,3) = x2l_l%rAttr(index_x2l_Faxa_bcphiwet,i) a2l%forc_aer(g,4) = x2l_l%rAttr(index_x2l_Faxa_ocphidry,i) a2l%forc_aer(g,5) = x2l_l%rAttr(index_x2l_Faxa_ocphodry,i) a2l%forc_aer(g,6) = x2l_l%rAttr(index_x2l_Faxa_ocphiwet,i) endif if ( .not. set_dustdep_from_file ) then a2l%forc_aer(g,7) = x2l_l%rAttr(index_x2l_Faxa_dstwet1,i) a2l%forc_aer(g,8) = x2l_l%rAttr(index_x2l_Faxa_dstdry1,i) a2l%forc_aer(g,9) = x2l_l%rAttr(index_x2l_Faxa_dstwet2,i) a2l%forc_aer(g,10) = x2l_l%rAttr(index_x2l_Faxa_dstdry2,i) a2l%forc_aer(g,11) = x2l_l%rAttr(index_x2l_Faxa_dstwet3,i) a2l%forc_aer(g,12) = x2l_l%rAttr(index_x2l_Faxa_dstdry3,i) a2l%forc_aer(g,13) = x2l_l%rAttr(index_x2l_Faxa_dstwet4,i) a2l%forc_aer(g,14) = x2l_l%rAttr(index_x2l_Faxa_dstdry4,i) endif ! Determine optional receive fields if (index_x2l_Sa_co2prog /= 0) then co2_ppmv_prog = x2l_l%rAttr(index_x2l_Sa_co2prog,i) ! co2 atm state prognostic else co2_ppmv_prog = co2_ppmv end if if (index_x2l_Sa_co2diag /= 0) then co2_ppmv_diag = x2l_l%rAttr(index_x2l_Sa_co2diag,i) ! co2 atm state diagnostic else co2_ppmv_diag = co2_ppmv end if ! Determine derived quantities for required fields a2l%forc_hgt_u(g) = a2l%forc_hgt(g) !observational height of wind [m] a2l%forc_hgt_t(g) = a2l%forc_hgt(g) !observational height of temperature [m] a2l%forc_hgt_q(g) = a2l%forc_hgt(g) !observational height of humidity [m] a2l%forc_vp(g) = a2l%forc_q(g) * a2l%forc_pbot(g) & / (0.622_r8 + 0.378_r8 * a2l%forc_q(g)) a2l%forc_rho(g) = (a2l%forc_pbot(g) - 0.378_r8 * a2l%forc_vp(g)) & / (rair * a2l%forc_t(g)) a2l%forc_po2(g) = o2_molar_const * a2l%forc_pbot(g) a2l%forc_wind(g) = sqrt(a2l%forc_u(g)**2 + a2l%forc_v(g)**2) a2l%forc_solar(g) = a2l%forc_solad(g,1) + a2l%forc_solai(g,1) + & a2l%forc_solad(g,2) + a2l%forc_solai(g,2) a2l%forc_rain(g) = forc_rainc + forc_rainl a2l%forc_snow(g) = forc_snowc + forc_snowl a2l%rainf (g) = a2l%forc_rain(g) + a2l%forc_snow(g) if (a2l%forc_t(g) > SHR_CONST_TKFRZ) then e = esatw(tdc(a2l%forc_t(g))) else e = esati(tdc(a2l%forc_t(g))) end if qsat = 0.622_r8*e / (a2l%forc_pbot(g) - 0.378_r8*e) a2l%forc_rh(g) = 100.0_r8*(a2l%forc_q(g) / qsat) ! Make sure relative humidity is properly bounded ! a2l%forc_rh(g) = min( 100.0_r8, a2l%forc_rh(g) ) ! a2l%forc_rh(g) = max( 0.0_r8, a2l%forc_rh(g) ) ! Determine derived quantities for optional fields ! Note that the following does unit conversions from ppmv to partial pressures (Pa) ! Note that forc_pbot is in Pa if (co2_type_idx == 1) then co2_ppmv_val = co2_ppmv_prog else if (co2_type_idx == 2) then co2_ppmv_val = co2_ppmv_diag else co2_ppmv_val = co2_ppmv end if a2l%forc_pco2(g) = co2_ppmv_val * 1.e-6_r8 * a2l%forc_pbot(g) #if (defined C13) a2l%forc_pc13o2(g) = co2_ppmv_val * c13ratio * 1.e-6_r8 * a2l%forc_pbot(g) #endif end do end subroutine lnd_import_mct !=============================================================================== !--------------------------------------------------------------------------- !BOP ! ! !IROUTINE: lnd_domain_mct ! ! !INTERFACE: subroutine lnd_domain_mct( lsize, gsMap_l, dom_l ) 2,8 ! ! !DESCRIPTION: ! ! Send the land model domain information to the coupler ! !--------------------------------------------------------------------------- ! !USES: use shr_kind_mod, only : r8 => shr_kind_r8 use clm_varcon , only : re use domainMod , only : adomain use decompMod , only : get_proc_bounds_atm, adecomp use spmdMod , only : iam use mct_mod , only : mct_gsMap, mct_gGrid, mct_gGrid_importIAttr, & mct_gGrid_importRAttr, mct_gGrid_init, & mct_gsMap_orderedPoints use seq_flds_mod implicit none ! !ARGUMENTS: integer , intent(in) :: lsize ! land model domain data size type(mct_gsMap), intent(inout) :: gsMap_l ! Output land model MCT GS map type(mct_ggrid), intent(out) :: dom_l ! Output domain information for land model ! ! !REVISION HISTORY: ! Author: Mariana Vertenstein ! !EOP !--------------------------------------------------------------------------- ! ! Local Variables ! integer :: g,i,j ! index integer :: begg, endg ! beginning and ending gridcell indices real(r8), pointer :: data(:) ! temporary integer , pointer :: idata(:) ! temporary !------------------------------------------------------------------- ! ! Initialize mct domain type ! lat/lon in degrees, area in radians^2, mask is 1 (land), 0 (non-land) ! Note that in addition land carries around landfrac for the purposes of domain checking ! call mct_gGrid_init( GGrid=dom_l, CoordChars=trim(seq_flds_dom_coord), & OtherChars=trim(seq_flds_dom_other), lsize=lsize ) ! ! Allocate memory ! allocate(data(lsize)) ! ! Determine global gridpoint number attribute, GlobGridNum, which is set automatically by MCT ! call mct_gsMap_orderedPoints(gsMap_l, iam, idata) call mct_gGrid_importIAttr(dom_l,'GlobGridNum',idata,lsize) ! ! Determine domain (numbering scheme is: West to East and South to North to South pole) ! Initialize attribute vector with special value ! data(:) = -9999.0_R8 call mct_gGrid_importRAttr(dom_l,"lat" ,data,lsize) call mct_gGrid_importRAttr(dom_l,"lon" ,data,lsize) call mct_gGrid_importRAttr(dom_l,"area" ,data,lsize) call mct_gGrid_importRAttr(dom_l,"aream",data,lsize) data(:) = 0.0_R8 call mct_gGrid_importRAttr(dom_l,"mask" ,data,lsize) ! ! Determine bounds ! call get_proc_bounds_atm(begg, endg) ! ! Fill in correct values for domain components ! Note aream will be filled in in the atm-lnd mapper ! do g = begg,endg i = 1 + (g - begg) data(i) = adomain%lonc(g) end do call mct_gGrid_importRattr(dom_l,"lon",data,lsize) do g = begg,endg i = 1 + (g - begg) data(i) = adomain%latc(g) end do call mct_gGrid_importRattr(dom_l,"lat",data,lsize) do g = begg,endg i = 1 + (g - begg) data(i) = adomain%area(g)/(re*re) end do call mct_gGrid_importRattr(dom_l,"area",data,lsize) do g = begg,endg i = 1 + (g - begg) data(i) = real(adomain%mask(g), r8) end do call mct_gGrid_importRattr(dom_l,"mask",data,lsize) do g = begg,endg i = 1 + (g - begg) data(i) = real(adomain%frac(g), r8) end do call mct_gGrid_importRattr(dom_l,"frac",data,lsize) deallocate(data) deallocate(idata) end subroutine lnd_domain_mct !=============================================================================== #ifdef RTM !--------------------------------------------------------------------------- !BOP ! ! !IROUTINE: rof_SetgsMap_mct ! ! !INTERFACE: subroutine rof_SetgsMap_mct( mpicom_l, LNDID, gsMap_r ) 1,8 ! ! !DESCRIPTION: ! ! Set the MCT GS map for the runoff model ! !--------------------------------------------------------------------------- ! !USES: use shr_kind_mod, only : r8 => shr_kind_r8 use clm_varpar , only : rtmlon, rtmlat use RunoffMod , only : runoff use abortutils , only : endrun use clm_varctl , only : iulog use mct_mod , only : mct_gsMap, mct_gsMap_init implicit none ! !ARGUMENTS: integer , intent(in) :: mpicom_l ! MPI communicator for land model integer , intent(in) :: LNDID ! Land model identifier type(mct_gsMap), intent(out) :: gsMap_r ! MCT GS map for runoff model data ! ! !REVISION HISTORY: ! Author: Mariana Vertenstein ! !EOP !--------------------------------------------------------------------------- ! ! Local Variables ! integer,allocatable :: gindex(:) ! indexing for runoff grid cells integer :: n, ni ! indices integer :: lsize,gsize ! size of runoff data and number of grid cells integer :: ier ! error code character(len=32), parameter :: sub = 'rof_SetgsMap_mct' !------------------------------------------------------------------- ! Build the rof grid numbering for MCT ! NOTE: Numbering scheme is: West to East and South to North ! starting at south pole. Should be the same as what's used in SCRIP gsize = rtmlon*rtmlat lsize = runoff%lnumro allocate(gindex(lsize),stat=ier) ni = 0 do n = runoff%begr,runoff%endr if (runoff%mask(n) == 2) then ni = ni + 1 if (ni > runoff%lnumro) then write(iulog,*) sub, ' : ERROR runoff count',n,ni,runoff%lnumro call endrun( sub//' ERROR: runoff > expected' ) endif gindex(ni) = runoff%gindex(n) endif end do if (ni /= runoff%lnumro) then write(iulog,*) sub, ' : ERROR runoff total count',ni,runoff%lnumro call endrun( sub//' ERROR: runoff not equal to expected' ) endif call mct_gsMap_init( gsMap_r, gindex, mpicom_l, LNDID, lsize, gsize ) deallocate(gindex) end subroutine rof_SetgsMap_mct !=============================================================================== !--------------------------------------------------------------------------- !BOP ! ! !IROUTINE: rof_domain_mct ! ! !INTERFACE: subroutine rof_domain_mct( lsize, gsMap_r, dom_r ) 1,11 ! ! !DESCRIPTION: ! ! Send the runoff model domain information to the coupler ! !--------------------------------------------------------------------------- ! !USES: use shr_kind_mod, only : r8 => shr_kind_r8 use clm_varcon , only : re use RunoffMod , only : runoff use abortutils , only : endrun use clm_varctl , only : iulog use spmdMod , only : iam use mct_mod , only : mct_gsMap, mct_gGrid, mct_gGrid_importIAttr, & mct_gGrid_importRAttr, mct_gGrid_init, mct_gsMap_orderedPoints use seq_flds_mod use seq_flds_indices implicit none ! !ARGUMENTS: integer , intent(in) :: lsize ! Size of runoff domain information type(mct_gsMap), intent(inout) :: gsMap_r ! Output MCT GS map for runoff model type(mct_ggrid), intent(out) :: dom_r ! Domain information from the runoff model ! ! !REVISION HISTORY: ! Author: Mariana Vertenstein ! !EOP !--------------------------------------------------------------------------- ! ! Local Variables ! integer :: n, ni ! index real(r8), pointer :: data(:) ! temporary integer , pointer :: idata(:) ! temporary character(len=32), parameter :: sub = 'rof_domain_mct' !------------------------------------------------------------------- ! ! Initialize mct domain type ! lat/lon in degrees, area in radians^2, mask is 1 (land), 0 (non-land) ! Note that in addition land carries around landfrac for the purposes of domain checking ! call mct_gGrid_init( GGrid=dom_r, CoordChars=trim(seq_flds_dom_coord), & OtherChars=trim(seq_flds_dom_other), lsize=lsize ) ! ! Allocate memory ! allocate(data(lsize)) ! ! Determine global gridpoint number attribute, GlobGridNum, which is set automatically by MCT ! call mct_gsMap_orderedPoints(gsMap_r, iam, idata) call mct_gGrid_importIAttr(dom_r,'GlobGridNum',idata,lsize) ! ! Determine domain (numbering scheme is: West to East and South to North to South pole) ! Initialize attribute vector with special value ! data(:) = -9999.0_R8 call mct_gGrid_importRAttr(dom_r,"lat" ,data,lsize) call mct_gGrid_importRAttr(dom_r,"lon" ,data,lsize) call mct_gGrid_importRAttr(dom_r,"area" ,data,lsize) call mct_gGrid_importRAttr(dom_r,"aream",data,lsize) data(:) = 0.0_R8 call mct_gGrid_importRAttr(dom_r,"mask" ,data,lsize) ! ! Determine bounds numbering consistency ! ni = 0 do n = runoff%begr,runoff%endr if (runoff%mask(n) == 2) then ni = ni + 1 if (ni > runoff%lnumro) then write(iulog,*) sub, ' : ERROR runoff count',n,ni,runoff%lnumro call endrun( sub//' ERROR: runoff > expected' ) endif end if end do if (ni /= runoff%lnumro) then write(iulog,*) sub, ' : ERROR runoff total count',ni,runoff%lnumro call endrun( sub//' ERROR: runoff not equal to expected' ) endif ! ! Fill in correct values for domain components ! Note aream will be filled in in the atm-lnd mapper ! ni = 0 do n = runoff%begr,runoff%endr if (runoff%mask(n) == 2) then ni = ni + 1 data(ni) = runoff%lonc(n) end if end do call mct_gGrid_importRattr(dom_r,"lon",data,lsize) ni = 0 do n = runoff%begr,runoff%endr if (runoff%mask(n) == 2) then ni = ni + 1 data(ni) = runoff%latc(n) end if end do call mct_gGrid_importRattr(dom_r,"lat",data,lsize) ni = 0 do n = runoff%begr,runoff%endr if (runoff%mask(n) == 2) then ni = ni + 1 data(ni) = runoff%area(n)*1.0e-6_r8/(re*re) end if end do call mct_gGrid_importRattr(dom_r,"area",data,lsize) ni = 0 do n = runoff%begr,runoff%endr if (runoff%mask(n) == 2) then ni = ni + 1 data(ni) = 1.0_r8 end if end do call mct_gGrid_importRattr(dom_r,"mask",data,lsize) call mct_gGrid_importRattr(dom_r,"frac",data,lsize) deallocate(data) deallocate(idata) end subroutine rof_domain_mct !==================================================================================== !--------------------------------------------------------------------------- !BOP ! ! !IROUTINE: rof_export_mct ! ! !INTERFACE: subroutine rof_export_mct( r2x_r) 2,10 ! ! !DESCRIPTION: ! ! Send the runoff model export state to the CCSM coupler ! !--------------------------------------------------------------------------- ! !USES: use shr_kind_mod, only : r8 => shr_kind_r8 use RunoffMod , only : runoff, nt_rtm, rtm_tracers use abortutils , only : endrun use clm_varctl , only : iulog, ice_runoff use mct_mod , only : mct_aVect use seq_flds_indices implicit none ! !ARGUMENTS: type(mct_aVect), intent(inout) :: r2x_r ! Runoff to coupler export state ! ! !REVISION HISTORY: ! Author: Mariana Vertenstein ! !EOP !--------------------------------------------------------------------------- ! ! Local variables ! integer :: ni, n, nt, nliq, nfrz character(len=32), parameter :: sub = 'rof_export_mct' !----------------------------------------------------- nliq = 0 nfrz = 0 do nt = 1,nt_rtm if (trim(rtm_tracers(nt)) == 'LIQ') then nliq = nt endif if (trim(rtm_tracers(nt)) == 'ICE') then nfrz = nt endif enddo if (nliq == 0 .or. nfrz == 0) then write(iulog,*)'RtmUpdateInput: ERROR in rtm_tracers LIQ ICE ',nliq,nfrz,rtm_tracers call endrun() endif ni = 0 if ( ice_runoff )then do n = runoff%begr,runoff%endr if (runoff%mask(n) == 2) then ni = ni + 1 ! liquid and ice runoff are treated separately r2x_r%rAttr(index_r2x_Forr_roff,ni) = runoff%runoff(n,nliq)/(runoff%area(n)*1.0e-6_r8*1000._r8) r2x_r%rAttr(index_r2x_Forr_ioff,ni) = runoff%runoff(n,nfrz)/(runoff%area(n)*1.0e-6_r8*1000._r8) if (ni > runoff%lnumro) then write(iulog,*) sub, ' : ERROR runoff count',n,ni call endrun( sub//' : ERROR runoff > expected' ) endif endif end do else do n = runoff%begr,runoff%endr if (runoff%mask(n) == 2) then ni = ni + 1 ! liquid and ice runoff are bundled together to liquid runoff, and then ice runoff set to zero r2x_r%rAttr(index_r2x_Forr_roff,ni) = & (runoff%runoff(n,nfrz)+runoff%runoff(n,nliq))/(runoff%area(n)*1.0e-6_r8*1000._r8) r2x_r%rAttr(index_r2x_Forr_ioff,ni) = 0._r8 if (ni > runoff%lnumro) then write(iulog,*) sub, ' : ERROR runoff count',n,ni call endrun( sub//' : ERROR runoff > expected' ) endif endif end do end if if (ni /= runoff%lnumro) then write(iulog,*) sub, ' : ERROR runoff total count',ni,runoff%lnumro call endrun( sub//' : ERROR runoff not equal to expected' ) endif end subroutine rof_export_mct #endif !==================================================================================== subroutine sno_export_mct( s2x, s2x_s ) 2,4 use clm_glclnd , only : lnd2glc_type use decompMod , only : get_proc_bounds_atm use seq_flds_indices type(lnd2glc_type), intent(inout) :: s2x type(mct_aVect) , intent(inout) :: s2x_s integer :: g,i integer :: begg, endg ! beginning and ending gridcell indices call get_proc_bounds_atm(begg, endg) s2x_s%rAttr(:,:) = 0.0_r8 ! qice is positive if ice is growing, negative if melting do g = begg,endg i = 1 + (g-begg) #if (defined GLC_NEC_10 || defined GLC_NEC_5 || defined GLC_NEC_3 || defined GLC_NEC_1) s2x_s%rAttr(index_s2x_Ss_tsrf01,i) = s2x%tsrf(g,1) s2x_s%rAttr(index_s2x_Ss_topo01,i) = s2x%topo(g,1) s2x_s%rAttr(index_s2x_Fgss_qice01,i) = s2x%qice(g,1) #endif #if (defined GLC_NEC_10 || defined GLC_NEC_5 || defined GLC_NEC_3 ) s2x_s%rAttr(index_s2x_Ss_tsrf02,i) = s2x%tsrf(g,2) s2x_s%rAttr(index_s2x_Ss_topo02,i) = s2x%topo(g,2) s2x_s%rAttr(index_s2x_Fgss_qice02,i) = s2x%qice(g,2) s2x_s%rAttr(index_s2x_Ss_tsrf03,i) = s2x%tsrf(g,3) s2x_s%rAttr(index_s2x_Ss_topo03,i) = s2x%topo(g,3) s2x_s%rAttr(index_s2x_Fgss_qice03,i) = s2x%qice(g,3) #endif #if (defined GLC_NEC_10 || defined GLC_NEC_5 ) s2x_s%rAttr(index_s2x_Ss_tsrf04,i) = s2x%tsrf(g,4) s2x_s%rAttr(index_s2x_Ss_topo04,i) = s2x%topo(g,4) s2x_s%rAttr(index_s2x_Fgss_qice04,i) = s2x%qice(g,4) s2x_s%rAttr(index_s2x_Ss_tsrf05,i) = s2x%tsrf(g,5) s2x_s%rAttr(index_s2x_Ss_topo05,i) = s2x%topo(g,5) s2x_s%rAttr(index_s2x_Fgss_qice05,i) = s2x%qice(g,5) #endif #if (defined GLC_NEC_10 ) s2x_s%rAttr(index_s2x_Ss_tsrf06,i) = s2x%tsrf(g,6) s2x_s%rAttr(index_s2x_Ss_topo06,i) = s2x%topo(g,6) s2x_s%rAttr(index_s2x_Fgss_qice06,i) = s2x%qice(g,6) s2x_s%rAttr(index_s2x_Ss_tsrf07,i) = s2x%tsrf(g,7) s2x_s%rAttr(index_s2x_Ss_topo07,i) = s2x%topo(g,7) s2x_s%rAttr(index_s2x_Fgss_qice07,i) = s2x%qice(g,7) s2x_s%rAttr(index_s2x_Ss_tsrf08,i) = s2x%tsrf(g,8) s2x_s%rAttr(index_s2x_Ss_topo08,i) = s2x%topo(g,8) s2x_s%rAttr(index_s2x_Fgss_qice08,i) = s2x%qice(g,8) s2x_s%rAttr(index_s2x_Ss_tsrf09,i) = s2x%tsrf(g,9) s2x_s%rAttr(index_s2x_Ss_topo09,i) = s2x%topo(g,9) s2x_s%rAttr(index_s2x_Fgss_qice09,i) = s2x%qice(g,9) s2x_s%rAttr(index_s2x_Ss_tsrf10,i) = s2x%tsrf(g,10) s2x_s%rAttr(index_s2x_Ss_topo10,i) = s2x%topo(g,10) s2x_s%rAttr(index_s2x_Fgss_qice10,i) = s2x%qice(g,10) #endif end do ! g end subroutine sno_export_mct !==================================================================================== subroutine sno_import_mct( x2s_s, x2s ) 1,7 use clm_glclnd , only: glc2lnd_type use decompMod , only: get_proc_bounds_atm use abortutils , only: endrun use clm_varctl , only: iulog use mct_mod , only: mct_aVect use seq_flds_indices ! ! Arguments ! type(mct_aVect) , intent(inout) :: x2s_s type(glc2lnd_type), intent(inout) :: x2s ! ! Local Variables ! integer :: g,i integer :: begg, endg ! beginning and ending gridcell indices character(len=32), parameter :: sub = 'sno_import_mct' !----------------------------------------------------- call get_proc_bounds_atm(begg, endg) do g = begg,endg i = 1 + (g - begg) #if (defined GLC_NEC_10 || defined GLC_NEC_5 || defined GLC_NEC_3 || defined GLC_NEC_1) x2s%frac(g,1) = x2s_s%rAttr(index_x2s_Sg_frac01,i) x2s%topo(g,1) = x2s_s%rAttr(index_x2s_Sg_topo01,i) x2s%hflx(g,1) = x2s_s%rAttr(index_x2s_Fsgg_hflx01,i) x2s%rofi(g,1) = x2s_s%rAttr(index_x2s_Fsgg_rofi01,i) x2s%rofl(g,1) = x2s_s%rAttr(index_x2s_Fsgg_rofl01,i) #endif #if (defined GLC_NEC_10 || defined GLC_NEC_5 || defined GLC_NEC_3 ) x2s%frac(g,2) = x2s_s%rAttr(index_x2s_Sg_frac02,i) x2s%topo(g,2) = x2s_s%rAttr(index_x2s_Sg_topo02,i) x2s%hflx(g,2) = x2s_s%rAttr(index_x2s_Fsgg_hflx02,i) x2s%rofi(g,2) = x2s_s%rAttr(index_x2s_Fsgg_rofi02,i) x2s%rofi(g,2) = x2s_s%rAttr(index_x2s_Fsgg_rofl02,i) x2s%frac(g,3) = x2s_s%rAttr(index_x2s_Sg_frac03,i) x2s%topo(g,3) = x2s_s%rAttr(index_x2s_Sg_topo03,i) x2s%hflx(g,3) = x2s_s%rAttr(index_x2s_Fsgg_hflx03,i) x2s%rofi(g,3) = x2s_s%rAttr(index_x2s_Fsgg_rofi03,i) x2s%rofl(g,3) = x2s_s%rAttr(index_x2s_Fsgg_rofl03,i) #endif #if (defined GLC_NEC_10 || defined GLC_NEC_5 ) x2s%frac(g,4) = x2s_s%rAttr(index_x2s_Sg_frac04,i) x2s%topo(g,4) = x2s_s%rAttr(index_x2s_Sg_topo04,i) x2s%hflx(g,4) = x2s_s%rAttr(index_x2s_Fsgg_hflx04,i) x2s%rofi(g,4) = x2s_s%rAttr(index_x2s_Fsgg_rofi04,i) x2s%rofl(g,4) = x2s_s%rAttr(index_x2s_Fsgg_rofl04,i) x2s%frac(g,5) = x2s_s%rAttr(index_x2s_Sg_frac05,i) x2s%topo(g,5) = x2s_s%rAttr(index_x2s_Sg_topo05,i) x2s%hflx(g,5) = x2s_s%rAttr(index_x2s_Fsgg_hflx05,i) x2s%rofi(g,5) = x2s_s%rAttr(index_x2s_Fsgg_rofi05,i) x2s%rofl(g,5) = x2s_s%rAttr(index_x2s_Fsgg_rofl05,i) #endif #if (defined GLC_NEC_10 ) x2s%frac(g,6) = x2s_s%rAttr(index_x2s_Sg_frac06,i) x2s%topo(g,6) = x2s_s%rAttr(index_x2s_Sg_topo06,i) x2s%hflx(g,6) = x2s_s%rAttr(index_x2s_Fsgg_hflx06,i) x2s%rofi(g,6) = x2s_s%rAttr(index_x2s_Fsgg_rofi06,i) x2s%rofi(g,6) = x2s_s%rAttr(index_x2s_Fsgg_rofl06,i) x2s%frac(g,7) = x2s_s%rAttr(index_x2s_Sg_frac07,i) x2s%topo(g,7) = x2s_s%rAttr(index_x2s_Sg_topo07,i) x2s%hflx(g,7) = x2s_s%rAttr(index_x2s_Fsgg_hflx07,i) x2s%rofi(g,7) = x2s_s%rAttr(index_x2s_Fsgg_rofi07,i) x2s%rofi(g,7) = x2s_s%rAttr(index_x2s_Fsgg_rofl07,i) x2s%frac(g,8) = x2s_s%rAttr(index_x2s_Sg_frac08,i) x2s%topo(g,8) = x2s_s%rAttr(index_x2s_Sg_topo08,i) x2s%hflx(g,8) = x2s_s%rAttr(index_x2s_Fsgg_hflx08,i) x2s%rofi(g,8) = x2s_s%rAttr(index_x2s_Fsgg_rofi08,i) x2s%rofl(g,8) = x2s_s%rAttr(index_x2s_Fsgg_rofl08,i) x2s%frac(g,9) = x2s_s%rAttr(index_x2s_Sg_frac09,i) x2s%topo(g,9) = x2s_s%rAttr(index_x2s_Sg_topo09,i) x2s%hflx(g,9) = x2s_s%rAttr(index_x2s_Fsgg_hflx09,i) x2s%rofi(g,9) = x2s_s%rAttr(index_x2s_Fsgg_rofi09,i) x2s%rofl(g,9) = x2s_s%rAttr(index_x2s_Fsgg_rofl09,i) x2s%frac(g,10) = x2s_s%rAttr(index_x2s_Sg_frac10,i) x2s%topo(g,10) = x2s_s%rAttr(index_x2s_Sg_topo10,i) x2s%hflx(g,10) = x2s_s%rAttr(index_x2s_Fsgg_hflx10,i) x2s%rofi(g,10) = x2s_s%rAttr(index_x2s_Fsgg_rofi10,i) x2s%rofl(g,10) = x2s_s%rAttr(index_x2s_Fsgg_rofl10,i) #endif end do ! g end subroutine sno_import_mct !==================================================================================== end module lnd_comp_mct