From 5bb1dc98cea1a653b0d5e7da2d8b58b68216022b Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Fri, 10 Jul 2026 11:13:50 +0200 Subject: [PATCH 1/9] added new co2 surface source to overwrite co2_diag --- bld/build-namelist | 13 ++ bld/namelist_files/namelist_definition.xml | 52 +++++ src/cpl/nuopc/atm_import_export.F90 | 14 +- src/cpl/nuopc/atm_stream_co2.F90 | 227 +++++++++++++++++++++ 4 files changed, 305 insertions(+), 1 deletion(-) create mode 100644 src/cpl/nuopc/atm_stream_co2.F90 diff --git a/bld/build-namelist b/bld/build-namelist index 17781990b1..eb3086c392 100755 --- a/bld/build-namelist +++ b/bld/build-namelist @@ -710,6 +710,19 @@ if (!($simple_phys or $aqua_mode)) { } } +# Setup default co2 surface source stream only if not simple_phys or aqua_mode and +# the chemistry cannot produce the nitrogen depostion fluxes +if (!($simple_phys or $aqua_mode)) { + add_default($nl, 'co2_surface_source') + add_default($nl, 'stream_co2_surface_source_mesh_filename' , 'sim_year'=>$sim_year); + add_default($nl, 'stream_co2_surface_source_data_filename' , 'sim_year'=>$sim_year); + add_default($nl, 'stream_co2_surface_source_year_first' , 'sim_year'=>$sim_year); + add_default($nl, 'stream_co2_surface_source_year_last' , 'sim_year'=>$sim_year); + add_default($nl, 'stream_co2_surface_source_year_align' , 'sim_year'=>$sim_year); + add_default($nl, 'stream_co2_surface_source_varname'); + } +} + # Topography add_default($nl, 'use_topo_file'); my $use_topo_file = $nl->get_value('use_topo_file'); diff --git a/bld/namelist_files/namelist_definition.xml b/bld/namelist_files/namelist_definition.xml index 6924c798e3..eb4aff9184 100644 --- a/bld/namelist_files/namelist_definition.xml +++ b/bld/namelist_files/namelist_definition.xml @@ -10288,4 +10288,56 @@ Path to ocean file Default: path + + + + If TRUE, set co2_diag sent to land and ocean to value read from co2_surface_source_data_filename + Default: FALSE + + + + First year to use in co2 stream data. + Default: 2000 + + + + Last year last to use in co2 stream data. + Default: 2000 + + + +The simulation year corresponding to stream_co2_surface_source_year_first. +A common usage is to set this to the first year of the model run +(corresponding to the xml variable RUN_STARTDATE). With this setting, +the forcing in the first year of the run will be the forcing of year +yearFirst. +Another usage is to align the calendar of transient forcing with the +model calendar. For example, setting yearAlign = yearFirst will lead +to the forcing calendar being the same as the model calendar. The +forcing for a given model year would be the forcing of the same +year. This would be appropriate in transient runs where the model +calendar is setup to span the same year range as the forcing data. +Set by build-namelist. +Default: 1 + + + +co2 stream data filename. + + + +Grid mesh file corresponding to sream_co2_surface_source_data_filename. + + + +Variable names on co2 stream file(s). + + diff --git a/src/cpl/nuopc/atm_import_export.F90 b/src/cpl/nuopc/atm_import_export.F90 index 48b253ba6f..426d4b27b7 100644 --- a/src/cpl/nuopc/atm_import_export.F90 +++ b/src/cpl/nuopc/atm_import_export.F90 @@ -1,6 +1,6 @@ module atm_import_export - use NUOPC , only : NUOPC_CompAttributeGet, NUOPC_Advertise, NUOPC_IsConnected + use NUOPC , only : NUOPC_CompAttributeGet, NUOPC_Advertise, NUOPC_IsConnected use NUOPC_Model , only : NUOPC_ModelGet use ESMF , only : ESMF_GridComp, ESMF_State, ESMF_Mesh, ESMF_StateGet, ESMF_Field use ESMF , only : ESMF_Clock @@ -28,6 +28,8 @@ module atm_import_export use chemistry , only : chem_has_ndep_flx use cam_control_mod , only : aqua_planet, simple_phys use cam_esmf_mod , only : cam_esmf_set_areas + use atm_stream_co2_surface_source, only : stream_co2_surface_source_init, stream_co2_surface_source_interp + use atm_stream_co2_surface_source, only : stream_co2_surface_source_is_initialized implicit none private ! except @@ -1227,6 +1229,16 @@ subroutine export_fields(gcomp, cam_out, rc) call state_getfldptr(exportState, 'Sa_co2diag', fldptr=fldptr_co2diag, exists=exists, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return if (exists) then + ! if co2_surface_source is a filename - use this to overwrite co2_diag + if (trim(co2_surface_source) /= 'unset') then + if (.not. stream_co2_is_initialized) then + call stream_co2_surface_source_init(rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end if + call stream_co2_surface_source_interp(cam_out, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end if + g = 1 do c = begchunk,endchunk do i = 1,get_ncols_p(c) diff --git a/src/cpl/nuopc/atm_stream_co2.F90 b/src/cpl/nuopc/atm_stream_co2.F90 new file mode 100644 index 0000000000..e38319a6c1 --- /dev/null +++ b/src/cpl/nuopc/atm_stream_co2.F90 @@ -0,0 +1,227 @@ +module atm_stream_co2_surface_source + + !----------------------------------------------------------------------- + ! Contains methods for reading in co2_surface_source deposition data file + ! Also includes functions for dynamic co2_surface_source file handling and + ! interpolation. + !----------------------------------------------------------------------- + ! + use ESMF , only : ESMF_Clock, ESMF_Mesh + use ESMF , only : ESMF_SUCCESS, ESMF_LOGERR_PASSTHRU, ESMF_END_ABORT + use ESMF , only : ESMF_Finalize, ESMF_LogFoundError + use nuopc_shr_methods , only : chkerr + use dshr_strdata_mod , only : shr_strdata_type + use shr_kind_mod , only : r8 => shr_kind_r8, CL => shr_kind_cl, CS => shr_kind_cs + use shr_log_mod , only : errMsg => shr_log_errMsg + use spmd_utils , only : mpicom, masterproc, iam + use spmd_utils , only : mpi_character, mpi_integer + use cam_logfile , only : iulog + use cam_abortutils , only : endrun + use cam_esmf_mod , only : model_clock, model_mesh + + implicit none + private + + public :: stream_co2_surface_source_readnl ! read runtime options + public :: stream_co2_surface_source_init ! position datasets for dynamic co2_surface_source + public :: stream_co2_surface_source_interp ! interpolates between two years of co2_surface_source file data + + logical, public, protected :: stream_co2_surface_source_is_initialized = .false. + + type(shr_strdata_type) :: sdat_co2_surface_source ! input data stream + + ! namelist variables + character(len=CL) :: stream_co2_surface_source_data_filename + character(len=CL) :: stream_co2_surface_source_mesh_filename + character(len=CL) :: stream_co2_surface_source_varname ! variable name for co2_surface_source on stream file(s) + integer :: stream_co2_surface_source_year_first ! first year in stream to use + integer :: stream_co2_surface_source_year_last ! last year in stream to use + integer :: stream_co2_surface_source_year_align ! align stream_year_first + + character(len=*), parameter :: sourcefile = __FILE__ + +!============================================================================== +contains +!============================================================================== + + subroutine stream_co2_surface_source_readnl(nlfile) + + ! Uses: + use shr_nl_mod, only: shr_nl_find_group_name + + ! input/output variables + character(len=*), intent(in) :: nlfile + + ! local variables + integer :: nu_nml ! unit for namelist file + integer :: nml_error ! namelist i/o error flag + integer :: ierr ! error status + integer :: nf ! field counter + character(*), parameter :: subName = "('stream_co2_surface_source_readnl')" + !----------------------------------------------------------------------- + + namelist /co2_surface_source_stream_nl/ & + stream_co2_surface_source_data_filename, & + stream_co2_surface_source_mesh_filename, & + stream_co2_surface_source_year_first, & + stream_co2_surface_source_year_last, & + stream_co2_surface_source_year_align, & + stream_co2_surface_source_var + + ! Default values for namelist + stream_co2_surface_source_data_filename = ' ' + stream_co2_surface_source_mesh_filename = ' ' + stream_co2_surface_source_varlist = ' ' + stream_co2_surface_source_year_first = 1 ! first year in stream to use + stream_co2_surface_source_year_last = 1 ! last year in stream to use + stream_co2_surface_source_year_align = 1 ! align stream_co2_surface_source_year_first with this model year + + ! Read co2_surface_source_stream namelist + if (masterproc) then + open( newunit=nu_nml, file=trim(nlfile), status='old', iostat=nml_error ) + if (nml_error /= 0) then + call endrun(subName//': ERROR opening '//trim(nlfile)//errMsg(sourcefile, __LINE__)) + end if + call shr_nl_find_group_name(nu_nml, 'co2_surface_source_stream_nl', status=nml_error) + if (nml_error == 0) then + read(nu_nml, nml=co2_surface_source_stream_nl, iostat=nml_error) + if (nml_error /= 0) then + call endrun(' ERROR reading co2_surface_source_stream_nl namelist'//errMsg(sourcefile, __LINE__)) + end if + end if + close(nu_nml) + endif + call mpi_bcast(stream_co2_surface_source_mesh_filename, & + len(stream_co2_surface_source_mesh_filename), mpi_character, 0, mpicom, ierr) + if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_mesh_filename") + call mpi_bcast(stream_co2_surface_source_data_filename, & + len(stream_co2_surface_source_data_filename), mpi_character, 0, mpicom, ierr) + if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_data_filename") + call mpi_bcast(stream_co2_surface_source_varlist, & + len(stream_co2_surface_source_varlist), mpi_character, 0, mpicom, ierr) + if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_varname") + call mpi_bcast(stream_co2_surface_source_year_first, & + 1, mpi_integer, 0, mpicom, ierr) + if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_year_first") + call mpi_bcast(stream_co2_surface_source_year_last, & + 1, mpi_integer, 0, mpicom, ierr) + if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_year_last") + call mpi_bcast(stream_co2_surface_source_year_align, & + 1, mpi_integer, 0, mpicom, ierr) + if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_year_align") + + if (masterproc) then + write(iulog,'(a)') ' ' + write(iulog,'(2a)') subname,' stream co2_surface_source settings:' + write(iulog,'(3a)') subname,' stream_co2_surface_source_data_filename = ',& + trim(stream_co2_surface_source_data_filename) + write(iulog,'(3a)') subname,' stream_co2_surface_source_mesh_filename = ',& + trim(stream_co2_surface_source_mesh_filename) + write(iulog,'(3a)') subname,' stream_co2_surface_source_varname = ',& + trim(stream_co2_surface_source_varname) + write(iulog,'(2a,i0)') subname,' stream_co2_surface_source_year_first = ',& + stream_co2_surface_source_year_first + write(iulog,'(2a,i0)') subname,' stream_co2_surface_source_year_last = ',& + stream_co2_surface_source_year_last + write(iulog,'(2a,i0)') subname,' stream_co2_surface_source_year_align = ',& + stream_co2_surface_source_year_align + write(iulog,'(a)') ' ' + endif + + end subroutine stream_co2_surface_source_readnl + + !================================================================ + subroutine stream_co2_surface_source_init(rc) + use dshr_strdata_mod, only: shr_strdata_init_from_inline + + ! input/output variables + integer, intent(out) :: rc + + ! local variables + character(*), parameter :: subName = "('stream_co2_surface_source_init')" + !----------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + ! Read the input namelist + call stream_co2_surface_source_readnl('atm_in') + + ! Initialize the cdeps data type sdat_co2_surface_source + call shr_strdata_init_from_inline(sdat_co2_surface_source, & + my_task = iam, & + logunit = iulog, & + compname = 'ATM', & + model_clock = model_clock, & + model_mesh = model_mesh, & + stream_meshfile = trim(stream_co2_surface_source_mesh_filename), & + stream_filenames = (/trim(stream_co2_surface_source_data_filename)/), & + stream_yearFirst = stream_co2_surface_source_year_first, & + stream_yearLast = stream_co2_surface_source_year_last, & + stream_yearAlign = stream_co2_surface_source_year_align, & + stream_fldlistFile = (/stream_co2_surface_source_varname/), & + stream_fldListModel = (/stream_co2_surface_source_varname/), & + stream_lev_dimname = 'null', & + stream_mapalgo = 'bilinear', & + stream_offset = 0, & + stream_taxmode = 'cycle', & + stream_dtlimit = 1.0e30_r8, & + stream_tintalgo = 'linear', & + stream_name = 'CO2_SURFACE_SOURCE data ', & + rc = rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + stream_co2_surface_source_is_initialized = .true. + + end subroutine stream_co2_surface_source_init + + !================================================================ + subroutine stream_co2_surface_source_interp(cam_out, rc) + + use dshr_methods_mod , only : dshr_fldbun_getfldptr + use dshr_strdata_mod , only : shr_strdata_advance + use camsrfexch , only : cam_out_t + use ppgrid , only : begchunk, endchunk + use time_manager , only : get_curr_date + use phys_grid , only : get_ncols_p + + ! input/output variables + type(cam_out_t) , intent(inout) :: cam_out(begchunk:endchunk) + integer , intent(out) :: rc + + ! local variables + integer :: ig,icol,lchnk + integer :: year ! year (0, ...) for nstep+1 + integer :: mon ! month (1, ..., 12) for nstep+1 + integer :: day ! day of month (1, ..., 31) for nstep+1 + integer :: sec ! seconds into current date for nstep+1 + integer :: mcdate ! Current model date (yyyymmdd) + real(r8), pointer :: dataptr1d(:) + character(*), parameter :: subName = "('stream_co2_surface_source_interp')" + !----------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + ! Advance co2_surface_source sdat stream + call get_curr_date(year, mon, day, sec) + mcdate = year*10000 + mon*100 + day + call shr_strdata_advance(sdat_co2_surface_source, ymd=mcdate, tod=sec, logunit=iulog, & + istr='co2_surface_source_diag', rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Get pointer for stream data that is time and spatially interpolated to model time and grid + call dshr_fldbun_getFldPtr(sdat_co2_surface_source%pstrm(1)%fldbun_model, & + stream_co2_surface_source_varname, fldptr1=dataptr1d, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Set output diagnostic co2_surface_source + ig = 1 + do lchnk = begchunk,endchunk + do icol = 1,get_ncols_p(lchnk) + cam_out(lchnk)%co2_diag(icol) = dataptr1d(ig) + ig = ig + 1 + end do + end do + + end subroutine stream_co2_surface_source_interp + +end module atm_stream_co2_surface_source From e09687d0d1abdfcc6cb44f25647a23c4a4d64539 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Sat, 11 Jul 2026 10:32:40 +0200 Subject: [PATCH 2/9] fixed compiler problems --- bld/build-namelist | 18 +++--- bld/namelist_files/namelist_defaults_cam.xml | 9 +++ bld/namelist_files/namelist_definition.xml | 32 ++++------ src/cpl/nuopc/atm_import_export.F90 | 8 +-- src/cpl/nuopc/atm_stream_co2.F90 | 62 +++++++++++--------- 5 files changed, 70 insertions(+), 59 deletions(-) diff --git a/bld/build-namelist b/bld/build-namelist index eb3086c392..997d5c50e5 100755 --- a/bld/build-namelist +++ b/bld/build-namelist @@ -713,14 +713,16 @@ if (!($simple_phys or $aqua_mode)) { # Setup default co2 surface source stream only if not simple_phys or aqua_mode and # the chemistry cannot produce the nitrogen depostion fluxes if (!($simple_phys or $aqua_mode)) { - add_default($nl, 'co2_surface_source') - add_default($nl, 'stream_co2_surface_source_mesh_filename' , 'sim_year'=>$sim_year); - add_default($nl, 'stream_co2_surface_source_data_filename' , 'sim_year'=>$sim_year); - add_default($nl, 'stream_co2_surface_source_year_first' , 'sim_year'=>$sim_year); - add_default($nl, 'stream_co2_surface_source_year_last' , 'sim_year'=>$sim_year); - add_default($nl, 'stream_co2_surface_source_year_align' , 'sim_year'=>$sim_year); - add_default($nl, 'stream_co2_surface_source_varname'); - } + add_default($nl, 'co2_surface_source'); + my $co2_surface_source = get_default_value("co2_surface_source"); + #if (lc($co2_surface_source) eq 'true') { + add_default($nl, 'stream_co2_surface_source_mesh_filename'); + add_default($nl, 'stream_co2_surface_source_data_filename'); + add_default($nl, 'stream_co2_surface_source_data_varname'); + add_default($nl, 'stream_co2_surface_source_year_first'); + add_default($nl, 'stream_co2_surface_source_year_last' ); + add_default($nl, 'stream_co2_surface_source_year_align'); + #} } # Topography diff --git a/bld/namelist_files/namelist_defaults_cam.xml b/bld/namelist_files/namelist_defaults_cam.xml index 097128e591..7e79de5133 100644 --- a/bld/namelist_files/namelist_defaults_cam.xml +++ b/bld/namelist_files/namelist_defaults_cam.xml @@ -2016,6 +2016,15 @@ atm/cam/dst/dst_source2x2tuned-cam4-06132012.nc atm/cam/dst/dst_source1x1tuned-cam4-06202012.nc + +.false. +unset +unset +unset +-999 +-999 +-999 + NDEP_NHx_month:NDEP_NOy_month drynhx:wetnhx:drynoy:wetnoy diff --git a/bld/namelist_files/namelist_definition.xml b/bld/namelist_files/namelist_definition.xml index eb4aff9184..7d4517ae73 100644 --- a/bld/namelist_files/namelist_definition.xml +++ b/bld/namelist_files/namelist_definition.xml @@ -10163,7 +10163,7 @@ Default: false - Scales the relative humidity in the optical calculations - within OSLO_AERO for modes 1-5 + within OSLO_AERO for modes 1-5 - RH not scaled for dust (modes 6-7) or seasalt (modes 8-10) Default: 1.0 @@ -10295,19 +10295,28 @@ Default: path If TRUE, set co2_diag sent to land and ocean to value read from co2_surface_source_data_filename Default: FALSE - + +Grid mesh file corresponding to sream_co2_surface_source_data_filename. + + +co2 stream data filename. + + +co2 varname on stream data file(s). + First year to use in co2 stream data. Default: 2000 - Last year last to use in co2 stream data. Default: 2000 - The simulation year corresponding to stream_co2_surface_source_year_first. @@ -10325,19 +10334,4 @@ Set by build-namelist. Default: 1 - -co2 stream data filename. - - - -Grid mesh file corresponding to sream_co2_surface_source_data_filename. - - - -Variable names on co2 stream file(s). - - diff --git a/src/cpl/nuopc/atm_import_export.F90 b/src/cpl/nuopc/atm_import_export.F90 index 426d4b27b7..4281c7ca16 100644 --- a/src/cpl/nuopc/atm_import_export.F90 +++ b/src/cpl/nuopc/atm_import_export.F90 @@ -1,6 +1,6 @@ module atm_import_export - use NUOPC , only : NUOPC_CompAttributeGet, NUOPC_Advertise, NUOPC_IsConnected + use NUOPC , only : NUOPC_CompAttributeGet, NUOPC_Advertise, NUOPC_IsConnected use NUOPC_Model , only : NUOPC_ModelGet use ESMF , only : ESMF_GridComp, ESMF_State, ESMF_Mesh, ESMF_StateGet, ESMF_Field use ESMF , only : ESMF_Clock @@ -29,7 +29,7 @@ module atm_import_export use cam_control_mod , only : aqua_planet, simple_phys use cam_esmf_mod , only : cam_esmf_set_areas use atm_stream_co2_surface_source, only : stream_co2_surface_source_init, stream_co2_surface_source_interp - use atm_stream_co2_surface_source, only : stream_co2_surface_source_is_initialized + use atm_stream_co2_surface_source, only : stream_co2_surface_source_is_initialized, co2_surface_source implicit none private ! except @@ -1230,8 +1230,8 @@ subroutine export_fields(gcomp, cam_out, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return if (exists) then ! if co2_surface_source is a filename - use this to overwrite co2_diag - if (trim(co2_surface_source) /= 'unset') then - if (.not. stream_co2_is_initialized) then + if (co2_surface_source) then + if (.not. stream_co2_surface_source_is_initialized) then call stream_co2_surface_source_init(rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return end if diff --git a/src/cpl/nuopc/atm_stream_co2.F90 b/src/cpl/nuopc/atm_stream_co2.F90 index e38319a6c1..e0eea0adb2 100644 --- a/src/cpl/nuopc/atm_stream_co2.F90 +++ b/src/cpl/nuopc/atm_stream_co2.F90 @@ -14,7 +14,7 @@ module atm_stream_co2_surface_source use shr_kind_mod , only : r8 => shr_kind_r8, CL => shr_kind_cl, CS => shr_kind_cs use shr_log_mod , only : errMsg => shr_log_errMsg use spmd_utils , only : mpicom, masterproc, iam - use spmd_utils , only : mpi_character, mpi_integer + use spmd_utils , only : mpi_character, mpi_integer, mpi_logical use cam_logfile , only : iulog use cam_abortutils , only : endrun use cam_esmf_mod , only : model_clock, model_mesh @@ -26,19 +26,20 @@ module atm_stream_co2_surface_source public :: stream_co2_surface_source_init ! position datasets for dynamic co2_surface_source public :: stream_co2_surface_source_interp ! interpolates between two years of co2_surface_source file data - logical, public, protected :: stream_co2_surface_source_is_initialized = .false. - type(shr_strdata_type) :: sdat_co2_surface_source ! input data stream ! namelist variables - character(len=CL) :: stream_co2_surface_source_data_filename character(len=CL) :: stream_co2_surface_source_mesh_filename - character(len=CL) :: stream_co2_surface_source_varname ! variable name for co2_surface_source on stream file(s) - integer :: stream_co2_surface_source_year_first ! first year in stream to use - integer :: stream_co2_surface_source_year_last ! last year in stream to use - integer :: stream_co2_surface_source_year_align ! align stream_year_first + character(len=CL) :: stream_co2_surface_source_data_filename + character(len=CL) :: stream_co2_surface_source_data_varname ! variable name for co2_surface_source on stream file(s) + integer :: stream_co2_surface_source_year_first ! first year in stream to use + integer :: stream_co2_surface_source_year_last ! last year in stream to use + integer :: stream_co2_surface_source_year_align ! align stream_year_first - character(len=*), parameter :: sourcefile = __FILE__ + logical, public, protected :: co2_surface_source + logical, public, protected :: stream_co2_surface_source_is_initialized = .false. + + character(len=*), parameter :: u_FILE_u = __FILE__ !============================================================================== contains @@ -61,45 +62,50 @@ subroutine stream_co2_surface_source_readnl(nlfile) !----------------------------------------------------------------------- namelist /co2_surface_source_stream_nl/ & - stream_co2_surface_source_data_filename, & + co2_surface_source, & stream_co2_surface_source_mesh_filename, & + stream_co2_surface_source_data_filename, & + stream_co2_surface_source_data_varname, & stream_co2_surface_source_year_first, & stream_co2_surface_source_year_last, & - stream_co2_surface_source_year_align, & - stream_co2_surface_source_var + stream_co2_surface_source_year_align ! Default values for namelist + co2_surface_source = .false. stream_co2_surface_source_data_filename = ' ' stream_co2_surface_source_mesh_filename = ' ' - stream_co2_surface_source_varlist = ' ' - stream_co2_surface_source_year_first = 1 ! first year in stream to use - stream_co2_surface_source_year_last = 1 ! last year in stream to use - stream_co2_surface_source_year_align = 1 ! align stream_co2_surface_source_year_first with this model year + stream_co2_surface_source_data_varname = ' ' + stream_co2_surface_source_year_first = -999 ! first year in stream to use + stream_co2_surface_source_year_last = -999 ! last year in stream to use + stream_co2_surface_source_year_align = -999 ! align stream_co2_surface_source_year_first with this model year ! Read co2_surface_source_stream namelist if (masterproc) then open( newunit=nu_nml, file=trim(nlfile), status='old', iostat=nml_error ) if (nml_error /= 0) then - call endrun(subName//': ERROR opening '//trim(nlfile)//errMsg(sourcefile, __LINE__)) + call endrun(subName//': ERROR opening '//trim(nlfile)//errMsg(u_FILE_u, __LINE__)) end if call shr_nl_find_group_name(nu_nml, 'co2_surface_source_stream_nl', status=nml_error) if (nml_error == 0) then read(nu_nml, nml=co2_surface_source_stream_nl, iostat=nml_error) if (nml_error /= 0) then - call endrun(' ERROR reading co2_surface_source_stream_nl namelist'//errMsg(sourcefile, __LINE__)) + call endrun(' ERROR reading co2_surface_source_stream_nl namelist'//errMsg(u_FILE_u, __LINE__)) end if end if close(nu_nml) endif + call mpi_bcast(co2_surface_source, & + 1, mpi_logical, 0, mpicom, ierr) + if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_mesh_filename") call mpi_bcast(stream_co2_surface_source_mesh_filename, & len(stream_co2_surface_source_mesh_filename), mpi_character, 0, mpicom, ierr) if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_mesh_filename") call mpi_bcast(stream_co2_surface_source_data_filename, & len(stream_co2_surface_source_data_filename), mpi_character, 0, mpicom, ierr) if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_data_filename") - call mpi_bcast(stream_co2_surface_source_varlist, & - len(stream_co2_surface_source_varlist), mpi_character, 0, mpicom, ierr) - if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_varname") + call mpi_bcast(stream_co2_surface_source_data_varname, & + len(stream_co2_surface_source_data_varname), mpi_character, 0, mpicom, ierr) + if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_data_varname") call mpi_bcast(stream_co2_surface_source_year_first, & 1, mpi_integer, 0, mpicom, ierr) if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_year_first") @@ -117,8 +123,8 @@ subroutine stream_co2_surface_source_readnl(nlfile) trim(stream_co2_surface_source_data_filename) write(iulog,'(3a)') subname,' stream_co2_surface_source_mesh_filename = ',& trim(stream_co2_surface_source_mesh_filename) - write(iulog,'(3a)') subname,' stream_co2_surface_source_varname = ',& - trim(stream_co2_surface_source_varname) + write(iulog,'(3a)') subname,' stream_co2_surface_source_data_varname = ',& + trim(stream_co2_surface_source_data_varname) write(iulog,'(2a,i0)') subname,' stream_co2_surface_source_year_first = ',& stream_co2_surface_source_year_first write(iulog,'(2a,i0)') subname,' stream_co2_surface_source_year_last = ',& @@ -158,8 +164,8 @@ subroutine stream_co2_surface_source_init(rc) stream_yearFirst = stream_co2_surface_source_year_first, & stream_yearLast = stream_co2_surface_source_year_last, & stream_yearAlign = stream_co2_surface_source_year_align, & - stream_fldlistFile = (/stream_co2_surface_source_varname/), & - stream_fldListModel = (/stream_co2_surface_source_varname/), & + stream_fldlistFile = (/stream_co2_surface_source_data_varname/), & + stream_fldListModel = (/stream_co2_surface_source_data_varname/), & stream_lev_dimname = 'null', & stream_mapalgo = 'bilinear', & stream_offset = 0, & @@ -210,18 +216,18 @@ subroutine stream_co2_surface_source_interp(cam_out, rc) ! Get pointer for stream data that is time and spatially interpolated to model time and grid call dshr_fldbun_getFldPtr(sdat_co2_surface_source%pstrm(1)%fldbun_model, & - stream_co2_surface_source_varname, fldptr1=dataptr1d, rc=rc) + stream_co2_surface_source_data_varname, fldptr1=dataptr1d, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return ! Set output diagnostic co2_surface_source ig = 1 do lchnk = begchunk,endchunk do icol = 1,get_ncols_p(lchnk) - cam_out(lchnk)%co2_diag(icol) = dataptr1d(ig) + cam_out(lchnk)%co2diag(icol) = dataptr1d(ig) ig = ig + 1 end do end do end subroutine stream_co2_surface_source_interp -end module atm_stream_co2_surface_source +end module atm_stream_co2_surface_source From 0b96e5511e2590ac332ac236d775963064c4a7fb Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Sun, 12 Jul 2026 15:05:57 +0200 Subject: [PATCH 3/9] updates to get 1850 test case working --- bld/build-namelist | 25 ++++--- bld/namelist_files/namelist_defaults_cam.xml | 6 -- src/cpl/nuopc/atm_import_export.F90 | 8 +-- src/cpl/nuopc/atm_stream_co2.F90 | 74 +++++++++++--------- 4 files changed, 61 insertions(+), 52 deletions(-) diff --git a/bld/build-namelist b/bld/build-namelist index 997d5c50e5..8112af0f3a 100755 --- a/bld/build-namelist +++ b/bld/build-namelist @@ -714,15 +714,22 @@ if (!($simple_phys or $aqua_mode)) { # the chemistry cannot produce the nitrogen depostion fluxes if (!($simple_phys or $aqua_mode)) { add_default($nl, 'co2_surface_source'); - my $co2_surface_source = get_default_value("co2_surface_source"); - #if (lc($co2_surface_source) eq 'true') { - add_default($nl, 'stream_co2_surface_source_mesh_filename'); - add_default($nl, 'stream_co2_surface_source_data_filename'); - add_default($nl, 'stream_co2_surface_source_data_varname'); - add_default($nl, 'stream_co2_surface_source_year_first'); - add_default($nl, 'stream_co2_surface_source_year_last' ); - add_default($nl, 'stream_co2_surface_source_year_align'); - #} + if ($nl->get_value('co2_surface_source') =~ /$TRUE/io) { + if ( !(defined $nl->get_value('stream_co2_surface_source_mesh_filename') and + defined $nl->get_value('stream_co2_surface_source_data_filename') and + defined $nl->get_value('stream_co2_surface_source_data_varname') and + defined $nl->get_value('stream_co2_surface_source_year_first') and + defined $nl->get_value('stream_co2_surface_source_year_last') and + defined $nl->get_value('stream_co2_surface_source_year_align') ) ) { + die "$ProgName - ERROR: if co2_surface_source is .true. then the following must be defined: + stream_co2_surface_source_mesh_filename, + stream_co2_surface_source_data_filename, + stream_co2_surface_source_data_varname, + stream_co2_surface_source_year_first, + stream_co2_surface_source_year_last, + stream_co2_surface_source_year_align\n"; + } + } } # Topography diff --git a/bld/namelist_files/namelist_defaults_cam.xml b/bld/namelist_files/namelist_defaults_cam.xml index 7e79de5133..beecf7beec 100644 --- a/bld/namelist_files/namelist_defaults_cam.xml +++ b/bld/namelist_files/namelist_defaults_cam.xml @@ -2018,12 +2018,6 @@ .false. -unset -unset -unset --999 --999 --999 NDEP_NHx_month:NDEP_NOy_month diff --git a/src/cpl/nuopc/atm_import_export.F90 b/src/cpl/nuopc/atm_import_export.F90 index 4281c7ca16..23c8060c96 100644 --- a/src/cpl/nuopc/atm_import_export.F90 +++ b/src/cpl/nuopc/atm_import_export.F90 @@ -1230,11 +1230,11 @@ subroutine export_fields(gcomp, cam_out, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return if (exists) then ! if co2_surface_source is a filename - use this to overwrite co2_diag + if (.not. stream_co2_surface_source_is_initialized) then + call stream_co2_surface_source_init(rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end if if (co2_surface_source) then - if (.not. stream_co2_surface_source_is_initialized) then - call stream_co2_surface_source_init(rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - end if call stream_co2_surface_source_interp(cam_out, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return end if diff --git a/src/cpl/nuopc/atm_stream_co2.F90 b/src/cpl/nuopc/atm_stream_co2.F90 index e0eea0adb2..be0ccfc09f 100644 --- a/src/cpl/nuopc/atm_stream_co2.F90 +++ b/src/cpl/nuopc/atm_stream_co2.F90 @@ -94,44 +94,52 @@ subroutine stream_co2_surface_source_readnl(nlfile) end if close(nu_nml) endif + call mpi_bcast(co2_surface_source, & 1, mpi_logical, 0, mpicom, ierr) - if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_mesh_filename") - call mpi_bcast(stream_co2_surface_source_mesh_filename, & - len(stream_co2_surface_source_mesh_filename), mpi_character, 0, mpicom, ierr) - if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_mesh_filename") - call mpi_bcast(stream_co2_surface_source_data_filename, & - len(stream_co2_surface_source_data_filename), mpi_character, 0, mpicom, ierr) - if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_data_filename") - call mpi_bcast(stream_co2_surface_source_data_varname, & - len(stream_co2_surface_source_data_varname), mpi_character, 0, mpicom, ierr) - if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_data_varname") - call mpi_bcast(stream_co2_surface_source_year_first, & - 1, mpi_integer, 0, mpicom, ierr) - if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_year_first") - call mpi_bcast(stream_co2_surface_source_year_last, & - 1, mpi_integer, 0, mpicom, ierr) - if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_year_last") - call mpi_bcast(stream_co2_surface_source_year_align, & - 1, mpi_integer, 0, mpicom, ierr) - if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_year_align") + if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: co2_surface_source") + + if (co2_surface_source) then + call mpi_bcast(stream_co2_surface_source_mesh_filename, & + len(stream_co2_surface_source_mesh_filename), mpi_character, 0, mpicom, ierr) + if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_mesh_filename") + call mpi_bcast(stream_co2_surface_source_data_filename, & + len(stream_co2_surface_source_data_filename), mpi_character, 0, mpicom, ierr) + if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_data_filename") + call mpi_bcast(stream_co2_surface_source_data_varname, & + len(stream_co2_surface_source_data_varname), mpi_character, 0, mpicom, ierr) + if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_data_varname") + call mpi_bcast(stream_co2_surface_source_year_first, & + 1, mpi_integer, 0, mpicom, ierr) + if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_year_first") + call mpi_bcast(stream_co2_surface_source_year_last, & + 1, mpi_integer, 0, mpicom, ierr) + if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_year_last") + call mpi_bcast(stream_co2_surface_source_year_align, & + 1, mpi_integer, 0, mpicom, ierr) + if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_year_align") + end if if (masterproc) then write(iulog,'(a)') ' ' - write(iulog,'(2a)') subname,' stream co2_surface_source settings:' - write(iulog,'(3a)') subname,' stream_co2_surface_source_data_filename = ',& - trim(stream_co2_surface_source_data_filename) - write(iulog,'(3a)') subname,' stream_co2_surface_source_mesh_filename = ',& - trim(stream_co2_surface_source_mesh_filename) - write(iulog,'(3a)') subname,' stream_co2_surface_source_data_varname = ',& - trim(stream_co2_surface_source_data_varname) - write(iulog,'(2a,i0)') subname,' stream_co2_surface_source_year_first = ',& - stream_co2_surface_source_year_first - write(iulog,'(2a,i0)') subname,' stream_co2_surface_source_year_last = ',& - stream_co2_surface_source_year_last - write(iulog,'(2a,i0)') subname,' stream_co2_surface_source_year_align = ',& - stream_co2_surface_source_year_align - write(iulog,'(a)') ' ' + if (co2_surface_source) then + write(iulog,'(2a)') subname,' co2 surface source override settings::' + write(iulog,'(3a)') subname,' stream_co2_surface_source_data_filename = ',& + trim(stream_co2_surface_source_data_filename) + write(iulog,'(3a)') subname,' stream_co2_surface_source_mesh_filename = ',& + trim(stream_co2_surface_source_mesh_filename) + write(iulog,'(3a)') subname,' stream_co2_surface_source_data_varname = ',& + trim(stream_co2_surface_source_data_varname) + write(iulog,'(2a,i0)') subname,' stream_co2_surface_source_year_first = ',& + stream_co2_surface_source_year_first + write(iulog,'(2a,i0)') subname,' stream_co2_surface_source_year_last = ',& + stream_co2_surface_source_year_last + write(iulog,'(2a,i0)') subname,' stream_co2_surface_source_year_align = ',& + stream_co2_surface_source_year_align + write(iulog,'(a)') ' ' + else + write(iulog, '(2a)') subname, 'co2 surface source will not be overwritten' + end if endif end subroutine stream_co2_surface_source_readnl From cba45053c14071e243de3eaedb8b685a350f893f Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Mon, 13 Jul 2026 13:40:31 +0200 Subject: [PATCH 4/9] added taxmode as namelists to both ndep and co2 streams --- bld/namelist_files/namelist_defaults_cam.xml | 3 ++ bld/namelist_files/namelist_definition.xml | 8 ++++ src/cpl/nuopc/atm_stream_co2.F90 | 19 +++++++- src/cpl/nuopc/atm_stream_ndep.F90 | 46 +++++++++++++------- 4 files changed, 59 insertions(+), 17 deletions(-) diff --git a/bld/namelist_files/namelist_defaults_cam.xml b/bld/namelist_files/namelist_defaults_cam.xml index beecf7beec..33ec962c04 100644 --- a/bld/namelist_files/namelist_defaults_cam.xml +++ b/bld/namelist_files/namelist_defaults_cam.xml @@ -2041,6 +2041,9 @@ 2015 2010 +cycle +extend + 1 1850 diff --git a/bld/namelist_files/namelist_definition.xml b/bld/namelist_files/namelist_definition.xml index 7d4517ae73..f88b8e165d 100644 --- a/bld/namelist_files/namelist_definition.xml +++ b/bld/namelist_files/namelist_definition.xml @@ -8262,6 +8262,10 @@ calendar is setup to span the same year range as the forcing data. Set by build-namelist. Default: 1 + +time extrapolation mode. + @@ -10307,6 +10311,10 @@ co2 stream data filename. group="co2_surface_source_stream_nl" valid_values="" > co2 varname on stream data file(s). + +time extrapolation mode. + First year to use in co2 stream data. diff --git a/src/cpl/nuopc/atm_stream_co2.F90 b/src/cpl/nuopc/atm_stream_co2.F90 index be0ccfc09f..9ed57e09df 100644 --- a/src/cpl/nuopc/atm_stream_co2.F90 +++ b/src/cpl/nuopc/atm_stream_co2.F90 @@ -32,6 +32,7 @@ module atm_stream_co2_surface_source character(len=CL) :: stream_co2_surface_source_mesh_filename character(len=CL) :: stream_co2_surface_source_data_filename character(len=CL) :: stream_co2_surface_source_data_varname ! variable name for co2_surface_source on stream file(s) + character(len=CS) :: stream_co2_surface_source_taxmode ! 'cycle' or 'extend' or 'limit' integer :: stream_co2_surface_source_year_first ! first year in stream to use integer :: stream_co2_surface_source_year_last ! last year in stream to use integer :: stream_co2_surface_source_year_align ! align stream_year_first @@ -66,6 +67,7 @@ subroutine stream_co2_surface_source_readnl(nlfile) stream_co2_surface_source_mesh_filename, & stream_co2_surface_source_data_filename, & stream_co2_surface_source_data_varname, & + stream_co2_surface_source_taxmode, & stream_co2_surface_source_year_first, & stream_co2_surface_source_year_last, & stream_co2_surface_source_year_align @@ -75,6 +77,7 @@ subroutine stream_co2_surface_source_readnl(nlfile) stream_co2_surface_source_data_filename = ' ' stream_co2_surface_source_mesh_filename = ' ' stream_co2_surface_source_data_varname = ' ' + stream_co2_surface_source_taxmode = 'unset' stream_co2_surface_source_year_first = -999 ! first year in stream to use stream_co2_surface_source_year_last = -999 ! last year in stream to use stream_co2_surface_source_year_align = -999 ! align stream_co2_surface_source_year_first with this model year @@ -109,6 +112,9 @@ subroutine stream_co2_surface_source_readnl(nlfile) call mpi_bcast(stream_co2_surface_source_data_varname, & len(stream_co2_surface_source_data_varname), mpi_character, 0, mpicom, ierr) if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_data_varname") + call mpi_bcast(stream_co2_surface_source_taxmode, & + len(stream_co2_surface_source_data_varname), mpi_character, 0, mpicom, ierr) + if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_data_varname") call mpi_bcast(stream_co2_surface_source_year_first, & 1, mpi_integer, 0, mpicom, ierr) if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_year_first") @@ -118,6 +124,15 @@ subroutine stream_co2_surface_source_readnl(nlfile) call mpi_bcast(stream_co2_surface_source_year_align, & 1, mpi_integer, 0, mpicom, ierr) if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_year_align") + + ! error check + if ( trim(stream_co2_surface_source_taxmode) /= 'cycle' .and. & + trim(stream_co2_surface_source_taxmode) /= 'extend' .and. & + trim(stream_co2_surface_source_taxmode) /= 'limit') then + call endrun(subName//': ERROR stream_co2_surface_source_taxmode '& + //trim(stream_co2_surface_source_taxmode)& + //' must be either cycle, extend or limit') + end if end if if (masterproc) then @@ -130,6 +145,8 @@ subroutine stream_co2_surface_source_readnl(nlfile) trim(stream_co2_surface_source_mesh_filename) write(iulog,'(3a)') subname,' stream_co2_surface_source_data_varname = ',& trim(stream_co2_surface_source_data_varname) + write(iulog,'(3a)') subname,' stream_co2_surface_source_taxmode = ',& + trim(stream_co2_surface_source_data_varname) write(iulog,'(2a,i0)') subname,' stream_co2_surface_source_year_first = ',& stream_co2_surface_source_year_first write(iulog,'(2a,i0)') subname,' stream_co2_surface_source_year_last = ',& @@ -177,7 +194,7 @@ subroutine stream_co2_surface_source_init(rc) stream_lev_dimname = 'null', & stream_mapalgo = 'bilinear', & stream_offset = 0, & - stream_taxmode = 'cycle', & + stream_taxmode = trim(stream_co2_surface_source_taxmode), & stream_dtlimit = 1.0e30_r8, & stream_tintalgo = 'linear', & stream_name = 'CO2_SURFACE_SOURCE data ', & diff --git a/src/cpl/nuopc/atm_stream_ndep.F90 b/src/cpl/nuopc/atm_stream_ndep.F90 index b72a598444..6dd92a155d 100644 --- a/src/cpl/nuopc/atm_stream_ndep.F90 +++ b/src/cpl/nuopc/atm_stream_ndep.F90 @@ -41,6 +41,7 @@ module atm_stream_ndep character(len=CL) :: stream_ndep_data_filename character(len=CL) :: stream_ndep_mesh_filename character(len=CL) :: stream_ndep_varlist ! colon delimited string of ndep field names + character(len=CS) :: stream_ndep_taxmode ! time extrapolation - 'cycle','limit' or 'extend' integer :: stream_ndep_year_first ! first year in stream to use integer :: stream_ndep_year_last ! last year in stream to use integer :: stream_ndep_year_align ! align stream_year_firstndep with @@ -76,12 +77,14 @@ subroutine stream_ndep_readnl(nlfile) stream_ndep_year_first, & stream_ndep_year_last, & stream_ndep_year_align, & - stream_ndep_varlist + stream_ndep_varlist, & + stream_ndep_taxmode ! Default values for namelist stream_ndep_data_filename = ' ' stream_ndep_mesh_filename = ' ' stream_ndep_varlist = ' ' + stream_ndep_taxmode = 'unset' stream_ndep_year_first = 1 ! first year in stream to use stream_ndep_year_last = 1 ! last year in stream to use stream_ndep_year_align = 1 ! align stream_ndep_year_first with this model year @@ -101,23 +104,11 @@ subroutine stream_ndep_readnl(nlfile) end if close(nu_nml) endif - call mpi_bcast(stream_ndep_mesh_filename, len(stream_ndep_mesh_filename), mpi_character, 0, mpicom, ierr) - if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_ndep_mesh_filename") - call mpi_bcast(stream_ndep_data_filename, len(stream_ndep_data_filename), mpi_character, 0, mpicom, ierr) - if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_ndep_data_filename") - call mpi_bcast(stream_ndep_varlist, len(stream_ndep_varlist), mpi_character, 0, mpicom, ierr) - if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_ndep_varlist") - call mpi_bcast(stream_ndep_year_first, 1, mpi_integer, 0, mpicom, ierr) - if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_ndep_year_first") - call mpi_bcast(stream_ndep_year_last, 1, mpi_integer, 0, mpicom, ierr) - if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_ndep_year_last") - call mpi_bcast(stream_ndep_year_align, 1, mpi_integer, 0, mpicom, ierr) - if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_ndep_year_align") ! Determine if ndep stream is active, and if not return + call mpi_bcast(stream_ndep_data_filename, len(stream_ndep_data_filename), mpi_character, 0, mpicom, ierr) + if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_ndep_data_filename") ndep_stream_active = (len_trim(stream_ndep_data_filename)>0 .and. stream_ndep_data_filename/='UNSET') - - ! Check whether the stream is being used. if (.not. ndep_stream_active) then if (masterproc) then write(iulog,'(a)') ' ' @@ -127,6 +118,29 @@ subroutine stream_ndep_readnl(nlfile) RETURN endif + ! Broadcast remaining namelist variables + call mpi_bcast(stream_ndep_mesh_filename, len(stream_ndep_mesh_filename), mpi_character, 0, mpicom, ierr) + if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_ndep_mesh_filename") + call mpi_bcast(stream_ndep_varlist, len(stream_ndep_varlist), mpi_character, 0, mpicom, ierr) + if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_ndep_varlist") + call mpi_bcast(stream_ndep_taxmode, len(stream_ndep_taxmode), mpi_character, 0, mpicom, ierr) + if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_ndep_taxmode") + call mpi_bcast(stream_ndep_year_first, 1, mpi_integer, 0, mpicom, ierr) + if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_ndep_year_first") + call mpi_bcast(stream_ndep_year_last, 1, mpi_integer, 0, mpicom, ierr) + if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_ndep_year_last") + call mpi_bcast(stream_ndep_year_align, 1, mpi_integer, 0, mpicom, ierr) + if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_ndep_year_align") + + ! error check + if ( trim(stream_ndep_taxmode) /= 'cycle' .and. & + trim(stream_ndep_taxmode) /= 'extend' .and. & + trim(stream_ndep_taxmode) /= 'limit') then + call endrun(subName//': ERROR stream_ndep_taxmode '& + //trim(stream_ndep_taxmode) & + //' must be either cycle, extend or limit') + end if + ! Create array of variable names on ndep forcing file - needed to initialize sdat numflds = shr_string_listGetNum(stream_ndep_varlist) allocate(stream_ndep_varnames(numflds), stat=ierr) @@ -185,7 +199,7 @@ subroutine stream_ndep_init(rc) stream_lev_dimname = 'null', & stream_mapalgo = 'bilinear', & stream_offset = 0, & - stream_taxmode = 'cycle', & + stream_taxmode = trim(stream_ndep_taxmode), & stream_dtlimit = 1.0e30_r8, & stream_tintalgo = 'linear', & stream_name = 'Nitrogen deposition data ', & From c07bbfc93e0e45caeb05e611008acbee6779b5d6 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Tue, 14 Jul 2026 10:20:45 +0200 Subject: [PATCH 5/9] changes to get tests for co2_surface_source working --- bld/build-namelist | 5 ++- bld/namelist_files/namelist_definition.xml | 2 +- src/cpl/nuopc/atm_stream_co2.F90 | 50 +++++++++++----------- src/utils/cam_pio_utils.F90 | 2 +- 4 files changed, 32 insertions(+), 27 deletions(-) diff --git a/bld/build-namelist b/bld/build-namelist index 8112af0f3a..0063c23985 100755 --- a/bld/build-namelist +++ b/bld/build-namelist @@ -706,6 +706,7 @@ if (!($simple_phys or $aqua_mode)) { add_default($nl, 'stream_ndep_year_first' , 'sim_year'=>$sim_year); add_default($nl, 'stream_ndep_year_last' , 'sim_year'=>$sim_year); add_default($nl, 'stream_ndep_year_align' , 'sim_year'=>$sim_year); + add_default($nl, 'stream_ndep_taxmode' , 'sim_year'=>$sim_year); add_default($nl, 'stream_ndep_varlist'); } } @@ -720,11 +721,13 @@ if (!($simple_phys or $aqua_mode)) { defined $nl->get_value('stream_co2_surface_source_data_varname') and defined $nl->get_value('stream_co2_surface_source_year_first') and defined $nl->get_value('stream_co2_surface_source_year_last') and - defined $nl->get_value('stream_co2_surface_source_year_align') ) ) { + defined $nl->get_value('stream_co2_surface_source_year_align') and + defined $nl->get_value('stream_co2_surface_source_taxmode') ) ) { die "$ProgName - ERROR: if co2_surface_source is .true. then the following must be defined: stream_co2_surface_source_mesh_filename, stream_co2_surface_source_data_filename, stream_co2_surface_source_data_varname, + stream_co2_surface_source_taxmode, stream_co2_surface_source_year_first, stream_co2_surface_source_year_last, stream_co2_surface_source_year_align\n"; diff --git a/bld/namelist_files/namelist_definition.xml b/bld/namelist_files/namelist_definition.xml index f88b8e165d..c3233c2374 100644 --- a/bld/namelist_files/namelist_definition.xml +++ b/bld/namelist_files/namelist_definition.xml @@ -10311,7 +10311,7 @@ co2 stream data filename. group="co2_surface_source_stream_nl" valid_values="" > co2 varname on stream data file(s). - time extrapolation mode. diff --git a/src/cpl/nuopc/atm_stream_co2.F90 b/src/cpl/nuopc/atm_stream_co2.F90 index 9ed57e09df..678890e25d 100644 --- a/src/cpl/nuopc/atm_stream_co2.F90 +++ b/src/cpl/nuopc/atm_stream_co2.F90 @@ -146,7 +146,7 @@ subroutine stream_co2_surface_source_readnl(nlfile) write(iulog,'(3a)') subname,' stream_co2_surface_source_data_varname = ',& trim(stream_co2_surface_source_data_varname) write(iulog,'(3a)') subname,' stream_co2_surface_source_taxmode = ',& - trim(stream_co2_surface_source_data_varname) + trim(stream_co2_surface_source_taxmode) write(iulog,'(2a,i0)') subname,' stream_co2_surface_source_year_first = ',& stream_co2_surface_source_year_first write(iulog,'(2a,i0)') subname,' stream_co2_surface_source_year_last = ',& @@ -176,30 +176,32 @@ subroutine stream_co2_surface_source_init(rc) ! Read the input namelist call stream_co2_surface_source_readnl('atm_in') - + ! Initialize the cdeps data type sdat_co2_surface_source - call shr_strdata_init_from_inline(sdat_co2_surface_source, & - my_task = iam, & - logunit = iulog, & - compname = 'ATM', & - model_clock = model_clock, & - model_mesh = model_mesh, & - stream_meshfile = trim(stream_co2_surface_source_mesh_filename), & - stream_filenames = (/trim(stream_co2_surface_source_data_filename)/), & - stream_yearFirst = stream_co2_surface_source_year_first, & - stream_yearLast = stream_co2_surface_source_year_last, & - stream_yearAlign = stream_co2_surface_source_year_align, & - stream_fldlistFile = (/stream_co2_surface_source_data_varname/), & - stream_fldListModel = (/stream_co2_surface_source_data_varname/), & - stream_lev_dimname = 'null', & - stream_mapalgo = 'bilinear', & - stream_offset = 0, & - stream_taxmode = trim(stream_co2_surface_source_taxmode), & - stream_dtlimit = 1.0e30_r8, & - stream_tintalgo = 'linear', & - stream_name = 'CO2_SURFACE_SOURCE data ', & - rc = rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (co2_surface_source) then + call shr_strdata_init_from_inline(sdat_co2_surface_source, & + my_task = iam, & + logunit = iulog, & + compname = 'ATM', & + model_clock = model_clock, & + model_mesh = model_mesh, & + stream_meshfile = trim(stream_co2_surface_source_mesh_filename), & + stream_filenames = (/trim(stream_co2_surface_source_data_filename)/), & + stream_yearFirst = stream_co2_surface_source_year_first, & + stream_yearLast = stream_co2_surface_source_year_last, & + stream_yearAlign = stream_co2_surface_source_year_align, & + stream_fldlistFile = (/stream_co2_surface_source_data_varname/), & + stream_fldListModel = (/stream_co2_surface_source_data_varname/), & + stream_lev_dimname = 'null', & + stream_mapalgo = 'bilinear', & + stream_offset = 0, & + stream_taxmode = trim(stream_co2_surface_source_taxmode), & + stream_dtlimit = 1.0e30_r8, & + stream_tintalgo = 'linear', & + stream_name = 'CO2_SURFACE_SOURCE data ', & + rc = rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end if stream_co2_surface_source_is_initialized = .true. diff --git a/src/utils/cam_pio_utils.F90 b/src/utils/cam_pio_utils.F90 index 788957869a..1977faf9a3 100644 --- a/src/utils/cam_pio_utils.F90 +++ b/src/utils/cam_pio_utils.F90 @@ -1144,7 +1144,7 @@ subroutine cam_pio_openfile(file, fname, mode, errcode) end if if(pio_iotask_rank(pio_subsystem) == 0) then - write(iulog,*) 'Opening existing file ', trim(fname), file%fh + write(iulog,'(a,2x,a,4x,i0)') 'Opening existing file ', trim(fname), file%fh end if ierr = pio_openfile(pio_subsystem, file, pio_iotype, fname, mode) From e1dcbb03983a98958886e636b8fe4f19dc8f5a50 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Wed, 15 Jul 2026 20:40:22 +0200 Subject: [PATCH 6/9] addressed issue raised in PR review --- bld/namelist_files/namelist_defaults_cam.xml | 8 +- bld/namelist_files/namelist_definition.xml | 56 ++++++----- src/control/runtime_opts.F90 | 2 + src/cpl/nuopc/atm_import_export.F90 | 12 +-- src/cpl/nuopc/atm_stream_co2.F90 | 97 +++++++++----------- src/cpl/nuopc/atm_stream_ndep.F90 | 24 ++--- 6 files changed, 101 insertions(+), 98 deletions(-) diff --git a/bld/namelist_files/namelist_defaults_cam.xml b/bld/namelist_files/namelist_defaults_cam.xml index 33ec962c04..4548ea28f9 100644 --- a/bld/namelist_files/namelist_defaults_cam.xml +++ b/bld/namelist_files/namelist_defaults_cam.xml @@ -2033,19 +2033,19 @@ 2000 1850 -1850 +1850 2010 2000 1850 -2015 +2015 2010 cycle -extend +extend 1 -1850 +1850 .false. diff --git a/bld/namelist_files/namelist_definition.xml b/bld/namelist_files/namelist_definition.xml index c3233c2374..dafbfdca52 100644 --- a/bld/namelist_files/namelist_definition.xml +++ b/bld/namelist_files/namelist_definition.xml @@ -8264,7 +8264,11 @@ Default: 1 -time extrapolation mode. +Time extrapolation algorithm to use for nitrogen deposition. +- cycle: Simply cycle through the available model data (i.e., start over when the end is reached) +- extend: Use the final value when end of data is reached. +- limit: Halt the model run if the model time exceeds the available data. +Default: extend for transient, otherwise cycle -Grid mesh file corresponding to sream_ndep_data_filename. +Grid mesh file corresponding to stream_ndep_data_filename. -Grid mesh file corresponding to sream_co2_surface_source_data_filename. + Grid mesh file corresponding to stream_co2_surface_source_data_filename. + Must be set by user. -co2 stream data filename. + Data source file for reading CO2 concentrations to be passed to the surface if co2_surface_source=.true. + Must be set by user. -co2 varname on stream data file(s). + Variable name for reading CO2 concentrations in stream_co2_surface_source_data_filename. + Must be set by user. -time extrapolation mode. + Time extrapolation algorithm to use for CO2 surface stream data. + - cycle: Simply cycle through the available model data (i.e., start over when the end is reached) + - extend: Use the final value when end of data is reached. + - limit: Halt the model run if the model time exceeds the available data. + Must be set by user. - First year to use in co2 stream data. - Default: 2000 + First year to use in CO2 surface stream data. + Must be set by user. - Last year last to use in co2 stream data. - Default: 2000 + Last year to use in CO2 surface stream data. + Must be set by user. -The simulation year corresponding to stream_co2_surface_source_year_first. -A common usage is to set this to the first year of the model run -(corresponding to the xml variable RUN_STARTDATE). With this setting, -the forcing in the first year of the run will be the forcing of year -yearFirst. -Another usage is to align the calendar of transient forcing with the -model calendar. For example, setting yearAlign = yearFirst will lead -to the forcing calendar being the same as the model calendar. The -forcing for a given model year would be the forcing of the same -year. This would be appropriate in transient runs where the model -calendar is setup to span the same year range as the forcing data. -Set by build-namelist. -Default: 1 + The simulation year corresponding to stream_co2_surface_source_year_first. + A common usage is to set this to the first year of the model run + (corresponding to the xml variable RUN_STARTDATE). With this setting, + the forcing in the first year of the run will be the forcing of year + yearFirst. + Another usage is to align the calendar of transient forcing with the + model calendar. For example, setting yearAlign = yearFirst will lead + to the forcing calendar being the same as the model calendar. The + forcing for a given model year would be the forcing of the same + year. This would be appropriate in transient runs where the model + calendar is setup to span the same year range as the forcing data. + Must be set by user. diff --git a/src/control/runtime_opts.F90 b/src/control/runtime_opts.F90 index 8fab0c6b20..6186bf2a8a 100644 --- a/src/control/runtime_opts.F90 +++ b/src/control/runtime_opts.F90 @@ -104,6 +104,7 @@ subroutine read_namelist(nlfilename, single_column, scmlat, scmlon) use surface_emissions_mod, only: surface_emissions_readnl use elevated_emissions_mod, only: elevated_emissions_readnl use atm_stream_ndep, only: stream_ndep_readnl + use atm_stream_co2, only: stream_co2_surface_source_readnl !---------------------------Arguments----------------------------------- @@ -209,6 +210,7 @@ subroutine read_namelist(nlfilename, single_column, scmlat, scmlon) call surface_emissions_readnl(nlfilename) call elevated_emissions_readnl(nlfilename) call stream_ndep_readnl(nlfilename) + call stream_co2_surface_source_readnl(nlfilename) end subroutine read_namelist diff --git a/src/cpl/nuopc/atm_import_export.F90 b/src/cpl/nuopc/atm_import_export.F90 index 23c8060c96..fbf7de8377 100644 --- a/src/cpl/nuopc/atm_import_export.F90 +++ b/src/cpl/nuopc/atm_import_export.F90 @@ -28,8 +28,8 @@ module atm_import_export use chemistry , only : chem_has_ndep_flx use cam_control_mod , only : aqua_planet, simple_phys use cam_esmf_mod , only : cam_esmf_set_areas - use atm_stream_co2_surface_source, only : stream_co2_surface_source_init, stream_co2_surface_source_interp - use atm_stream_co2_surface_source, only : stream_co2_surface_source_is_initialized, co2_surface_source + use atm_stream_co2 , only : stream_co2_surface_source_init, stream_co2_surface_source_interp + use atm_stream_co2 , only : stream_co2_surface_source_is_initialized, co2_surface_source implicit none private ! except @@ -1230,11 +1230,11 @@ subroutine export_fields(gcomp, cam_out, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return if (exists) then ! if co2_surface_source is a filename - use this to overwrite co2_diag - if (.not. stream_co2_surface_source_is_initialized) then - call stream_co2_surface_source_init(rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - end if if (co2_surface_source) then + if (.not. stream_co2_surface_source_is_initialized) then + call stream_co2_surface_source_init(rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end if call stream_co2_surface_source_interp(cam_out, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return end if diff --git a/src/cpl/nuopc/atm_stream_co2.F90 b/src/cpl/nuopc/atm_stream_co2.F90 index 678890e25d..dfddf958dc 100644 --- a/src/cpl/nuopc/atm_stream_co2.F90 +++ b/src/cpl/nuopc/atm_stream_co2.F90 @@ -1,4 +1,4 @@ -module atm_stream_co2_surface_source +module atm_stream_co2 !----------------------------------------------------------------------- ! Contains methods for reading in co2_surface_source deposition data file @@ -6,14 +6,12 @@ module atm_stream_co2_surface_source ! interpolation. !----------------------------------------------------------------------- ! - use ESMF , only : ESMF_Clock, ESMF_Mesh - use ESMF , only : ESMF_SUCCESS, ESMF_LOGERR_PASSTHRU, ESMF_END_ABORT - use ESMF , only : ESMF_Finalize, ESMF_LogFoundError + use ESMF , only : ESMF_SUCCESS use nuopc_shr_methods , only : chkerr use dshr_strdata_mod , only : shr_strdata_type use shr_kind_mod , only : r8 => shr_kind_r8, CL => shr_kind_cl, CS => shr_kind_cs use shr_log_mod , only : errMsg => shr_log_errMsg - use spmd_utils , only : mpicom, masterproc, iam + use spmd_utils , only : mpicom, masterproc, iam, masterprocid use spmd_utils , only : mpi_character, mpi_integer, mpi_logical use cam_logfile , only : iulog use cam_abortutils , only : endrun @@ -96,43 +94,41 @@ subroutine stream_co2_surface_source_readnl(nlfile) end if end if close(nu_nml) + + ! Error check + if ( trim(stream_co2_surface_source_taxmode) /= 'cycle' .and. & + trim(stream_co2_surface_source_taxmode) /= 'extend' .and. & + trim(stream_co2_surface_source_taxmode) /= 'limit') then + call endrun(subName//': ERROR stream_co2_surface_source_taxmode '& + //trim(stream_co2_surface_source_taxmode)& + //' must be either cycle, extend or limit') + end if endif - call mpi_bcast(co2_surface_source, & - 1, mpi_logical, 0, mpicom, ierr) + call mpi_bcast(co2_surface_source, 1, mpi_logical, masterprocid, mpicom, ierr) if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: co2_surface_source") if (co2_surface_source) then call mpi_bcast(stream_co2_surface_source_mesh_filename, & - len(stream_co2_surface_source_mesh_filename), mpi_character, 0, mpicom, ierr) + len(stream_co2_surface_source_mesh_filename), mpi_character, masterprocid, mpicom, ierr) if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_mesh_filename") call mpi_bcast(stream_co2_surface_source_data_filename, & - len(stream_co2_surface_source_data_filename), mpi_character, 0, mpicom, ierr) + len(stream_co2_surface_source_data_filename), mpi_character, masterprocid, mpicom, ierr) if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_data_filename") call mpi_bcast(stream_co2_surface_source_data_varname, & - len(stream_co2_surface_source_data_varname), mpi_character, 0, mpicom, ierr) + len(stream_co2_surface_source_data_varname), mpi_character, masterprocid, mpicom, ierr) if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_data_varname") call mpi_bcast(stream_co2_surface_source_taxmode, & - len(stream_co2_surface_source_data_varname), mpi_character, 0, mpicom, ierr) - if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_data_varname") + len(stream_co2_surface_source_taxmode), mpi_character, masterprocid, mpicom, ierr) + if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_taxmode") call mpi_bcast(stream_co2_surface_source_year_first, & - 1, mpi_integer, 0, mpicom, ierr) + 1, mpi_integer, masterprocid, mpicom, ierr) if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_year_first") call mpi_bcast(stream_co2_surface_source_year_last, & - 1, mpi_integer, 0, mpicom, ierr) + 1, mpi_integer, masterprocid, mpicom, ierr) if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_year_last") call mpi_bcast(stream_co2_surface_source_year_align, & - 1, mpi_integer, 0, mpicom, ierr) - if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_co2_surface_source_year_align") - - ! error check - if ( trim(stream_co2_surface_source_taxmode) /= 'cycle' .and. & - trim(stream_co2_surface_source_taxmode) /= 'extend' .and. & - trim(stream_co2_surface_source_taxmode) /= 'limit') then - call endrun(subName//': ERROR stream_co2_surface_source_taxmode '& - //trim(stream_co2_surface_source_taxmode)& - //' must be either cycle, extend or limit') - end if + 1, mpi_integer, masterprocid, mpicom, ierr) end if if (masterproc) then @@ -174,34 +170,29 @@ subroutine stream_co2_surface_source_init(rc) rc = ESMF_SUCCESS - ! Read the input namelist - call stream_co2_surface_source_readnl('atm_in') - ! Initialize the cdeps data type sdat_co2_surface_source - if (co2_surface_source) then - call shr_strdata_init_from_inline(sdat_co2_surface_source, & - my_task = iam, & - logunit = iulog, & - compname = 'ATM', & - model_clock = model_clock, & - model_mesh = model_mesh, & - stream_meshfile = trim(stream_co2_surface_source_mesh_filename), & - stream_filenames = (/trim(stream_co2_surface_source_data_filename)/), & - stream_yearFirst = stream_co2_surface_source_year_first, & - stream_yearLast = stream_co2_surface_source_year_last, & - stream_yearAlign = stream_co2_surface_source_year_align, & - stream_fldlistFile = (/stream_co2_surface_source_data_varname/), & - stream_fldListModel = (/stream_co2_surface_source_data_varname/), & - stream_lev_dimname = 'null', & - stream_mapalgo = 'bilinear', & - stream_offset = 0, & - stream_taxmode = trim(stream_co2_surface_source_taxmode), & - stream_dtlimit = 1.0e30_r8, & - stream_tintalgo = 'linear', & - stream_name = 'CO2_SURFACE_SOURCE data ', & - rc = rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - end if + call shr_strdata_init_from_inline(sdat_co2_surface_source, & + my_task = iam, & + logunit = iulog, & + compname = 'ATM', & + model_clock = model_clock, & + model_mesh = model_mesh, & + stream_meshfile = trim(stream_co2_surface_source_mesh_filename), & + stream_filenames = (/trim(stream_co2_surface_source_data_filename)/), & + stream_yearFirst = stream_co2_surface_source_year_first, & + stream_yearLast = stream_co2_surface_source_year_last, & + stream_yearAlign = stream_co2_surface_source_year_align, & + stream_fldlistFile = (/stream_co2_surface_source_data_varname/), & + stream_fldListModel = (/stream_co2_surface_source_data_varname/), & + stream_lev_dimname = 'null', & + stream_mapalgo = 'bilinear', & + stream_offset = 0, & + stream_taxmode = trim(stream_co2_surface_source_taxmode), & + stream_dtlimit = 1.0e30_r8, & + stream_tintalgo = 'linear', & + stream_name = 'CO2_SURFACE_SOURCE data ', & + rc = rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return stream_co2_surface_source_is_initialized = .true. @@ -257,4 +248,4 @@ subroutine stream_co2_surface_source_interp(cam_out, rc) end subroutine stream_co2_surface_source_interp -end module atm_stream_co2_surface_source +end module atm_stream_co2 diff --git a/src/cpl/nuopc/atm_stream_ndep.F90 b/src/cpl/nuopc/atm_stream_ndep.F90 index 6dd92a155d..03fb8a89c0 100644 --- a/src/cpl/nuopc/atm_stream_ndep.F90 +++ b/src/cpl/nuopc/atm_stream_ndep.F90 @@ -13,7 +13,7 @@ module atm_stream_ndep use dshr_strdata_mod , only : shr_strdata_type use shr_kind_mod , only : r8 => shr_kind_r8, CL => shr_kind_cl, CS => shr_kind_cs use shr_log_mod , only : errMsg => shr_log_errMsg - use spmd_utils , only : mpicom, masterproc, iam + use spmd_utils , only : mpicom, masterproc, iam, masterprocid use spmd_utils , only : mpi_character, mpi_integer use cam_logfile , only : iulog use cam_abortutils , only : endrun @@ -68,7 +68,7 @@ subroutine stream_ndep_readnl(nlfile) integer :: ierr ! error status integer :: nf ! field counter integer :: numflds ! number of fields in stream_ndep_varlist - character(*), parameter :: subName = "('stream_ndep_readnl')" + character(len=*), parameter :: subName = "('stream_ndep_readnl')" !----------------------------------------------------------------------- namelist /ndep_stream_nl/ & @@ -106,7 +106,7 @@ subroutine stream_ndep_readnl(nlfile) endif ! Determine if ndep stream is active, and if not return - call mpi_bcast(stream_ndep_data_filename, len(stream_ndep_data_filename), mpi_character, 0, mpicom, ierr) + call mpi_bcast(stream_ndep_data_filename, len(stream_ndep_data_filename), mpi_character, masterprocid, mpicom, ierr) if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_ndep_data_filename") ndep_stream_active = (len_trim(stream_ndep_data_filename)>0 .and. stream_ndep_data_filename/='UNSET') if (.not. ndep_stream_active) then @@ -119,17 +119,17 @@ subroutine stream_ndep_readnl(nlfile) endif ! Broadcast remaining namelist variables - call mpi_bcast(stream_ndep_mesh_filename, len(stream_ndep_mesh_filename), mpi_character, 0, mpicom, ierr) + call mpi_bcast(stream_ndep_mesh_filename, len(stream_ndep_mesh_filename), mpi_character, masterprocid, mpicom, ierr) if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_ndep_mesh_filename") - call mpi_bcast(stream_ndep_varlist, len(stream_ndep_varlist), mpi_character, 0, mpicom, ierr) + call mpi_bcast(stream_ndep_varlist, len(stream_ndep_varlist), mpi_character, masterprocid, mpicom, ierr) if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_ndep_varlist") - call mpi_bcast(stream_ndep_taxmode, len(stream_ndep_taxmode), mpi_character, 0, mpicom, ierr) + call mpi_bcast(stream_ndep_taxmode, len(stream_ndep_taxmode), mpi_character, masterprocid, mpicom, ierr) if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_ndep_taxmode") - call mpi_bcast(stream_ndep_year_first, 1, mpi_integer, 0, mpicom, ierr) + call mpi_bcast(stream_ndep_year_first, 1, mpi_integer, masterprocid, mpicom, ierr) if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_ndep_year_first") - call mpi_bcast(stream_ndep_year_last, 1, mpi_integer, 0, mpicom, ierr) + call mpi_bcast(stream_ndep_year_last, 1, mpi_integer, masterprocid, mpicom, ierr) if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_ndep_year_last") - call mpi_bcast(stream_ndep_year_align, 1, mpi_integer, 0, mpicom, ierr) + call mpi_bcast(stream_ndep_year_align, 1, mpi_integer, masterprocid, mpicom, ierr) if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_ndep_year_align") ! error check @@ -171,7 +171,7 @@ subroutine stream_ndep_init(rc) integer, intent(out) :: rc ! local variables - character(*), parameter :: subName = "('stream_ndep_init')" + character(len=*), parameter :: subName = "('stream_ndep_init')" !----------------------------------------------------------------------- rc = ESMF_SUCCESS @@ -233,7 +233,7 @@ subroutine stream_ndep_check_units( stream_fldFileName_ndep) integer :: ierr ! error status integer :: err_handling ! temporary character(len=CS) :: ndepunits ! ndep units - character(*), parameter :: subName = "('stream_ndep_check_units')" + character(len=*), parameter :: subName = "('stream_ndep_check_units')" !----------------------------------------------------------------------- call cam_pio_openfile( fileid, trim(stream_fldFileName_ndep), PIO_NOWRITE) @@ -294,7 +294,7 @@ subroutine stream_ndep_interp(cam_out, rc) real(r8), pointer :: dataptr1d_nhx_wet(:) real(r8), pointer :: dataptr1d_noy_dry(:) real(r8), pointer :: dataptr1d_noy_wet(:) - character(*), parameter :: subName = "('stream_ndep_interp')" + character(len=*), parameter :: subName = "('stream_ndep_interp')" !----------------------------------------------------------------------- rc = ESMF_SUCCESS From 62c1b5d78dbb7929b28bbe4b0207425b9c8cdb98 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Fri, 17 Jul 2026 20:54:14 +0200 Subject: [PATCH 7/9] now sending ppm rather than mmol co2 to land/ocean --- src/cpl/nuopc/atm_stream_co2.F90 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cpl/nuopc/atm_stream_co2.F90 b/src/cpl/nuopc/atm_stream_co2.F90 index dfddf958dc..46405f99c6 100644 --- a/src/cpl/nuopc/atm_stream_co2.F90 +++ b/src/cpl/nuopc/atm_stream_co2.F90 @@ -238,10 +238,12 @@ subroutine stream_co2_surface_source_interp(cam_out, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return ! Set output diagnostic co2_surface_source + ! Input data is in [mol/mol] but land and ocean expect to receive [ppm]. + ! Unit conversion is to multiply by 1e6. ig = 1 do lchnk = begchunk,endchunk do icol = 1,get_ncols_p(lchnk) - cam_out(lchnk)%co2diag(icol) = dataptr1d(ig) + cam_out(lchnk)%co2diag(icol) = dataptr1d(ig) * 1.0e6_r8 ig = ig + 1 end do end do From 63e0f35bd6afa180ce82cab4ad76dda25d34087d Mon Sep 17 00:00:00 2001 From: Steve Goldhaber Date: Sun, 19 Jul 2026 21:39:13 +0200 Subject: [PATCH 8/9] Fix character declarations and init logic --- src/cpl/nuopc/atm_stream_co2.F90 | 60 +++++++++++++++++--------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/src/cpl/nuopc/atm_stream_co2.F90 b/src/cpl/nuopc/atm_stream_co2.F90 index 46405f99c6..1c9360ce00 100644 --- a/src/cpl/nuopc/atm_stream_co2.F90 +++ b/src/cpl/nuopc/atm_stream_co2.F90 @@ -6,7 +6,7 @@ module atm_stream_co2 ! interpolation. !----------------------------------------------------------------------- ! - use ESMF , only : ESMF_SUCCESS + use ESMF , only : ESMF_SUCCESS use nuopc_shr_methods , only : chkerr use dshr_strdata_mod , only : shr_strdata_type use shr_kind_mod , only : r8 => shr_kind_r8, CL => shr_kind_cl, CS => shr_kind_cs @@ -57,7 +57,7 @@ subroutine stream_co2_surface_source_readnl(nlfile) integer :: nml_error ! namelist i/o error flag integer :: ierr ! error status integer :: nf ! field counter - character(*), parameter :: subName = "('stream_co2_surface_source_readnl')" + character(len=*), parameter :: subName = "('stream_co2_surface_source_readnl')" !----------------------------------------------------------------------- namelist /co2_surface_source_stream_nl/ & @@ -165,36 +165,38 @@ subroutine stream_co2_surface_source_init(rc) integer, intent(out) :: rc ! local variables - character(*), parameter :: subName = "('stream_co2_surface_source_init')" + character(len=*), parameter :: subName = "('stream_co2_surface_source_init')" !----------------------------------------------------------------------- rc = ESMF_SUCCESS - ! Initialize the cdeps data type sdat_co2_surface_source - call shr_strdata_init_from_inline(sdat_co2_surface_source, & - my_task = iam, & - logunit = iulog, & - compname = 'ATM', & - model_clock = model_clock, & - model_mesh = model_mesh, & - stream_meshfile = trim(stream_co2_surface_source_mesh_filename), & - stream_filenames = (/trim(stream_co2_surface_source_data_filename)/), & - stream_yearFirst = stream_co2_surface_source_year_first, & - stream_yearLast = stream_co2_surface_source_year_last, & - stream_yearAlign = stream_co2_surface_source_year_align, & - stream_fldlistFile = (/stream_co2_surface_source_data_varname/), & - stream_fldListModel = (/stream_co2_surface_source_data_varname/), & - stream_lev_dimname = 'null', & - stream_mapalgo = 'bilinear', & - stream_offset = 0, & - stream_taxmode = trim(stream_co2_surface_source_taxmode), & - stream_dtlimit = 1.0e30_r8, & - stream_tintalgo = 'linear', & - stream_name = 'CO2_SURFACE_SOURCE data ', & - rc = rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - - stream_co2_surface_source_is_initialized = .true. + if (co2_surface_source .and. .not. stream_co2_surface_source_is_initialized) then + ! Initialize the cdeps data type sdat_co2_surface_source + call shr_strdata_init_from_inline(sdat_co2_surface_source, & + my_task = iam, & + logunit = iulog, & + compname = 'ATM', & + model_clock = model_clock, & + model_mesh = model_mesh, & + stream_meshfile = trim(stream_co2_surface_source_mesh_filename), & + stream_filenames = (/trim(stream_co2_surface_source_data_filename)/), & + stream_yearFirst = stream_co2_surface_source_year_first, & + stream_yearLast = stream_co2_surface_source_year_last, & + stream_yearAlign = stream_co2_surface_source_year_align, & + stream_fldlistFile = (/stream_co2_surface_source_data_varname/), & + stream_fldListModel = (/stream_co2_surface_source_data_varname/), & + stream_lev_dimname = 'null', & + stream_mapalgo = 'bilinear', & + stream_offset = 0, & + stream_taxmode = trim(stream_co2_surface_source_taxmode), & + stream_dtlimit = 1.0e30_r8, & + stream_tintalgo = 'linear', & + stream_name = 'CO2_SURFACE_SOURCE data ', & + rc = rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + stream_co2_surface_source_is_initialized = .true. + end if end subroutine stream_co2_surface_source_init @@ -220,7 +222,7 @@ subroutine stream_co2_surface_source_interp(cam_out, rc) integer :: sec ! seconds into current date for nstep+1 integer :: mcdate ! Current model date (yyyymmdd) real(r8), pointer :: dataptr1d(:) - character(*), parameter :: subName = "('stream_co2_surface_source_interp')" + character(len=*), parameter :: subName = "('stream_co2_surface_source_interp')" !----------------------------------------------------------------------- rc = ESMF_SUCCESS From 550f2e2ea2aa067c011c9909355d9fa1bf6727ea Mon Sep 17 00:00:00 2001 From: Steve Goldhaber Date: Mon, 20 Jul 2026 09:38:36 +0200 Subject: [PATCH 9/9] Fix logic bug introduced by following reviewer change request --- src/cpl/nuopc/atm_stream_co2.F90 | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/cpl/nuopc/atm_stream_co2.F90 b/src/cpl/nuopc/atm_stream_co2.F90 index 1c9360ce00..c6f8d6e178 100644 --- a/src/cpl/nuopc/atm_stream_co2.F90 +++ b/src/cpl/nuopc/atm_stream_co2.F90 @@ -96,14 +96,16 @@ subroutine stream_co2_surface_source_readnl(nlfile) close(nu_nml) ! Error check - if ( trim(stream_co2_surface_source_taxmode) /= 'cycle' .and. & - trim(stream_co2_surface_source_taxmode) /= 'extend' .and. & - trim(stream_co2_surface_source_taxmode) /= 'limit') then - call endrun(subName//': ERROR stream_co2_surface_source_taxmode '& - //trim(stream_co2_surface_source_taxmode)& - //' must be either cycle, extend or limit') + if (co2_surface_source) then + if ( trim(stream_co2_surface_source_taxmode) /= 'cycle' .and. & + trim(stream_co2_surface_source_taxmode) /= 'extend' .and. & + trim(stream_co2_surface_source_taxmode) /= 'limit') then + call endrun(subName//': ERROR stream_co2_surface_source_taxmode ' & + //trim(stream_co2_surface_source_taxmode) & + //' must be either cycle, extend or limit') + end if end if - endif + end if call mpi_bcast(co2_surface_source, 1, mpi_logical, masterprocid, mpicom, ierr) if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: co2_surface_source") @@ -153,7 +155,7 @@ subroutine stream_co2_surface_source_readnl(nlfile) else write(iulog, '(2a)') subname, 'co2 surface source will not be overwritten' end if - endif + end if end subroutine stream_co2_surface_source_readnl