From c4a255e920ea9c5b932b2a5d9e2a376d4563344f Mon Sep 17 00:00:00 2001 From: Steve Goldhaber Date: Tue, 25 Feb 2025 16:06:23 +0100 Subject: [PATCH] Final updates from cam6_4_070 --- src/chemistry/mozart/mo_chm_diags.F90 | 5 ++ src/control/camsrfexch.F90 | 24 +++--- src/cpl/nuopc/atm_import_export.F90 | 104 +++++++++++--------------- 3 files changed, 63 insertions(+), 70 deletions(-) diff --git a/src/chemistry/mozart/mo_chm_diags.F90 b/src/chemistry/mozart/mo_chm_diags.F90 index 33e0a7e176..6eabc73f4c 100644 --- a/src/chemistry/mozart/mo_chm_diags.F90 +++ b/src/chemistry/mozart/mo_chm_diags.F90 @@ -18,6 +18,7 @@ module mo_chm_diags public :: chm_diags_inti public :: chm_diags public :: het_diags + public :: chm_prod_ndep_flx integer :: id_n,id_no,id_no2,id_no3,id_n2o5,id_hno3,id_ho2no2,id_clono2,id_brono2 integer :: id_isopfdn, id_isopfdnc, id_terpfdn !these are dinitrates @@ -55,6 +56,8 @@ module mo_chm_diags real(r8), parameter :: N_molwgt = 14.00674_r8 real(r8), parameter :: S_molwgt = 32.066_r8 + logical, protected :: chm_prod_ndep_flx =.false. + contains subroutine chm_diags_inti @@ -330,6 +333,8 @@ subroutine chm_diags_inti toth_species = (/ id_ch4, id_h2o, id_h2 /) + chm_prod_ndep_flx = any(noy_species>0) .or. any(nhx_species>0) + call addfld( 'NOX', (/ 'lev' /), 'A', 'mol/mol', 'nox (N+NO+NO2)' ) call addfld( 'NOY', (/ 'lev' /), 'A', 'mol/mol', & 'noy = total nitrogen (N+NO+NO2+NO3+2N2O5+HNO3+HO2NO2+ORGNOY+NH4NO3)' ) diff --git a/src/control/camsrfexch.F90 b/src/control/camsrfexch.F90 index 44812d67ff..e14f9362b2 100644 --- a/src/control/camsrfexch.F90 +++ b/src/control/camsrfexch.F90 @@ -13,9 +13,7 @@ module camsrfexch use cam_abortutils, only: endrun use cam_logfile, only: iulog use srf_field_check, only: active_Sl_ram1, active_Sl_fv, active_Sl_soilw, & - active_Fall_flxdst1, active_Fall_flxvoc, active_Fall_flxfire, & - active_Faxa_nhx, active_Faxa_noy - + active_Fall_flxdst1, active_Fall_flxvoc, active_Fall_flxfire implicit none @@ -333,14 +331,20 @@ subroutine atm2hub_alloc( cam_out ) cam_out(c)%dstwet4(:) = 0._r8 nullify(cam_out(c)%nhx_nitrogen_flx) - allocate (cam_out(c)%nhx_nitrogen_flx(pcols), stat=ierror) - if ( ierror /= 0 ) call endrun(sub//': allocation error nhx_nitrogen_flx') - cam_out(c)%nhx_nitrogen_flx(:) = 0._r8 - nullify(cam_out(c)%noy_nitrogen_flx) - allocate (cam_out(c)%noy_nitrogen_flx(pcols), stat=ierror) - if ( ierror /= 0 ) call endrun(sub//': allocation error noy_nitrogen_flx') - cam_out(c)%noy_nitrogen_flx(:) = 0._r8 + + if (.not. (simple_phys .or. aqua_planet)) then + + allocate (cam_out(c)%nhx_nitrogen_flx(pcols), stat=ierror) + if ( ierror /= 0 ) call endrun(sub//': allocation error nhx_nitrogen_flx') + cam_out(c)%nhx_nitrogen_flx(:) = 0._r8 + + allocate (cam_out(c)%noy_nitrogen_flx(pcols), stat=ierror) + if ( ierror /= 0 ) call endrun(sub//': allocation error noy_nitrogen_flx') + cam_out(c)%noy_nitrogen_flx(:) = 0._r8 + + endif + end do end subroutine atm2hub_alloc diff --git a/src/cpl/nuopc/atm_import_export.F90 b/src/cpl/nuopc/atm_import_export.F90 index eea2b5b3b2..c8ea012c6b 100644 --- a/src/cpl/nuopc/atm_import_export.F90 +++ b/src/cpl/nuopc/atm_import_export.F90 @@ -23,10 +23,10 @@ module atm_import_export use srf_field_check , only : set_active_Fall_flxfire use srf_field_check , only : set_active_Fall_fco2_lnd use srf_field_check , only : set_active_Faoo_fco2_ocn - use srf_field_check , only : set_active_Faxa_nhx - use srf_field_check , only : set_active_Faxa_noy - use srf_field_check , only : active_Faxa_nhx, active_Faxa_noy - use atm_stream_ndep , only : stream_ndep_init, stream_ndep_interp, stream_ndep_is_initialized, use_ndep_stream + use atm_stream_ndep , only : stream_ndep_init, stream_ndep_interp, stream_ndep_is_initialized + use atm_stream_ndep , only : ndep_stream_active + use chemistry , only : chem_has_ndep_flx + use cam_control_mod , only : aqua_planet, simple_phys implicit none private ! except @@ -61,7 +61,6 @@ module atm_import_export integer :: drydep_nflds = -huge(1) ! number of dry deposition velocity fields lnd-> atm integer :: megan_nflds = -huge(1) ! number of MEGAN voc fields from lnd-> atm integer :: emis_nflds = -huge(1) ! number of fire emission fields from lnd-> atm - integer, public :: ndep_nflds = -huge(1) ! number of nitrogen deposition fields from atm->lnd/ocn logical :: atm_provides_lightning = .false. ! cld to grnd lightning flash freq (min-1) logical, public :: dms_from_ocn = .false. ! dms is obtained from ocean as atm import data logical, public :: brf_from_ocn = .false. ! brf is obtained from ocean as atm import data @@ -84,13 +83,11 @@ subroutine read_surface_fields_namelists() use shr_megan_mod , only : shr_megan_readnl use shr_fire_emis_mod , only : shr_fire_emis_readnl use shr_carma_mod , only : shr_carma_readnl - use shr_ndep_mod , only : shr_ndep_readnl use shr_lightning_coupling_mod, only : shr_lightning_coupling_readnl character(len=*), parameter :: nl_file_name = 'drv_flds_in' ! read mediator fields options - call shr_ndep_readnl(nl_file_name, ndep_nflds) call shr_drydep_readnl(nl_file_name, drydep_nflds) call shr_megan_readnl(nl_file_name, megan_nflds) call shr_fire_emis_readnl(nl_file_name, emis_nflds) @@ -121,7 +118,7 @@ subroutine advertise_fields(gcomp, flds_scalar_name, rc) character(len=128) :: fldname logical :: ispresent logical :: isset - character(len=*), parameter :: subname='(atm_import_export:advertise_fields)' + character(len=*), parameter :: subname='(atm_import_export:advertise_fields): ' !------------------------------------------------------------------------------- rc = ESMF_SUCCESS @@ -136,17 +133,23 @@ subroutine advertise_fields(gcomp, flds_scalar_name, rc) call NUOPC_CompAttributeGet(gcomp, name='flds_co2a', value=cvalue, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return read(cvalue,*) flds_co2a - if (masterproc) write(iulog,'(a)') trim(subname)//'flds_co2a = '// trim(cvalue) + if (masterproc) then + write(iulog,'(3a)') trim(subname), 'flds_co2a = ', trim(cvalue) + end if call NUOPC_CompAttributeGet(gcomp, name='flds_co2b', value=cvalue, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return read(cvalue,*) flds_co2b - if (masterproc) write(iulog,'(a)') trim(subname)//'flds_co2b = '// trim(cvalue) + if (masterproc) then + write(iulog,'(3a)') trim(subname), 'flds_co2b = ', trim(cvalue) + end if call NUOPC_CompAttributeGet(gcomp, name='flds_co2c', value=cvalue, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return read(cvalue,*) flds_co2c - if (masterproc) write(iulog,'(a)') trim(subname)//'flds_co2c = '// trim(cvalue) + if (masterproc) then + write(iulog,'(3a)') trim(subname), 'flds_co2c = ', trim(cvalue) + end if call NUOPC_CompAttributeGet(gcomp, name='flds_dms', value=cvalue, ispresent=ispresent, isset=isset, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return @@ -155,8 +158,9 @@ subroutine advertise_fields(gcomp, flds_scalar_name, rc) else dms_from_ocn = .false. end if - if (masterproc) write(iulog,'(a,l)') trim(subname)//'dms_from_ocn = ',dms_from_ocn - write(6,'(a,l)')trim(subname)//'dms_from_ocn = ',dms_from_ocn + if (masterproc) then + write(iulog,'(2a,l)') trim(subname), 'dms_from_ocn = ', dms_from_ocn + end if call NUOPC_CompAttributeGet(gcomp, name='flds_brf', value=cvalue, ispresent=ispresent, isset=isset, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return @@ -165,7 +169,9 @@ subroutine advertise_fields(gcomp, flds_scalar_name, rc) else brf_from_ocn = .false. end if - if (masterproc) write(iulog,'(a,l)') trim(subname)//'brf_from_ocn = ',brf_from_ocn + if (masterproc) then + write(iulog,'(2a,l)') trim(subname), 'brf_from_ocn = ', brf_from_ocn + end if call NUOPC_CompAttributeGet(gcomp, name='flds_n2o', value=cvalue, ispresent=ispresent, isset=isset, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return @@ -174,7 +180,9 @@ subroutine advertise_fields(gcomp, flds_scalar_name, rc) else n2o_from_ocn = .false. end if - if (masterproc) write(iulog,'(a,l)') trim(subname)//'n2o_from_ocn = ',n2o_from_ocn + if (masterproc) then + write(iulog,'(2a,l)') trim(subname), 'n2o_from_ocn = ', n2o_from_ocn + end if call NUOPC_CompAttributeGet(gcomp, name='flds_nh3', value=cvalue, ispresent=ispresent, isset=isset, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return @@ -183,7 +191,9 @@ subroutine advertise_fields(gcomp, flds_scalar_name, rc) else nh3_from_ocn = .false. end if - if (masterproc) write(iulog,'(a,l)') trim(subname)//'nh3_from_ocn = ',nh3_from_ocn + if (masterproc) then + write(iulog,'(2a,l)') trim(subname), 'nh3_from_ocn = ', nh3_from_ocn + end if !-------------------------------- ! Export fields @@ -240,16 +250,7 @@ subroutine advertise_fields(gcomp, flds_scalar_name, rc) call fldlist_add(fldsFrAtm_num, fldsFrAtm, 'Sa_co2diag' ) end if - if (ndep_nflds > 0) then - ! The following is when CAM/WACCM computes ndep - call set_active_Faxa_nhx(.true.) - call set_active_Faxa_noy(.true.) - else - ! The following is used for reading in stream data, or for aquaplanet or simple model - ! cases where the ndep fluxes are not used. - call set_active_Faxa_nhx(.false.) - call set_active_Faxa_noy(.false.) - end if + ! Nitrogen deposition fluxes ! Assume that 2 fields are always sent as part of Faxa_ndep call fldlist_add(fldsFrAtm_num, fldsFrAtm, 'Faxa_ndep', ungridded_lbound=1, ungridded_ubound=2) @@ -582,7 +583,6 @@ subroutine import_fields( gcomp, cam_in, restart_init, rc) real(r8), pointer :: fldptr_tauy(:) real(r8), pointer :: fldptr_sen(:) real(r8), pointer :: fldptr_evap(:) - integer :: pndx_fdms ! DMS surface flux physics index logical, save :: first_time = .true. character(len=*), parameter :: subname='(atm_import_export:import_fields)' !--------------------------------------------------------------------------- @@ -892,7 +892,7 @@ subroutine import_fields( gcomp, cam_in, restart_init, rc) call state_getfldptr(importState, 'Faoo_fdms_ocn', fldptr=fldptr1d, exists=exists, rc=rc) if (exists) then ! Ideally what should happen below is that - ! cam_in%cflx(icol,pndx_fdms) should be set directly from + ! cam_in%cflx(icol,) should be set directly from ! fldptr1d. However, the code initializes the chemistry ! consituents surface fluxes (i.e.cam_in%cflx(:,:)) to zero in ! the routine in mozart/chemistry.F90 at the start of every @@ -1043,7 +1043,6 @@ subroutine export_fields( gcomp, model_mesh, model_clock, cam_out, rc) integer :: i,m,c,n,g ! indices integer :: nstep logical :: exists - real(r8) :: scale_ndep real(r8) :: wind_dir ! 2d output pointers real(r8), pointer :: fldptr_ndep(:,:) @@ -1250,10 +1249,9 @@ subroutine export_fields( gcomp, model_mesh, model_clock, cam_out, rc) call state_getfldptr(exportState, 'Faxa_ndep', fldptr2d=fldptr_ndep, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - if (.not. active_Faxa_nhx .and. .not. active_Faxa_noy) then + fldptr_ndep(:,:) = 0._r8 - ! ndep fields not active (i.e., not computed by WACCM). Either they are not needed, - ! or they are obtained from the ndep input stream. + if (.not. (simple_phys .or. aqua_planet)) then ! The ndep_stream_nl namelist group is read in stream_ndep_init. This sets whether ! or not the stream will be used. @@ -1263,45 +1261,31 @@ subroutine export_fields( gcomp, model_mesh, model_clock, cam_out, rc) stream_ndep_is_initialized = .true. end if - if (use_ndep_stream) then + if (ndep_stream_active.or.chem_has_ndep_flx) then + + ! Nitrogen dep fluxes are obtained from the ndep input stream if input data is available + ! otherwise computed by chemistry + if (ndep_stream_active) then - ! get ndep fluxes from the stream - call stream_ndep_interp(cam_out, rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - ! NDEP read from forcing is expected to be in units of gN/m2/sec - but the mediator - ! expects units of kgN/m2/sec - scale_ndep = .001_r8 + ! get ndep fluxes from the stream + call stream_ndep_interp(cam_out, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return - else + end if - ! ndep fluxes not used. Set to zero. + g = 1 do c = begchunk,endchunk do i = 1,get_ncols_p(c) - cam_out(c)%nhx_nitrogen_flx(i) = 0._r8 - cam_out(c)%noy_nitrogen_flx(i) = 0._r8 + fldptr_ndep(1,g) = cam_out(c)%nhx_nitrogen_flx(i) * mod2med_areacor(g) + fldptr_ndep(2,g) = cam_out(c)%noy_nitrogen_flx(i) * mod2med_areacor(g) + g = g + 1 end do end do - scale_ndep = 1._r8 - end if - - else - - ! If waccm computes ndep, then its in units of kgN/m2/s - and the mediator expects - ! units of kgN/m2/sec, so the following conversion needs to happen - scale_ndep = 1._r8 + end if end if - g = 1 - do c = begchunk,endchunk - do i = 1,get_ncols_p(c) - fldptr_ndep(1,g) = cam_out(c)%nhx_nitrogen_flx(i) * scale_ndep * mod2med_areacor(g) - fldptr_ndep(2,g) = cam_out(c)%noy_nitrogen_flx(i) * scale_ndep * mod2med_areacor(g) - g = g + 1 - end do - end do - end subroutine export_fields !===============================================================================