diff --git a/bld/build-namelist b/bld/build-namelist index 83b1707672..8413f96f57 100755 --- a/bld/build-namelist +++ b/bld/build-namelist @@ -146,6 +146,7 @@ GetOptions( "uc|use_case=s" => \$opts{'use_case'}, "v|verbose" => \$opts{'verbose'}, "version" => \$opts{'version'}, + "cmeps" => \$opts{'cmeps'}, ) or usage(); # Give usage message. @@ -3843,8 +3844,15 @@ foreach my $name (@nl_groups) { $nl_group{$name} = ''; } # Dry deposition, MEGAN VOC emis and ozone namelists @comp_groups = qw(drydep_inparm megan_emis_nl fire_emis_nl carma_inparm ndep_inparm ozone_coupling_nl); -# FIXME The following add_default call needs to be moved and the right logic needs to be put in place -add_default($nl, 'atm_ozone_frequency', 'val'=>'monthly_interpolated'); + +# nature of ozone data passed to surface models -- only if cmeps (nuopc) coupling is used +if ($opts{'cmeps'}) { + if ($rad_prog_ozone) { + add_default($nl, 'atm_ozone_frequency', 'val'=>'instantaneous'); + } else { + add_default($nl, 'atm_ozone_frequency', 'val'=>'monthly_interpolated'); + } +} $outfile = "$opts{'dir'}/drv_flds_in"; $nl->write($outfile, 'groups'=>\@comp_groups); if ($print>=1) { diff --git a/cime_config/buildnml b/cime_config/buildnml index efd022d9f9..9393269f84 100755 --- a/cime_config/buildnml +++ b/cime_config/buildnml @@ -45,6 +45,7 @@ def buildnml(case, caseroot, compname): RUN_REFCASE = case.get_value("RUN_REFCASE") RUN_REFDATE = case.get_value("RUN_REFDATE") RUN_REFTOD = case.get_value("RUN_REFTOD") + COMP_INTERFACE = case.get_value("COMP_INTERFACE") testsrc = os.path.join(srcroot, "components", "cam") if os.path.exists(testsrc): @@ -168,6 +169,9 @@ def buildnml(case, caseroot, compname): buildnl_opts += ["-namelist", '" &atmexp ' + CAM_NAMELIST_OPTS + '/" '] + if COMP_INTERFACE == 'nuopc': + buildnl_opts.append("-cmeps") + cmd = os.path.join(srcroot, "bld", "build-namelist") cmd += " " + " ".join(buildnl_opts) diff --git a/src/control/camsrfexch.F90 b/src/control/camsrfexch.F90 index c92f602a0f..957d2a5ac6 100644 --- a/src/control/camsrfexch.F90 +++ b/src/control/camsrfexch.F90 @@ -36,7 +36,7 @@ module camsrfexch ! This is the data that is sent from the atmosphere to the surface models !--------------------------------------------------------------------------- - type cam_out_t + type cam_out_t integer :: lchnk ! chunk index integer :: ncol ! number of columns in chunk real(r8) :: tbot(pcols) ! bot level temperature @@ -46,20 +46,21 @@ module camsrfexch real(r8) :: vbot(pcols) ! bot level v wind real(r8) :: qbot(pcols,pcnst) ! bot level specific humidity real(r8) :: pbot(pcols) ! bot level pressure - real(r8) :: rho(pcols) ! bot level density - real(r8) :: netsw(pcols) ! - real(r8) :: flwds(pcols) ! + real(r8) :: rho(pcols) ! bot level density + real(r8) :: netsw(pcols) ! + real(r8) :: flwds(pcols) ! real(r8) :: precsc(pcols) ! real(r8) :: precsl(pcols) ! - real(r8) :: precc(pcols) ! - real(r8) :: precl(pcols) ! - real(r8) :: soll(pcols) ! - real(r8) :: sols(pcols) ! + real(r8) :: precc(pcols) ! + real(r8) :: precl(pcols) ! + real(r8) :: soll(pcols) ! + real(r8) :: sols(pcols) ! real(r8) :: solld(pcols) ! real(r8) :: solsd(pcols) ! - real(r8) :: thbot(pcols) ! + real(r8) :: thbot(pcols) ! real(r8) :: co2prog(pcols) ! prognostic co2 real(r8) :: co2diag(pcols) ! diagnostic co2 + real(r8) :: ozone(pcols) ! surface ozone concentration (ppbv) real(r8) :: psl(pcols) real(r8) :: bcphiwet(pcols) ! wet deposition of hydrophilic black carbon real(r8) :: bcphidry(pcols) ! dry deposition of hydrophilic black carbon @@ -77,13 +78,13 @@ module camsrfexch real(r8) :: dstdry4(pcols) ! dry deposition of dust (bin4) real(r8), pointer, dimension(:) :: nhx_nitrogen_flx ! nitrogen deposition fluxes (kgN/m2/s) real(r8), pointer, dimension(:) :: noy_nitrogen_flx ! nitrogen deposition fluxes (kgN/m2/s) - end type cam_out_t + end type cam_out_t !--------------------------------------------------------------------------- ! This is the merged state of sea-ice, land and ocean surface parameterizations !--------------------------------------------------------------------------- - type cam_in_t + type cam_in_t integer :: lchnk ! chunk index integer :: ncol ! number of active columns real(r8) :: asdir(pcols) ! albedo: shortwave, direct @@ -96,11 +97,11 @@ module camsrfexch real(r8) :: wsx(pcols) ! surface u-stress (N) real(r8) :: wsy(pcols) ! surface v-stress (N) real(r8) :: tref(pcols) ! ref height surface air temp - real(r8) :: qref(pcols) ! ref height specific humidity + real(r8) :: qref(pcols) ! ref height specific humidity real(r8) :: u10(pcols) ! 10m wind speed - real(r8) :: ts(pcols) ! merged surface temp + real(r8) :: ts(pcols) ! merged surface temp real(r8) :: sst(pcols) ! sea surface temp - real(r8) :: snowhland(pcols) ! snow depth (liquid water equivalent) over land + real(r8) :: snowhland(pcols) ! snow depth (liquid water equivalent) over land real(r8) :: snowhice(pcols) ! snow depth over ice real(r8) :: fco2_lnd(pcols) ! co2 flux from lnd real(r8) :: fco2_ocn(pcols) ! co2 flux from ocn @@ -120,7 +121,7 @@ module camsrfexch real(r8), pointer, dimension(:,:) :: meganflx ! MEGAN fluxes real(r8), pointer, dimension(:,:) :: fireflx ! wild fire emissions real(r8), pointer, dimension(:) :: fireztop ! wild fire emissions vert distribution top - end type cam_in_t + end type cam_in_t !=============================================================================== CONTAINS @@ -142,7 +143,7 @@ subroutine hub2atm_alloc( cam_in ) integer :: c ! chunk index integer :: ierror ! Error code character(len=*), parameter :: sub = 'hub2atm_alloc' - !----------------------------------------------------------------------- + !----------------------------------------------------------------------- if ( .not. phys_grid_initialized() ) call endrun(sub//": phys_grid not called yet") allocate (cam_in(begchunk:endchunk), stat=ierror) @@ -160,8 +161,8 @@ subroutine hub2atm_alloc( cam_in ) nullify(cam_in(c)%meganflx) nullify(cam_in(c)%fireflx) nullify(cam_in(c)%fireztop) - enddo - do c = begchunk,endchunk + enddo + do c = begchunk,endchunk if (active_Sl_ram1) then allocate (cam_in(c)%ram1(pcols), stat=ierror) if ( ierror /= 0 ) call endrun(sub//': allocation error ram1') @@ -186,14 +187,14 @@ subroutine hub2atm_alloc( cam_in ) end do if (lnd_drydep .and. n_drydep>0) then - do c = begchunk,endchunk + do c = begchunk,endchunk allocate (cam_in(c)%depvel(pcols,n_drydep), stat=ierror) if ( ierror /= 0 ) call endrun(sub//': allocation error depvel') end do endif if (active_Fall_flxfire .and. shr_fire_emis_mechcomps_n>0) then - do c = begchunk,endchunk + do c = begchunk,endchunk allocate(cam_in(c)%fireflx(pcols,shr_fire_emis_mechcomps_n), stat=ierror) if ( ierror /= 0 ) call endrun(sub//': allocation error fireflx') allocate(cam_in(c)%fireztop(pcols), stat=ierror) @@ -267,7 +268,7 @@ subroutine atm2hub_alloc( cam_out ) integer :: c ! chunk index integer :: ierror ! Error code character(len=*), parameter :: sub = 'atm2hub_alloc' - !----------------------------------------------------------------------- + !----------------------------------------------------------------------- if (.not. phys_grid_initialized()) call endrun(sub//": phys_grid not called yet") allocate (cam_out(begchunk:endchunk), stat=ierror) @@ -300,6 +301,7 @@ subroutine atm2hub_alloc( cam_out ) cam_out(c)%thbot(:) = 0._r8 cam_out(c)%co2prog(:) = 0._r8 cam_out(c)%co2diag(:) = 0._r8 + cam_out(c)%ozone(:) = 0._r8 cam_out(c)%psl(:) = 0._r8 cam_out(c)%bcphidry(:) = 0._r8 cam_out(c)%bcphodry(:) = 0._r8 @@ -338,7 +340,7 @@ end subroutine atm2hub_alloc subroutine atm2hub_deallocate(cam_out) type(cam_out_t), pointer :: cam_out(:) ! Atmosphere to surface input - !----------------------------------------------------------------------- + !----------------------------------------------------------------------- if(associated(cam_out)) then deallocate(cam_out) @@ -354,7 +356,7 @@ subroutine hub2atm_deallocate(cam_in) type(cam_in_t), pointer :: cam_in(:) ! Atmosphere to surface input integer :: c - !----------------------------------------------------------------------- + !----------------------------------------------------------------------- if(associated(cam_in)) then do c=begchunk,endchunk @@ -382,7 +384,7 @@ subroutine hub2atm_deallocate(cam_in) deallocate(cam_in(c)%depvel) nullify(cam_in(c)%depvel) end if - + enddo deallocate(cam_in) @@ -403,14 +405,15 @@ subroutine cam_export(state,cam_out,pbuf) use cam_history, only: outfld use chem_surfvals, only: chem_surfvals_get use co2_cycle, only: co2_transport, c_i - use physconst, only: rair, mwdry, mwco2, gravit + use physconst, only: rair, mwdry, mwco2, gravit, mwo3 use constituents, only: pcnst use physics_buffer, only: pbuf_get_index, pbuf_get_field, physics_buffer_desc + use rad_constituents, only: rad_cnst_get_gas implicit none ! Input arguments - type(physics_state), intent(in) :: state + type(physics_state), intent(in) :: state type (cam_out_t), intent(inout) :: cam_out type(physics_buffer_desc), pointer :: pbuf(:) @@ -434,6 +437,7 @@ subroutine cam_export(state,cam_out,pbuf) real(r8), pointer :: snow_sed(:) ! snow from ZM convection real(r8), pointer :: prec_pcw(:) ! total precipitation from Hack convection real(r8), pointer :: snow_pcw(:) ! snow from Hack convection + real(r8), pointer :: o3_ptr(:,:) !----------------------------------------------------------------------- lchnk = state%lchnk @@ -489,16 +493,21 @@ subroutine cam_export(state,cam_out,pbuf) end do do m = 1, pcnst do i = 1, ncol - cam_out%qbot(i,m) = state%q(i,pver,m) + cam_out%qbot(i,m) = state%q(i,pver,m) end do end do - cam_out%co2diag(:ncol) = chem_surfvals_get('CO2VMR') * 1.0e+6_r8 + cam_out%co2diag(:ncol) = chem_surfvals_get('CO2VMR') * 1.0e+6_r8 if (co2_transport()) then do i=1,ncol cam_out%co2prog(i) = state%q(i,pver,c_i(4)) * 1.0e+6_r8 *mwdry/mwco2 end do end if + + ! get bottom layer ozone concentrations to export to surface models + call rad_cnst_get_gas(0, 'O3', state, pbuf, o3_ptr) + cam_out%ozone(:ncol) = o3_ptr(:ncol,pver) * 1.0e+9_r8 * mwdry/mwo3 ! ppbv + ! ! Precipation and snow rates from shallow convection, deep convection and stratiform processes. ! Compute total convective and stratiform precipitation and snow rates diff --git a/src/cpl/nuopc/atm_import_export.F90 b/src/cpl/nuopc/atm_import_export.F90 index c64028d0c8..073433ea20 100644 --- a/src/cpl/nuopc/atm_import_export.F90 +++ b/src/cpl/nuopc/atm_import_export.F90 @@ -135,6 +135,7 @@ subroutine advertise_fields(gcomp, flds_scalar_name, rc) call fldlist_add(fldsFrAtm_num, fldsFrAtm, 'Sa_pbot' ) call fldlist_add(fldsFrAtm_num, fldsFrAtm, 'Sa_dens' ) call fldlist_add(fldsFrAtm_num, fldsFrAtm, 'Sa_pslv' ) + call fldlist_add(fldsFrAtm_num, fldsFrAtm, 'Sa_o3' ) call fldlist_add(fldsFrAtm_num, fldsFrAtm, 'Faxa_rainc' ) call fldlist_add(fldsFrAtm_num, fldsFrAtm, 'Faxa_rainl' ) call fldlist_add(fldsFrAtm_num, fldsFrAtm, 'Faxa_snowc' ) @@ -869,6 +870,7 @@ subroutine export_fields( gcomp, cam_out, rc) real(r8), pointer :: fldptr_shum(:) , fldptr_dens(:) real(r8), pointer :: fldptr_ptem(:) , fldptr_pslv(:) real(r8), pointer :: fldptr_co2prog(:) , fldptr_co2diag(:) + real(r8), pointer :: fldptr_ozone(:) character(len=*), parameter :: subname='(atm_import_export:export_fields)' !--------------------------------------------------------------------------- @@ -986,6 +988,18 @@ subroutine export_fields( gcomp, cam_out, rc) end do end do + call state_getfldptr(exportState, 'Sa_o3', fldptr=fldptr_ozone, exists=exists, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (exists) then + g = 1 + do c = begchunk,endchunk + do i = 1,get_ncols_p(c) + fldptr_ozone(g) = cam_out(c)%ozone(i) ! atm ozone + g = g + 1 + end do + end do + end if + call state_getfldptr(exportState, 'Sa_co2prog', fldptr=fldptr_co2prog, exists=exists, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return if (exists) then