diff --git a/datm/atm_comp_nuopc.F90 b/datm/atm_comp_nuopc.F90 index 72c6b5972..99a91841b 100644 --- a/datm/atm_comp_nuopc.F90 +++ b/datm/atm_comp_nuopc.F90 @@ -124,6 +124,7 @@ module cdeps_datm_comp character(CL) :: factorFn_data = 'null' ! file containing correction factors data logical :: flds_presaero = .false. ! true => send valid prescribed aero fields to mediator logical :: flds_presndep = .false. ! true => send valid prescribed ndep fields to mediator + logical :: flds_preso3 = .false. ! true => send valid prescribed ozone fields to mediator logical :: flds_co2 = .false. ! true => send prescribed co2 to mediator logical :: flds_wiso = .false. ! true => send water isotopes to mediator character(CL) :: bias_correct = nullstr ! send bias correction fields to coupler @@ -230,7 +231,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) model_meshfile, model_maskfile, & nx_global, ny_global, restfilm, iradsw, factorFn_data, factorFn_mesh, & flds_presaero, flds_co2, flds_wiso, bias_correct, anomaly_forcing, & - skip_restart_read, flds_presndep + skip_restart_read, flds_presndep, flds_preso3 rc = ESMF_SUCCESS @@ -270,6 +271,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) call shr_mpi_bcast(restfilm , mpicom, 'restfilm') call shr_mpi_bcast(flds_presaero , mpicom, 'flds_presaero') call shr_mpi_bcast(flds_presndep , mpicom, 'flds_presndep') + call shr_mpi_bcast(flds_preso3 , mpicom, 'flds_preso3') call shr_mpi_bcast(flds_co2 , mpicom, 'flds_co2') call shr_mpi_bcast(flds_wiso , mpicom, 'flds_wiso') call shr_mpi_bcast(skip_restart_read , mpicom, 'skip_restart_read') @@ -288,6 +290,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) write(logunit,F00)' factorFn_mesh = ',trim(factorFn_mesh) write(logunit,F02)' flds_presaero = ',flds_presaero write(logunit,F02)' flds_presndep = ',flds_presndep + write(logunit,F02)' flds_preso3 = ',flds_preso3 write(logunit,F02)' flds_co2 = ',flds_co2 write(logunit,F02)' flds_wiso = ',flds_wiso write(logunit,F02)' skip_restart_read = ',skip_restart_read @@ -319,7 +322,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return case ('CLMNCEP') call datm_datamode_clmncep_advertise(exportState, fldsExport, flds_scalar_name, & - flds_co2, flds_wiso, flds_presaero, flds_presndep, rc) + flds_co2, flds_wiso, flds_presaero, flds_presndep, flds_preso3, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return case ('CPLHIST') call datm_datamode_cplhist_advertise(exportState, fldsExport, flds_scalar_name, & diff --git a/datm/cime_config/buildnml b/datm/cime_config/buildnml index 2ff95fdbe..575949b10 100755 --- a/datm/cime_config/buildnml +++ b/datm/cime_config/buildnml @@ -76,7 +76,7 @@ def _get_neon_data_availability(case, neonsite): oldestdate = datetime.strptime(neonatm[-10:],"%Y-%m.nc") neonatm = f'cdeps/{version}/{neonsite}/'+neonatm datavaliddate.append(neonatm) - if newestdate: + if newestdate: logger.info("Found tower data version {} for {} through {}".format(version, oldestdate, newestdate)) datavaliddate.sort() return datavaliddate @@ -105,6 +105,7 @@ def _create_namelists(case, confdir, inst_string, infile, nmlgen, data_list_path datm_topo = case.get_value("DATM_TOPO") datm_presaero = case.get_value("DATM_PRESAERO") datm_presndep = case.get_value("DATM_PRESNDEP") + datm_preso3 = case.get_value("DATM_PRESO3") datm_co2_tseries = case.get_value("DATM_CO2_TSERIES") atm_grid = case.get_value("ATM_GRID") model_grid = case.get_value("GRID") @@ -116,6 +117,8 @@ def _create_namelists(case, confdir, inst_string, infile, nmlgen, data_list_path "A DATM_MODE for CLM is incompatible with DATM_PRESAERO=none.") expect(datm_presndep != "none", "A DATM_MODE for CLM is incompatible with DATM_PRESNDEP=none.") + expect(datm_preso3 != "none", + "A DATM_MODE for CLM is incompatible with DATM_PRESO3=none.") expect(datm_topo != "none", "A DATM_MODE for CLM is incompatible with DATM_TOPO=none.") @@ -124,6 +127,7 @@ def _create_namelists(case, confdir, inst_string, infile, nmlgen, data_list_path logger.debug("DATM grid is {}".format(atm_grid)) logger.debug("DATM presaero mode is {}".format(datm_presaero)) logger.debug("DATM presndep mode is {}".format(datm_presndep)) + logger.debug("DATM preso3 mode is {}".format(datm_preso3)) logger.debug("DATM topo mode is {}".format(datm_topo)) # Initialize namelist defaults @@ -143,6 +147,7 @@ def _create_namelists(case, confdir, inst_string, infile, nmlgen, data_list_path config['datm_co2_tseries'] = datm_co2_tseries config['datm_presaero'] = datm_presaero config['datm_presndep'] = datm_presndep + config['datm_preso3'] = datm_preso3 if case.get_value('PTS_LON'): scol_lon = float(case.get_value('PTS_LON')) @@ -173,10 +178,13 @@ def _create_namelists(case, confdir, inst_string, infile, nmlgen, data_list_path streamlist.append("presaero.{}".format(datm_presaero)) if datm_presndep != "none": streamlist.append("presndep.{}".format(datm_presndep)) + if datm_preso3 != "none": + streamlist.append("preso3.{}".format(datm_preso3)) if datm_topo != "none": streamlist.append("topo.{}".format(datm_topo)) if datm_co2_tseries != "none": streamlist.append("co2tseries.{}".format(datm_co2_tseries)) + bias_correct = nmlgen.get_value("bias_correct") if bias_correct is not None: streamlist.append(bias_correct) @@ -189,10 +197,33 @@ def _create_namelists(case, confdir, inst_string, infile, nmlgen, data_list_path schema_file = os.path.join(_CDEPS_CONFIG,"stream_definition_v2.0.xsd") stream_file = os.path.join(_CDEPS_CONFIG,os.pardir, "datm","cime_config","stream_definition_datm.xml") streams = StreamCDEPS(stream_file, schema_file) - streams.create_stream_xml(streamlist, case, outfile, data_list_path, + streams.create_stream_xml(streamlist, case, outfile, data_list_path, os.path.join(caseroot,'user_nl_datm_streams'+inst_string), available_neon_data=available_neon_data) + +#################################################################################### +def _create_drv_flds_in(case, confdir): +#################################################################################### + datm_preso3 = case.get_value("DATM_PRESO3") + + # for now we are hard-coding this file name and values because we only need it for ozone + if datm_preso3 != "none": + + # Generate drv_flds_in file + outfile = os.path.join(confdir, "drv_flds_in") + ozone_nl_name = "&ozone_coupling_nl" + ozone_freq_par = "atm_ozone_frequency" + ozone_freq_val = "'multiday_average'" + nl_fin = "/" + + with open(outfile, "w") as drv_fl: + drv_fl.write("{}\n".format(ozone_nl_name)) + drv_fl.write(" {} = {}\n".format(ozone_freq_par, ozone_freq_val)) + drv_fl.write("{}\n".format(nl_fin)) + + + ############################################################################### def buildnml(case, caseroot, compname): ############################################################################### @@ -267,6 +298,8 @@ def buildnml(case, caseroot, compname): # create namelist and stream file(s) data component _create_namelists(case, confdir, inst_string, namelist_infile, nmlgen, data_list_path) + _create_drv_flds_in(case, confdir) + # copy namelist files and stream text files, to rundir copy_inputs_to_rundir(caseroot, compname, confdir, rundir, inst_string) diff --git a/datm/cime_config/config_component.xml b/datm/cime_config/config_component.xml index eed8a082d..9ff459f51 100644 --- a/datm/cime_config/config_component.xml +++ b/datm/cime_config/config_component.xml @@ -92,7 +92,7 @@ char - none,clim_1850,clim_2000,clim_2010,hist,SSP1-2.6,SSP2-4.5,SSP3-7.0,SSP5-3.4,SSP5-8.5 + none,clim_1850,clim_2000,clim_2010,hist,SSP1-2.6,SSP2-4.5,SSP3-7.0,SSP5-3.4,SSP5-8.5,cplhist clim_2000 clim_1850 @@ -112,6 +112,28 @@ DATM prescribed nitrogen deposition forcing + + char + none,clim_1850,clim_2000,clim_2010,hist,SSP2-4.5,SSP3-7.0,SSP5-8.5 + clim_2000 + + clim_1850 + clim_2000 + clim_2010 + SSP2-4.5 + SSP3-7.0 + SSP5-8.5 + hist + hist + + none + none + + run_component_datm + env_run.xml + DATM prescribed ozone forcing + + char none,observed,cplhist diff --git a/datm/cime_config/namelist_definition_datm.xml b/datm/cime_config/namelist_definition_datm.xml index 3ea0bef64..c677bffe0 100644 --- a/datm/cime_config/namelist_definition_datm.xml +++ b/datm/cime_config/namelist_definition_datm.xml @@ -279,6 +279,19 @@ + + logical + datm + datm_nml + + If true, prescribed o3 is sent from datm (must be true for running with CLM). + + + .true. + .false. + + + logical datm diff --git a/datm/cime_config/stream_definition_datm.xml b/datm/cime_config/stream_definition_datm.xml index d4228d246..c29decdca 100644 --- a/datm/cime_config/stream_definition_datm.xml +++ b/datm/cime_config/stream_definition_datm.xml @@ -187,6 +187,17 @@ presndep.SSP5-8.5 presndep.cplhist + ======================== + optional stream ozone (stream specified by xml variable DATM_PRESO3) + ======================== + preso3.clim_1850 + preso3.clim_2000 + preso3.hist + preso3.SSP2-4.5 + preso3.SSP3-7.0 + preso3.SSP5-8.5 + + ======================== optional stream topo (turned on and stream specified by xml variable DATM_TOPO) ======================== @@ -3999,6 +4010,273 @@ single + + + $DIN_LOC_ROOT/share/meshes/fv0.9x1.25_141008_polemod_ESMFmesh.nc + + + $DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/aero/aerodep_clm_SSP585_b.e21.BSSP585cmip6.f09_g17.CMIP6-SSP5-8.5.001_2014-2101_monthly_0.9x1.25_c190419.nc + + + BCDEPWET Faxa_bcphiwet + BCPHODRY Faxa_bcphodry + BCPHIDRY Faxa_bcphidry + OCDEPWET Faxa_ocphiwet + OCPHIDRY Faxa_ocphidry + OCPHODRY Faxa_ocphodry + DSTX01WD Faxa_dstwet1 + DSTX01DD Faxa_dstdry1 + DSTX02WD Faxa_dstwet2 + DSTX02DD Faxa_dstdry2 + DSTX03WD Faxa_dstwet3 + DSTX03DD Faxa_dstdry3 + DSTX04WD Faxa_dstwet4 + DSTX04DD Faxa_dstdry4 + + null + + bilinear + + null + 2015 + 2015 + 2101 + 0 + + linear + + + cycle + + + 1.5 + + single + + + + + + + + + $DIN_LOC_ROOT/share/meshes/fv0.9x1.25_141008_polemod_ESMFmesh.nc + + + $DIN_LOC_ROOT/cdeps/datm/ozone/O3_surface.f09_g17.CMIP6-historical-WACCM.001.monthly.185001-201412.nc + + + O3 Sa_o3 + + null + + bilinear + + null + 1 + 1850 + 1850 + 0 + + linear + + + cycle + + + 1.5 + + single + + + + + $DIN_LOC_ROOT/share/meshes/fv0.9x1.25_141008_polemod_ESMFmesh.nc + + + $DIN_LOC_ROOT/cdeps/datm/ozone/O3_surface.f09_g17.CMIP6-historical-WACCM.001.monthly.185001-201412.nc + + + O3 Sa_o3 + + null + + bilinear + + null + 1 + 2000 + 2000 + 0 + + linear + + + cycle + + + 1.5 + + single + + + + + $DIN_LOC_ROOT/share/meshes/fv0.9x1.25_141008_polemod_ESMFmesh.nc + + + $DIN_LOC_ROOT/cdeps/datm/ozone/O3_surface.f09_g17.CMIP6-historical-WACCM.001.monthly.185001-201412.nc + + + O3 Sa_o3 + + null + + bilinear + + null + 1 + 2010 + 2010 + 0 + + linear + + + cycle + + + 1.5 + + single + + + + + $DIN_LOC_ROOT/share/meshes/fv0.9x1.25_141008_polemod_ESMFmesh.nc + + + $DIN_LOC_ROOT/cdeps/datm/ozone/O3_surface.f09_g17.CMIP6-historical-WACCM.001.monthly.185001-201412.nc + + + O3 Sa_o3 + + null + + bilinear + + null + 1850 + 1850 + 2014 + 0 + + linear + + + cycle + + + 1.5 + + single + + + + + $DIN_LOC_ROOT/share/meshes/fv0.9x1.25_141008_polemod_ESMFmesh.nc + + + $DIN_LOC_ROOT/cdeps/datm/ozone/O3_surface.f09_g17.CMIP6-SSP2-4.5-WACCM.001.monthly.201501-210012.nc + + + O3 Sa_o3 + + null + + bilinear + + null + 2015 + 2015 + 2100 + 0 + + linear + + + cycle + + + 1.5 + + single + + + + + $DIN_LOC_ROOT/share/meshes/fv0.9x1.25_141008_polemod_ESMFmesh.nc + + + $DIN_LOC_ROOT/cdeps/datm/ozone/O3_surface.f09_g17.CMIP6-SSP3-7.0-WACCM.001.monthly.201501-210012.nc + + + O3 Sa_o3 + + null + + bilinear + + null + 2015 + 2015 + 2100 + 0 + + linear + + + cycle + + + 1.5 + + single + + + + + $DIN_LOC_ROOT/share/meshes/fv0.9x1.25_141008_polemod_ESMFmesh.nc + + + $DIN_LOC_ROOT/cdeps/datm/ozone/O3_surface.f09_g17.CMIP6-SSP5-8.5-WACCM.001.monthly.201501-210012.nc + + + O3 Sa_o3 + + null + + bilinear + + null + 2015 + 2015 + 2100 + 0 + + linear + + + cycle + + + 1.5 + + single + + + + @@ -4168,7 +4446,7 @@ $DIN_LOC_ROOT/share/meshes/fv0.9x1.25_141008_polemod_ESMFmesh.nc - $DIN_LOC_ROOT/lnd/clm2/ndepdata/lnd/clm2/fndepdata/fndep_clm_f09_g17.CMIP6-SSP2-4.5-WACCM_1849-2101_monthly_c191007.nc + $DIN_LOC_ROOT/lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP2-4.5-WACCM_1849-2101_monthly_c191007.nc NDEP_NHx_month Faxa_ndep_nhx diff --git a/datm/datm_datamode_clmncep_mod.F90 b/datm/datm_datamode_clmncep_mod.F90 index 0c4619c01..6c376d902 100644 --- a/datm/datm_datamode_clmncep_mod.F90 +++ b/datm/datm_datamode_clmncep_mod.F90 @@ -36,6 +36,7 @@ module datm_datamode_clmncep_mod real(r8), pointer :: Sa_dens(:) => null() real(r8), pointer :: Sa_pbot(:) => null() real(r8), pointer :: Sa_pslv(:) => null() + real(r8), pointer :: Sa_o3(:) => null() real(r8), pointer :: Faxa_lwdn(:) => null() real(r8), pointer :: Faxa_rainc(:) => null() real(r8), pointer :: Faxa_rainl(:) => null() @@ -113,7 +114,7 @@ module datm_datamode_clmncep_mod !=============================================================================== subroutine datm_datamode_clmncep_advertise(exportState, fldsexport, flds_scalar_name, & - flds_co2, flds_wiso, flds_presaero, flds_presndep, rc) + flds_co2, flds_wiso, flds_presaero, flds_presndep, flds_preso3, rc) ! input/output variables type(esmf_State) , intent(inout) :: exportState @@ -122,6 +123,7 @@ subroutine datm_datamode_clmncep_advertise(exportState, fldsexport, flds_scalar_ logical , intent(in) :: flds_wiso logical , intent(in) :: flds_presaero logical , intent(in) :: flds_presndep + logical , intent(in) :: flds_preso3 character(len=*) , intent(in) :: flds_scalar_name integer , intent(out) :: rc @@ -157,6 +159,9 @@ subroutine datm_datamode_clmncep_advertise(exportState, fldsexport, flds_scalar_ call dshr_fldList_add(fldsExport, 'Sa_co2prog') call dshr_fldList_add(fldsExport, 'Sa_co2diag') end if + if (flds_preso3) then + call dshr_fldList_add(fldsExport, 'Sa_o3') + end if if (flds_presaero) then call dshr_fldList_add(fldsExport, 'Faxa_bcph' , ungridded_lbound=1, ungridded_ubound=3) call dshr_fldList_add(fldsExport, 'Faxa_ocph' , ungridded_lbound=1, ungridded_ubound=3) @@ -309,6 +314,13 @@ subroutine datm_datamode_clmncep_init_pointers(importState, exportState, sdat, r if (ChkErr(rc,__LINE__,u_FILE_u)) return end if + call ESMF_StateGet(exportstate, 'Sa_o3', itemFlag, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (itemflag /= ESMF_STATEITEM_NOTFOUND) then + call dshr_state_getfldptr(exportState, 'Sa_o3', fldptr1=Sa_o3, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end if + ! error check if (.not. associated(strm_wind) .or. .not. associated(strm_tbot)) then call shr_sys_abort(trim(subname)//' ERROR: wind and tbot must be in streams for CLMNCEP') diff --git a/streams/dshr_stream_mod.F90 b/streams/dshr_stream_mod.F90 index 3075845ee..301718133 100644 --- a/streams/dshr_stream_mod.F90 +++ b/streams/dshr_stream_mod.F90 @@ -1718,9 +1718,11 @@ subroutine shr_stream_restIO(pioid, streams, mode) rcode = pio_def_dim(pioid, 'strlen', CL, dimid_str) do k=1,size(streams) + ! maxnfiles is the maximum number of files across all streams if (streams(k)%nfiles > maxnfiles) then maxnfiles = streams(k)%nfiles endif + ! maxnt is the maximum number of time samples across all possible stream files do n=1,streams(k)%nFiles if( streams(k)%file(n)%nt > maxnt) then maxnt = streams(k)%file(n)%nt