From 7d763470714093c57e21044ba5de1dc09b68eae9 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Mon, 16 Sep 2024 09:11:39 +0200 Subject: [PATCH 01/16] first set of changes --- cesm/mod_cesm.F90 | 2 +- cime_config/namelist_definition_blom.xml | 11 +++++ drivers/nuopc/ocn_comp_nuopc.F90 | 52 +++++++++++++++++++----- hamocc/mo_hamocc_init.F90 | 3 +- phy/mod_blom_init.F90 | 4 +- phy/mod_forcing.F90 | 5 ++- phy/mod_rdlim.F90 | 8 +++- phy/mod_swabs.F90 | 3 +- 8 files changed, 70 insertions(+), 18 deletions(-) diff --git a/cesm/mod_cesm.F90 b/cesm/mod_cesm.F90 index 076bef6b..2ced6195 100644 --- a/cesm/mod_cesm.F90 +++ b/cesm/mod_cesm.F90 @@ -33,7 +33,7 @@ module mod_cesm lamult, lasl, ustokes, vstokes, atmco2, atmbrf, & flxdms, flxbrf, & atmn2o, atmnh3, atmnhxdep, atmnoydep, & - use_stream_relaxation + use_stream_relaxation, use_stream_swa use mod_ben02, only: initai, rdcsic, rdctsf, fnlzai use mod_rdcsss, only: rdcsss use mod_idarlx, only: idarlx diff --git a/cime_config/namelist_definition_blom.xml b/cime_config/namelist_definition_blom.xml index 3ee1e529..21e18415 100644 --- a/cime_config/namelist_definition_blom.xml +++ b/cime_config/namelist_definition_blom.xml @@ -647,6 +647,17 @@ if .true., use NUOPC stream relaxation capability + + logical + limits + limits + + .false. + .true. + + if .true., use NUOPC stream swa capability + + real limits diff --git a/drivers/nuopc/ocn_comp_nuopc.F90 b/drivers/nuopc/ocn_comp_nuopc.F90 index 3c101f59..ba5fef13 100644 --- a/drivers/nuopc/ocn_comp_nuopc.F90 +++ b/drivers/nuopc/ocn_comp_nuopc.F90 @@ -51,6 +51,7 @@ module ocn_comp_nuopc use mod_config, only: inst_index, inst_name, inst_suffix use mod_time, only: blom_time use mod_forcing, only: srxday, trxday + use mod_swa, only: swamth, chlopt use mod_constants, only: epsilt use mod_blom_init, only: blom_init use mod_blom_step, only: blom_step @@ -58,6 +59,7 @@ module ocn_comp_nuopc use mod_restart, only: restart_write use ocn_stream_sss, only: ocn_stream_sss_init, ocn_stream_sss_interp use ocn_stream_sst, only: ocn_stream_sst_init, ocn_stream_sst_interp + use ocn_stream_swa, only: ocn_stream_swa_init, ocn_stream_swa_interp #ifdef HAMOCC use mo_control_bgc, only: use_BROMO #endif @@ -83,6 +85,13 @@ module ocn_comp_nuopc integer :: flds_scalar_index_ny = 0 integer :: flds_scalar_index_precip_factor = 0 +#ifdef HAMOCC + logical :: hamocc_defined = .true. +#else + logical :: hamocc_defined = .false. + logical :: use_BROMO = .false. +#endif + integer :: dbug = 0 logical :: profile_memory = .false. @@ -379,17 +388,6 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) logical :: isPresent, isSet logical :: ocn2glc_coupling logical :: flds_co2a, flds_co2c, flds_dms, flds_brf - logical :: hamocc_defined -#ifndef HAMOCC - logical :: use_BROMO -#endif - -#ifdef HAMOCC - hamocc_defined = .true. -#else - hamocc_defined = .false. - use_BROMO = .false. -#endif ! Get debug flag. call NUOPC_CompAttributeGet(gcomp, name='dbug_flag', value=cvalue, & @@ -745,6 +743,26 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) if (ChkErr(rc, __LINE__, u_FILE_u)) return end if + ! Initialize sdat for chlorophyll concentration if appropriate + if (swamth == 'chlorophyll') then + if (chlopt == 'climatology') then + call ocn_stream_chloro_init(Emesh, clock, rc) + if (ChkErr(rc, __LINE__, u_FILE_u)) return + else + if (mnproc == 1) then + write (lp,'(3a)') ' chlopt = ',trim(chlopt),' is unsupported!' + end if + call xcstop('(iniswa)') + stop '(iniswa)' + end if + end if + + ! Initialize sdat for swa climatology if appropriate + if (hamocc_defined) then + call ocn_stream_swa_init(Emesh, clock, rc) + if (ChkErr(rc, __LINE__, u_FILE_u)) return + end if + if (dbug > 5) call ESMF_LogWrite(subname//': done', ESMF_LOGMSG_INFO) end subroutine InitializeRealize @@ -907,6 +925,18 @@ subroutine ModelAdvance(gcomp, rc) if (ChkErr(rc, __LINE__, u_FILE_u)) return end if + ! Advance chlorophyll stream input if appropriate + if (swamth == 'chlorophyll' .and. chlopt == 'climatology') then + call ocn_stream_chloro_interp(clock, rc) + if (ChkErr(rc, __LINE__, u_FILE_u)) return + end if + + ! Advance swa stream input if appropriate + if (hamocc_defined) then + call ocn_stream_swa_interp(clock, rc) + if (ChkErr(rc, __LINE__, u_FILE_u)) return + end if + ! Advance the model a time step. call blom_step diff --git a/hamocc/mo_hamocc_init.F90 b/hamocc/mo_hamocc_init.F90 index edc7c60d..11a8bbeb 100644 --- a/hamocc/mo_hamocc_init.F90 +++ b/hamocc/mo_hamocc_init.F90 @@ -38,6 +38,7 @@ subroutine hamocc_init(read_rest,rstfnm_hamocc) use mod_time, only: date,baclin use mod_xc, only: ii,jj,kk,idm,jdm,kdm,nbdy,isp,ifp,ilp,mnproc,lp,xchalt use mod_grid, only: plon,plat + use mod_forcing, only: use_stream_swa use mod_tracers, only: ntrbgc,ntr,itrbgc,trc use mo_control_bgc, only: bgc_namelist,get_bgc_namelist,do_ndep,do_rivinpt,do_oalk, & do_sedspinup,sedspin_yr_s,sedspin_yr_e,sedspin_ncyc, & @@ -201,7 +202,7 @@ subroutine hamocc_init(read_rest,rstfnm_hamocc) call ini_read_ndep(idm,jdm) call ini_read_rivin(idm,jdm,omask) call ini_read_oafx(idm,jdm,bgc_dx,bgc_dy,plat,omask) - if (use_BROMO) then + if (use_BROMO .and. .not. use_stream_swa) then call ini_swa_clim(idm,jdm,omask) endif call ini_pi_ph(idm,jdm,omask) diff --git a/phy/mod_blom_init.F90 b/phy/mod_blom_init.F90 index 1381a22d..cde3bcdd 100644 --- a/phy/mod_blom_init.F90 +++ b/phy/mod_blom_init.F90 @@ -150,7 +150,9 @@ subroutine blom_init() ! Initialize shortwave radiation absorption ! ------------------------------------------------------------------ - call iniswa + if (.not. use_stream_swa) then + call iniswa + end if ! ------------------------------------------------------------------ ! Initialize second order turbulence closure closure diff --git a/phy/mod_forcing.F90 b/phy/mod_forcing.F90 index f5339acb..ecec1143 100644 --- a/phy/mod_forcing.F90 +++ b/phy/mod_forcing.F90 @@ -98,6 +98,8 @@ module mod_forcing sss_stream ! Sea-surface salinity [g kg-1] from stream data. logical :: use_stream_relaxation ! If true, use nuopc stream relaxation capability + logical :: use_stream_chloro ! If true, use nuopc stream chlorophyll capability + logical :: use_stream_swa ! If true, use nuopc stream swa capability ! Variables related to balancing the freshwater forcing budget. real(r8) :: & @@ -182,7 +184,8 @@ module mod_forcing surflx, surrlx, sswflx, salflx, brnflx, salrlx, taux, tauy, & ustar, ustarb, ustar3, wstar3, buoyfl, t_sw_nonloc, t_rs_nonloc, & s_br_nonloc, s_rs_nonloc, inivar_forcing, fwbbal, & - sss_stream, sst_stream, ice_stream, use_stream_relaxation + sss_stream, sst_stream, ice_stream, & + use_stream_relaxation, use_stream_swa contains diff --git a/phy/mod_rdlim.F90 b/phy/mod_rdlim.F90 index 15134883..8f163453 100644 --- a/phy/mod_rdlim.F90 +++ b/phy/mod_rdlim.F90 @@ -44,7 +44,8 @@ module mod_rdlim wavsrc_param, wavsrc_extern, & trxday, srxday, trxdpt, srxdpt, trxlim, & srxlim, srxbal, sprfac, & - srxlim, srxbal, sprfac, use_stream_relaxation + srxlim, srxbal, sprfac, & + use_stream_relaxation, use_stream_swa use mod_swabs, only: swamth, jwtype, chlopt, ccfile use mod_diffusion, only: readnml_diffusion use mod_eddtra, only: mlrmth, ce, cl, tau_mlr, tau_growing_hbl, & @@ -143,7 +144,8 @@ subroutine rdlim() itest,jtest, & cnsvdi, & csdiag, & - rstfrq,rstfmt,rstcmp,iotype,use_stream_relaxation + rstfrq,rstfmt,rstcmp,iotype,& + use_stream_relaxation, use_stream_swa ! read limits namelist @@ -248,6 +250,7 @@ subroutine rdlim() write (lp,*) 'RSTCMP',RSTCMP write (lp,*) 'IOTYPE',IOTYPE write (lp,*) 'USE_STREAM_RELAXATION',use_stream_relaxation + write (lp,*) 'USE_STREAM_SWA',use_stream_swa write (lp,*) end if @@ -331,6 +334,7 @@ subroutine rdlim() call xcbcst(rstcmp) call xcbcst(iotype) call xcbcst(use_stream_relaxation) + call xcbcst(use_stream_swa) ! resolve options select case (trim(wavsrc)) diff --git a/phy/mod_swabs.F90 b/phy/mod_swabs.F90 index e0416dd2..b7fcab99 100644 --- a/phy/mod_swabs.F90 +++ b/phy/mod_swabs.F90 @@ -55,6 +55,7 @@ module mod_swabs use mod_time, only: xmi, l1mi, l2mi, l3mi, l4mi, l5mi use mod_checksum, only: csdiag, chksummsk use mod_intp1d, only: intp1d + use mod_forcing, only: use_stream_swa use netcdf implicit none @@ -181,7 +182,7 @@ subroutine iniswa() end do !$omp end parallel do - else if (swamth == 'chlorophyll') then + else if (swamth == 'chlorophyll' .and. .not. use_stream_swa) then ! Initialize functionality for chlorophyll concentration dependent ! shortwave radiation absorption. From 28f0690ea31972a0202b257ef0cedccb0d8f7b98 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Mon, 16 Sep 2024 20:25:53 +0200 Subject: [PATCH 02/16] added streams for chloro, dust and swa --- cime_config/namelist_definition_blom.xml | 209 ++++++++++++++--- drivers/nuopc/ocn_comp_nuopc.F90 | 78 ++++--- drivers/nuopc/ocn_stream_chloro.F90 | 268 ++++++++++++++++++++++ drivers/nuopc/ocn_stream_dust.F90 | 279 +++++++++++++++++++++++ drivers/nuopc/ocn_stream_sst.F90 | 5 - drivers/nuopc/ocn_stream_swa.F90 | 277 ++++++++++++++++++++++ hamocc/mo_hamocc_step.F90 | 22 +- phy/mod_blom_init.F90 | 1 + phy/mod_forcing.F90 | 11 +- phy/mod_rdlim.F90 | 10 +- 10 files changed, 1078 insertions(+), 82 deletions(-) create mode 100644 drivers/nuopc/ocn_stream_chloro.F90 create mode 100644 drivers/nuopc/ocn_stream_dust.F90 create mode 100644 drivers/nuopc/ocn_stream_swa.F90 diff --git a/cime_config/namelist_definition_blom.xml b/cime_config/namelist_definition_blom.xml index 21e18415..94b6b77c 100644 --- a/cime_config/namelist_definition_blom.xml +++ b/cime_config/namelist_definition_blom.xml @@ -636,28 +636,6 @@ - - logical - limits - limits - - .false. - .true. - - if .true., use NUOPC stream relaxation capability - - - - logical - limits - limits - - .false. - .true. - - if .true., use NUOPC stream swa capability - - real limits @@ -3820,6 +3798,16 @@ Switch for M4AGO settling scheme + + logical + bgcnml + bgcnml + + .false. + + Switch for cyano-bluefix in euphotic zone only + + logical bgcnml @@ -4146,17 +4134,6 @@ add desc - - logical - config_bgc - config_bgc - - .true. - .false. - - activate the HAMOCC preformed tracers code - - @@ -8699,6 +8676,28 @@ + + logical + limits + limits + + .false. + .true. + + if .true., use NUOPC stream relaxation capability + + + + logical + limits + limits + + .false. + .true. + + if .true., use NUOPC stream swabs capability + + char stream_sss @@ -8835,4 +8834,148 @@ + + + + + + char + stream_swa + stream_swa + stream mesh file + + $DIN_LOC_ROOT/share/meshes/tnx1v4_20170601_cdf5_ESMFmesh.nc + + + + char(10) + stream_swa + stream_swa + + file name(s) containing salinity relaxation data + + + $DIN_LOC_ROOT/ocn/blom/bndcon/swa_clim_core_tnx0.25v4_20240512_cdf5.nc + + + + char + stream_swa + stream_swa + + variable name on stream file + + + swa + + + + integer + stream_swa + stream_swa + + First year in stream to use + + + 1 + + + + integer + stream_swa + stream_swa + + Last year in stream to use + + + 1 + + + + integer + stream_swa + stream_swa + + Align stream_year_first with this model year + + + 1 + + + + + + + + + char + stream_dust + stream_dust + stream mesh file + + $DIN_LOC_ROOT/share/meshes/tnx2v1_20230815_cdf5_ESMFmesh.nc + $DIN_LOC_ROOT/share/meshes/tnx1v4_20170601_cdf5_ESMFmesh.nc + $DIN_LOC_ROOT/share/meshes/tnx0.25v4_ESMFmesh_cdf5_c20231006.nc + FILL_THIS_IN + + + + char(10) + stream_dust + stream_dust + + file name(s) containing dust deposition data + + + $DIN_LOC_ROOT/ocn/blom/bndcon/dustdep_mhw2006_tnx2v1_20130506.nc + $DIN_LOC_ROOT/ocn/blom/bndcon/dustdep_mhw2006_tnx1v4_20171107.nc + $DIN_LOC_ROOT/ocn/blom/bndcon/dustdep_mhw2006_tnx0.25v4_20181004.nc + $DIN_LOC_ROOT/ocn/blom/bndcon/dustdep_mhw2006_tnx0.125v4_20221013.nc + + + + char + stream_dust + stream_dust + + variable name on stream file + + + DUST + + + + integer + stream_dust + stream_dust + + First year in stream to use + + + 1 + + + + integer + stream_dust + stream_dust + + Last year in stream to use + + + 1 + + + + integer + stream_dust + stream_dust + + Align stream_year_first with this model year + + + 1 + + + diff --git a/drivers/nuopc/ocn_comp_nuopc.F90 b/drivers/nuopc/ocn_comp_nuopc.F90 index ba5fef13..c394cc91 100644 --- a/drivers/nuopc/ocn_comp_nuopc.F90 +++ b/drivers/nuopc/ocn_comp_nuopc.F90 @@ -51,7 +51,7 @@ module ocn_comp_nuopc use mod_config, only: inst_index, inst_name, inst_suffix use mod_time, only: blom_time use mod_forcing, only: srxday, trxday - use mod_swa, only: swamth, chlopt + use mod_swabs, only: swamth, chlopt use mod_constants, only: epsilt use mod_blom_init, only: blom_init use mod_blom_step, only: blom_step @@ -60,8 +60,12 @@ module ocn_comp_nuopc use ocn_stream_sss, only: ocn_stream_sss_init, ocn_stream_sss_interp use ocn_stream_sst, only: ocn_stream_sst_init, ocn_stream_sst_interp use ocn_stream_swa, only: ocn_stream_swa_init, ocn_stream_swa_interp + use ocn_stream_dust, only: ocn_stream_dust_init, ocn_stream_dust_interp + use ocn_stream_chloro, only: ocn_stream_chloro_init, ocn_stream_chloro_interp + use mod_xc, only: mnproc, xcstop #ifdef HAMOCC use mo_control_bgc, only: use_BROMO + use mo_intfcblom, only: omask #endif implicit none @@ -85,13 +89,6 @@ module ocn_comp_nuopc integer :: flds_scalar_index_ny = 0 integer :: flds_scalar_index_precip_factor = 0 -#ifdef HAMOCC - logical :: hamocc_defined = .true. -#else - logical :: hamocc_defined = .false. - logical :: use_BROMO = .false. -#endif - integer :: dbug = 0 logical :: profile_memory = .false. @@ -542,14 +539,14 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) if (ChkErr(rc, __LINE__, u_FILE_u)) return if (isPresent .and. isSet) then read(cvalue,*) flds_dms - if (.not. hamocc_defined) then - ! if not defined HAMOCC and request to export dms, abort - if (flds_dms) then - write(lp,'(a)') subname//' cannot export dms with out HAMOCC defined' - call xchalt(subname) - stop subname - end if + ! if not defined HAMOCC and request to export dms, abort + if (flds_dms) then +#ifndef HAMOCC + write(lp,'(a)') subname//' cannot export dms with out HAMOCC defined' + call xchalt(subname) + stop subname end if +#endif else flds_dms = .false. end if @@ -562,22 +559,22 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) if (ChkErr(rc, __LINE__, u_FILE_u)) return if (isPresent .and. isSet) then read(cvalue,*) flds_brf - if (hamocc_defined) then - ! make sure that use_BROMO is true if ask for bromoform to be sent to mediator - if (flds_brf .and. .not. use_BROMO) then - write(lp,'(a)') subname//' cannot export bromoform if use_BROMO is not true' - call xchalt(subname) - stop subname - end if - else - ! if not defined HAMOCC and request to export brf, abort - if (flds_brf) then - write(lp,'(a)') subname//' cannot export bromoform with out HAMOCC defined' - call xchalt(subname) - stop subname - end if +#ifdef HAMOCC + ! make sure that use_BROMO is true if ask for bromoform to be sent to mediator + if (flds_brf .and. .not. use_BROMO) then + write(lp,'(a)') subname//' cannot export bromoform if use_BROMO is not true' + call xchalt(subname) + stop subname + end if +#else + ! if not defined HAMOCC and request to export brf, abort + if (flds_brf) then + write(lp,'(a)') subname//' cannot export bromoform with out HAMOCC defined' + call xchalt(subname) + stop subname end if end if +#endif write(msg,'(a,l1)') subname//': export brf ', flds_brf call blom_logwrite(msg) @@ -757,11 +754,16 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) end if end if +#ifdef HAMOCC ! Initialize sdat for swa climatology if appropriate - if (hamocc_defined) then - call ocn_stream_swa_init(Emesh, clock, rc) - if (ChkErr(rc, __LINE__, u_FILE_u)) return + call ocn_stream_swa_init(Emesh, clock, rc) + if (ChkErr(rc, __LINE__, u_FILE_u)) return + + ! Initialize sdat for dust deposition climatology if appropriate + call ocn_stream_dust_init(Emesh, clock, rc) + if (ChkErr(rc, __LINE__, u_FILE_u)) return end if +#endif if (dbug > 5) call ESMF_LogWrite(subname//': done', ESMF_LOGMSG_INFO) @@ -931,11 +933,15 @@ subroutine ModelAdvance(gcomp, rc) if (ChkErr(rc, __LINE__, u_FILE_u)) return end if +#ifdef HAMOCC ! Advance swa stream input if appropriate - if (hamocc_defined) then - call ocn_stream_swa_interp(clock, rc) - if (ChkErr(rc, __LINE__, u_FILE_u)) return - end if + call ocn_stream_swa_interp(clock, omask, rc) + if (ChkErr(rc, __LINE__, u_FILE_u)) return + + ! Advance dust stream input if appropriate + call ocn_stream_dust_interp(clock, omask, rc) + if (ChkErr(rc, __LINE__, u_FILE_u)) return +#endif ! Advance the model a time step. call blom_step diff --git a/drivers/nuopc/ocn_stream_chloro.F90 b/drivers/nuopc/ocn_stream_chloro.F90 new file mode 100644 index 00000000..3a9fe6cb --- /dev/null +++ b/drivers/nuopc/ocn_stream_chloro.F90 @@ -0,0 +1,268 @@ +module ocn_stream_chloro + + !----------------------------------------------------------------------- + ! Contains methods for reading in chlorophyll forcing file + !----------------------------------------------------------------------- + ! + use ESMF , only : ESMF_Clock, ESMF_Mesh, ESMF_Time, ESMF_ClockGet, ESMF_TimeGet + 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 shr_sys_mod , only : shr_sys_abort + use mod_fill_global , only : fill_global + use mod_xc + + implicit none + private + + public :: ocn_stream_chloro_init ! position datasets for dynamic chloro + public :: ocn_stream_chloro_interp ! interpolates between two years of chloro file data + + type(shr_strdata_type) :: sdat_chloro ! input data stream + character(len=CS) :: stream_chloro_varname = '' + + ! Array to store chloro flux after reading from file + real, allocatable, public :: chloro_stream(:,:) + + integer, parameter :: nfiles_max = 100 ! maximum number of stream files + character(len=*), parameter :: sourcefile = & + __FILE__ + +!============================================================================== +contains +!============================================================================== + + subroutine ocn_stream_chloro_init(model_mesh, model_clock, rc) + ! + ! Initialize data stream information. + + ! Uses + use shr_nl_mod , only: shr_nl_find_group_name + use dshr_strdata_mod , only: shr_strdata_init_from_inline + + ! input/output variables + type(ESMF_CLock), intent(in) :: model_clock + type(ESMF_Mesh) , intent(in) :: model_mesh + integer , intent(out) :: rc + + ! local variables + integer :: nu_nml ! unit for namelist file + integer :: nml_error ! namelist i/o error flag + integer :: ierr ! error status + character(len=CL) :: filein ! ocn namelist file + integer :: stream_chloro_year_first ! first year in stream to use + integer :: stream_chloro_year_last ! last year in stream to use + integer :: stream_chloro_year_align ! align stream_year_firstchloro with + character(len=CL) :: stream_chloro_mesh_filename + character(len=CL) :: stream_chloro_data_filename(nfiles_max) + character(len=CL), allocatable :: stream_filenames(:) + character(len=4) :: tmpchar + integer :: nfiles + integer :: nf + integer :: errstat + character(*), parameter :: subName = "('ocn_stream_chloro_init')" + !----------------------------------------------------------------------- + + namelist /stream_chloro/ & + stream_chloro_data_filename, & + stream_chloro_mesh_filename, & + stream_chloro_varname, & + stream_chloro_year_first, & + stream_chloro_year_last, & + stream_chloro_year_align + + rc = ESMF_SUCCESS + + ! Default values for namelist + stream_chloro_data_filename(:) = ' ' + stream_chloro_mesh_filename = ' ' + stream_chloro_varname = ' ' + stream_chloro_year_first = 1 ! first year in stream to use + stream_chloro_year_last = 1 ! last year in stream to use + stream_chloro_year_align = 1 ! align stream_chloro_year_first with this model year + + ! Read stream_chloro namelist + if (mnproc == 1) then + filein = "ocn_in" + open( newunit=nu_nml, file=trim(filein), status='old', iostat=nml_error ) + if (nml_error /= 0) then + call shr_sys_abort(subName//': ERROR opening '//trim(filein)//errMsg(sourcefile, __LINE__)) + end if + call shr_nl_find_group_name(nu_nml, 'stream_chloro', status=nml_error) + if (nml_error == 0) then + read(nu_nml, nml=stream_chloro, iostat=nml_error) + if (nml_error /= 0) then + call shr_sys_abort(' ERROR reading stream_chloro namelist: '//errMsg(sourcefile, __LINE__)) + end if + else + call shr_sys_abort(' ERROR finding stream_chloro namelist: '//errMsg(sourcefile, __LINE__)) + end if + close(nu_nml) + endif + + do nf = 1,nfiles_max + call xcbcst(stream_chloro_data_filename(nf)) + end do + call xcbcst(stream_chloro_mesh_filename) + call xcbcst(stream_chloro_varname) + call xcbcst(stream_chloro_year_first) + call xcbcst(stream_chloro_year_last) + call xcbcst(stream_chloro_year_align) + + ! Determine the actual number and filenames of stream files that will be used + nfiles = 0 + do nf = 1,nfiles_max + if (stream_chloro_data_filename(nf) == '') then + exit + else + nfiles = nfiles + 1 + end if + end do + allocate(stream_filenames(nfiles), stat=errstat) + if (errstat /= 0) then + write(lp,*) 'Failed to allocate stream_filenames' + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + end if + do nf = 1,nfiles + stream_filenames(nf) = trim(stream_chloro_data_filename(nf)) + end do + + ! Write out info + if (mnproc == 1) then + write(lp,'(a)' ) ' ' + write(lp,'(a,i8)') 'stream chloro settings:' + do nf = 1,nfiles + write(tmpchar,'(i0)') nf + write(lp,'(a,a)' ) ' stream_chloro_data_filename('//trim(tmpchar)//') = ',trim(stream_filenames(nf)) + end do + write(lp,'(a,a)' ) ' stream_chloro_mesh_filename = ',trim(stream_chloro_mesh_filename) + write(lp,'(a,a,a)') ' stream_chloro_varname = ',trim(stream_chloro_varname) + write(lp,'(a,i8)') ' stream_chloro_year_first = ',stream_chloro_year_first + write(lp,'(a,i8)') ' stream_chloro_year_last = ',stream_chloro_year_last + write(lp,'(a,i8)') ' stream_chloro_year_align = ',stream_chloro_year_align + write(lp,'(a)' ) ' ' + endif + + ! Initialize the cdeps data type sdat_chloro + call shr_strdata_init_from_inline(sdat_chloro, & + my_task = mnproc, & + logunit = lp, & + compname = 'OCN', & + model_clock = model_clock, & + model_mesh = model_mesh, & + stream_meshfile = trim(stream_chloro_mesh_filename), & + stream_filenames = stream_filenames, & + stream_yearFirst = stream_chloro_year_first, & + stream_yearLast = stream_chloro_year_last, & + stream_yearAlign = stream_chloro_year_align, & + stream_fldlistFile = (/stream_chloro_varname/), & + stream_fldlistModel = (/stream_chloro_varname/), & + stream_lev_dimname = 'null', & + stream_mapalgo = 'bilinear', & + stream_offset = 0, & + stream_taxmode = 'cycle', & + stream_dtlimit = 1.0e30_r8, & + stream_tintalgo = 'linear', & + stream_name = 'Chlorophyll concentration', & + rc = rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + + ! allocate field to hold chloro fields + if (mnproc == 1) then + write(lp,'(a)')'Memory allocation for variable chloro_stream ...' + write(lp,'(a,i10)')'First dimension : ',idm + write(lp,'(a,i10)')'Second dimension : ',jdm + endif + allocate (chloro_stream(idm,jdm),stat=errstat) + if (errstat /= 0) stop 'not enough memory chloro_stream' + chloro_stream(:,:) = 0.0 + + end subroutine ocn_stream_chloro_init + + !================================================================ + subroutine ocn_stream_chloro_interp(model_clock, rc) + + use dshr_strdata_mod , only : shr_strdata_advance + use dshr_methods_mod , only : dshr_fldbun_getfldptr + use mod_checksum , only : csdiag, chksummsk + + ! input/output variables + type(ESMF_Clock), intent(in) :: model_clock + integer , intent(out) :: rc + + ! local variables + type(ESMF_Time) :: date + integer :: i,j,n + integer :: jjcpl + 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 :: dataptr1(:) + real(r8), pointer :: dataptr2(:) + real(r8), parameter :: mval = -1.e12_r8 + real(r8), parameter :: fval = -1.e13_r8 + !----------------------------------------------------------------------- + + ! Advance sdat stream + call ESMF_ClockGet( model_clock, currTime=date, rc=rc ) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + call ESMF_TimeGet(date, yy=year, mm=mon, dd=day, s=sec, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + mcdate = year*10000 + mon*100 + day + + call shr_strdata_advance(sdat_chloro, ymd=mcdate, tod=sec, logunit=lp, istr='chlorodyn', rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + + ! Get pointer for stream data that is time and spatially interpolated to model time and grid + call dshr_fldbun_getFldPtr(sdat_chloro%pstrm(1)%fldbun_model, stream_chloro_varname, fldptr1=dataptr1, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + + ! Set the j-extent of the local ocean domain to be exchanged. Needed because of + ! duplication of the last global domain row when using a tripolar grid. + ! dimensions.F is created at build time by the bash script blom_dimensions and contains + if (nreg == 2 .and. nproc == jpr) then + jjcpl = jj - 1 + else + jjcpl = jj + endif + + do j = 1, jjcpl + do i = 1, ii + if (ip(i,j) == 0) then + chloro_stream(i,j) = mval + elseif (cplmsk(i,j) == 0) then + chloro_stream(i,j) = fval + else + n = (j - 1)*ii + i + chloro_stream(i,j) = dataptr1(n) + end if + end do + end do + + if (csdiag) then + if (mnproc == 1) then + write(lp,*) 'ocn_stream_chloro_interp:' + end if + call chksummsk(chloro_stream(1-nbdy,1-nbdy),ip,1,'chloro_stream') + end if + + end subroutine ocn_stream_chloro_interp + +end module ocn_stream_chloro diff --git a/drivers/nuopc/ocn_stream_dust.F90 b/drivers/nuopc/ocn_stream_dust.F90 new file mode 100644 index 00000000..e5b50b3a --- /dev/null +++ b/drivers/nuopc/ocn_stream_dust.F90 @@ -0,0 +1,279 @@ +module ocn_stream_dust + + !----------------------------------------------------------------------- + ! Contains methods for reading in dust forcing file + !----------------------------------------------------------------------- + ! + use ESMF , only : ESMF_Clock, ESMF_Mesh, ESMF_Time, ESMF_ClockGet, ESMF_TimeGet + 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 shr_sys_mod , only : shr_sys_abort + use mod_xc + + implicit none + private + + public :: ocn_stream_dust_init ! position datasets for dynamic dust + public :: ocn_stream_dust_interp ! interpolates between two years of dust file data + + type(shr_strdata_type) :: sdat_dust ! input data stream + character(len=CS) :: stream_dust_varname='DUST' + + ! Array to store dust flux after reading from file + real, allocatable, public :: dust_stream(:,:) + + integer, parameter :: nfiles_max = 100 ! maximum number of stream files + character(len=*), parameter :: sourcefile = & + __FILE__ + +!============================================================================== +contains +!============================================================================== + + subroutine ocn_stream_dust_init(model_mesh, model_clock, rc) + ! + ! Initialize data stream information. + + ! Uses + use shr_nl_mod , only: shr_nl_find_group_name + use dshr_strdata_mod , only: shr_strdata_init_from_inline + + ! input/output variables + type(ESMF_CLock), intent(in) :: model_clock + type(ESMF_Mesh) , intent(in) :: model_mesh + integer , intent(out) :: rc + + ! local variables + integer :: nu_nml ! unit for namelist file + integer :: nml_error ! namelist i/o error flag + integer :: ierr ! error status + character(len=CL) :: filein ! ocn namelist file + integer :: stream_dust_year_first ! first year in stream to use + integer :: stream_dust_year_last ! last year in stream to use + integer :: stream_dust_year_align ! align stream_year_firstdust with + character(len=CL) :: stream_dust_mesh_filename + character(len=CL) :: stream_dust_data_filename(nfiles_max) + character(len=CL), allocatable :: stream_filenames(:) + character(len=4) :: tmpchar + integer :: nfiles + integer :: nf + integer :: errstat + character(*), parameter :: subName = "('ocn_stream_dust_init')" + !----------------------------------------------------------------------- + + namelist /stream_dust/ & + stream_dust_data_filename, & + stream_dust_mesh_filename, & + stream_dust_varname, & + stream_dust_year_first, & + stream_dust_year_last, & + stream_dust_year_align + + rc = ESMF_SUCCESS + + ! Default values for namelist + stream_dust_data_filename(:) = ' ' + stream_dust_mesh_filename = ' ' + stream_dust_year_first = 1 ! first year in stream to use + stream_dust_year_last = 1 ! last year in stream to use + stream_dust_year_align = 1 ! align stream_dust_year_first with this model year + + ! Read stream_dust namelist + if (mnproc == 1) then + filein = "ocn_in" + open( newunit=nu_nml, file=trim(filein), status='old', iostat=nml_error ) + if (nml_error /= 0) then + call shr_sys_abort(subName//': ERROR opening '//trim(filein)//errMsg(sourcefile, __LINE__)) + end if + call shr_nl_find_group_name(nu_nml, 'stream_dust', status=nml_error) + if (nml_error == 0) then + read(nu_nml, nml=stream_dust, iostat=nml_error) + if (nml_error /= 0) then + call shr_sys_abort(' ERROR reading stream_dust namelist: '//errMsg(sourcefile, __LINE__)) + end if + else + call shr_sys_abort(' ERROR finding stream_dust namelist: '//errMsg(sourcefile, __LINE__)) + end if + close(nu_nml) + endif + + do nf = 1,nfiles_max + call xcbcst(stream_dust_data_filename(nf)) + end do + call xcbcst(stream_dust_mesh_filename) + call xcbcst(stream_dust_varname) + call xcbcst(stream_dust_year_first) + call xcbcst(stream_dust_year_last) + call xcbcst(stream_dust_year_align) + + ! Determine the actual number and filenames of stream files that will be used + nfiles = 0 + do nf = 1,nfiles_max + if (stream_dust_data_filename(nf) == '') then + exit + else + nfiles = nfiles + 1 + end if + end do + allocate(stream_filenames(nfiles), stat=errstat) + if (errstat /= 0) then + write(lp,*) 'Failed to allocate stream_filenames' + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + end if + do nf = 1,nfiles + stream_filenames(nf) = trim(stream_dust_data_filename(nf)) + end do + + ! Write out info + if (mnproc == 1) then + write(lp,'(a)' ) ' ' + write(lp,'(a,i8)') 'stream dust settings:' + do nf = 1,nfiles + write(tmpchar,'(i0)') nf + write(lp,'(a,a)' ) ' stream_dust_data_filename('//trim(tmpchar)//') = ',trim(stream_filenames(nf)) + end do + write(lp,'(a,a)' ) ' stream_dust_mesh_filename = ',trim(stream_dust_mesh_filename) + write(lp,'(a,a,a)') ' stream_dust_varname = ',trim(stream_dust_varname) + write(lp,'(a,i8)') ' stream_dust_year_first = ',stream_dust_year_first + write(lp,'(a,i8)') ' stream_dust_year_last = ',stream_dust_year_last + write(lp,'(a,i8)') ' stream_dust_year_align = ',stream_dust_year_align + write(lp,'(a)' ) ' ' + endif + + ! Initialize the cdeps data type sdat_dust + call shr_strdata_init_from_inline(sdat_dust, & + my_task = mnproc, & + logunit = lp, & + compname = 'OCN', & + model_clock = model_clock, & + model_mesh = model_mesh, & + stream_meshfile = trim(stream_dust_mesh_filename), & + stream_filenames = stream_filenames, & + stream_yearFirst = stream_dust_year_first, & + stream_yearLast = stream_dust_year_last, & + stream_yearAlign = stream_dust_year_align, & + stream_fldlistFile = (/stream_dust_varname/), & + stream_fldlistModel = (/stream_dust_varname/), & + stream_lev_dimname = 'null', & + stream_mapalgo = 'bilinear', & + stream_offset = 0, & + stream_taxmode = 'cycle', & + stream_dtlimit = 1.0e30_r8, & + stream_tintalgo = 'linear', & + stream_name = 'Dust Deposition', & + rc = rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + + ! allocate field to hold dust fields + if (mnproc == 1) then + write(lp,'(a)')'Memory allocation for variable dust_stream ...' + write(lp,'(a,i10)')'First dimension : ',idm + write(lp,'(a,i10)')'Second dimension : ',jdm + endif + allocate (dust_stream(jdm,idm),stat=errstat) + if (errstat /= 0) then + stop 'not enough memory dust_stream' + end if + dust_stream(:,:) = 0.0 + + end subroutine ocn_stream_dust_init + + !================================================================ + subroutine ocn_stream_dust_interp(model_clock, omask, rc) + + use dshr_strdata_mod , only : shr_strdata_advance + use dshr_methods_mod , only : dshr_fldbun_getfldptr + use mod_forcing , only : dust_stream + use mod_checksum , only : csdiag, chksummsk + + ! input/output variables + type(ESMF_Clock), intent(in) :: model_clock + real , intent(in) :: omask(:,:) ! land/ocean mask (1=ocean) + integer , intent(out) :: rc + + ! local variables + type(ESMF_Time) :: date + integer :: i,j,n + integer :: jjcpl + 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 :: dataptr1(:) + real(r8), parameter :: mval = -1.e12_r8 + real(r8), parameter :: fval = -1.e13_r8 + !----------------------------------------------------------------------- + + ! Advance sdat stream + call ESMF_ClockGet( model_clock, currTime=date, rc=rc ) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + call ESMF_TimeGet(date, yy=year, mm=mon, dd=day, s=sec, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + mcdate = year*10000 + mon*100 + day + + call shr_strdata_advance(sdat_dust, ymd=mcdate, tod=sec, logunit=lp, istr='dust', rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + + ! Get pointer for stream data that is time and spatially interpolated to model time and grid + call dshr_fldbun_getFldPtr(sdat_dust%pstrm(1)%fldbun_model, stream_dust_varname, fldptr1=dataptr1, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + + ! Set the j-extent of the local ocean domain to be exchanged. Needed because of + ! duplication of the last global domain row when using a tripolar grid. + ! dimensions.F is created at build time by the bash script blom_dimensions and contains + + if (nreg == 2 .and. nproc == jpr) then + jjcpl = jj - 1 + else + jjcpl = jj + endif + + do j = 1, jjcpl + do i = 1, ii + if (ip(i,j) == 0) then + dust_stream(i,j) = mval + elseif (cplmsk(i,j) == 0) then + dust_stream(i,j) = fval + else + n = (j - 1)*ii + i + dust_stream(i,j) = dataptr1(n) + end if + end do + end do + + if (csdiag) then + if (mnproc == 1) then + write(lp,*) 'ocn_stream_dust_interp:' + end if + call chksummsk(dust_stream,ip,1,'dust_stream') + end if + + ! set flux to zero over land + do j=1,kdm + do i=1,idm + if (omask(i,j) < 0.5) then + dust_stream(i,j) = 0.0 + end if + enddo + enddo + + end subroutine ocn_stream_dust_interp + +end module ocn_stream_dust diff --git a/drivers/nuopc/ocn_stream_sst.F90 b/drivers/nuopc/ocn_stream_sst.F90 index 85e4c439..296bd816 100644 --- a/drivers/nuopc/ocn_stream_sst.F90 +++ b/drivers/nuopc/ocn_stream_sst.F90 @@ -233,11 +233,6 @@ subroutine ocn_stream_sst_interp(model_clock, rc) ! Set the j-extent of the local ocean domain to be exchanged. Needed because of ! duplication of the last global domain row when using a tripolar grid. ! dimensions.F is created at build time by the bash script blom_dimensions and contains - ! the following hard-wired variables - ! nreg - region type - ! nproc - the number of processors - ! ipr - 1st 2-D node dimension (<=iqr) - ! jpr - 2nd 2-D node dimension (<=jqr) if (nreg == 2 .and. nproc == jpr) then jjcpl = jj - 1 diff --git a/drivers/nuopc/ocn_stream_swa.F90 b/drivers/nuopc/ocn_stream_swa.F90 new file mode 100644 index 00000000..45c52744 --- /dev/null +++ b/drivers/nuopc/ocn_stream_swa.F90 @@ -0,0 +1,277 @@ +module ocn_stream_swa + + !----------------------------------------------------------------------- + ! Contains methods for reading in swa forcing file + !----------------------------------------------------------------------- + ! + use ESMF , only : ESMF_Clock, ESMF_Mesh, ESMF_Time, ESMF_ClockGet, ESMF_TimeGet + 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 shr_sys_mod , only : shr_sys_abort + use mod_xc + + implicit none + private + + public :: ocn_stream_swa_init ! position datasets for dynamic swa + public :: ocn_stream_swa_interp ! interpolates between two years of swa file data + + type(shr_strdata_type) :: sdat_swa ! input data stream + character(len=CS) :: stream_swa_varname='swa' + + ! Array to store swa flux after reading from file + real, allocatable, public :: swa_stream(:,:) + + integer, parameter :: nfiles_max = 100 ! maximum number of stream files + character(len=*), parameter :: sourcefile = & + __FILE__ + +!============================================================================== +contains +!============================================================================== + + subroutine ocn_stream_swa_init(model_mesh, model_clock, rc) + ! + ! Initialize data stream information. + + ! Uses + use shr_nl_mod , only: shr_nl_find_group_name + use dshr_strdata_mod , only: shr_strdata_init_from_inline + + ! input/output variables + type(ESMF_CLock), intent(in) :: model_clock + type(ESMF_Mesh) , intent(in) :: model_mesh + integer , intent(out) :: rc + + ! local variables + integer :: nu_nml ! unit for namelist file + integer :: nml_error ! namelist i/o error flag + integer :: ierr ! error status + character(len=CL) :: filein ! ocn namelist file + integer :: stream_swa_year_first ! first year in stream to use + integer :: stream_swa_year_last ! last year in stream to use + integer :: stream_swa_year_align ! align stream_year_firstswa with + character(len=CL) :: stream_swa_mesh_filename + character(len=CL) :: stream_swa_data_filename(nfiles_max) + character(len=CL), allocatable :: stream_filenames(:) + character(len=4) :: tmpchar + integer :: nfiles + integer :: nf + integer :: errstat + character(*), parameter :: subName = "('ocn_stream_swa_init')" + !----------------------------------------------------------------------- + + namelist /stream_swa/ & + stream_swa_data_filename, & + stream_swa_mesh_filename, & + stream_swa_varname, & + stream_swa_year_first, & + stream_swa_year_last, & + stream_swa_year_align + + rc = ESMF_SUCCESS + + ! Default values for namelist + stream_swa_data_filename(:) = ' ' + stream_swa_mesh_filename = ' ' + stream_swa_varname = ' ' + stream_swa_year_first = 1 ! first year in stream to use + stream_swa_year_last = 1 ! last year in stream to use + stream_swa_year_align = 1 ! align stream_swa_year_first with this model year + + ! Read stream_swa namelist + if (mnproc == 1) then + filein = "ocn_in" + open( newunit=nu_nml, file=trim(filein), status='old', iostat=nml_error ) + if (nml_error /= 0) then + call shr_sys_abort(subName//': ERROR opening '//trim(filein)//errMsg(sourcefile, __LINE__)) + end if + call shr_nl_find_group_name(nu_nml, 'stream_swa', status=nml_error) + if (nml_error == 0) then + read(nu_nml, nml=stream_swa, iostat=nml_error) + if (nml_error /= 0) then + call shr_sys_abort(' ERROR reading stream_swa namelist: '//errMsg(sourcefile, __LINE__)) + end if + else + call shr_sys_abort(' ERROR finding stream_swa namelist: '//errMsg(sourcefile, __LINE__)) + end if + close(nu_nml) + endif + + do nf = 1,nfiles_max + call xcbcst(stream_swa_data_filename(nf)) + end do + call xcbcst(stream_swa_mesh_filename) + call xcbcst(stream_swa_varname) + call xcbcst(stream_swa_year_first) + call xcbcst(stream_swa_year_last) + call xcbcst(stream_swa_year_align) + + ! Determine the actual number and filenames of stream files that will be used + nfiles = 0 + do nf = 1,nfiles_max + if (stream_swa_data_filename(nf) == '') then + exit + else + nfiles = nfiles + 1 + end if + end do + allocate(stream_filenames(nfiles), stat=errstat) + if (errstat /= 0) then + write(lp,*) 'Failed to allocate stream_filenames' + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + end if + do nf = 1,nfiles + stream_filenames(nf) = trim(stream_swa_data_filename(nf)) + end do + + ! Write out info + if (mnproc == 1) then + write(lp,'(a)' ) ' ' + write(lp,'(a,i8)') 'stream swa settings:' + do nf = 1,nfiles + write(tmpchar,'(i0)') nf + write(lp,'(a,a)' ) ' stream_swa_data_filename('//trim(tmpchar)//') = ',trim(stream_filenames(nf)) + end do + write(lp,'(a,a)' ) ' stream_swa_mesh_filename = ',trim(stream_swa_mesh_filename) + write(lp,'(a,a,a)') ' stream_swa_varnames = ',trim(stream_swa_varname) + write(lp,'(a,i8)') ' stream_swa_year_first = ',stream_swa_year_first + write(lp,'(a,i8)') ' stream_swa_year_last = ',stream_swa_year_last + write(lp,'(a,i8)') ' stream_swa_year_align = ',stream_swa_year_align + write(lp,'(a)' ) ' ' + endif + + ! Initialize the cdeps data type sdat_swa + call shr_strdata_init_from_inline(sdat_swa, & + my_task = mnproc, & + logunit = lp, & + compname = 'OCN', & + model_clock = model_clock, & + model_mesh = model_mesh, & + stream_meshfile = trim(stream_swa_mesh_filename), & + stream_filenames = stream_filenames, & + stream_yearFirst = stream_swa_year_first, & + stream_yearLast = stream_swa_year_last, & + stream_yearAlign = stream_swa_year_align, & + stream_fldlistFile = (/stream_swa_varname/), & + stream_fldlistModel = (/stream_swa_varname/), & + stream_lev_dimname = 'null', & + stream_mapalgo = 'bilinear', & + stream_offset = 0, & + stream_taxmode = 'cycle', & + stream_dtlimit = 1.0e30_r8, & + stream_tintalgo = 'linear', & + stream_name = 'Shortwave Radiation Absorption', & + rc = rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + + ! allocate field to hold swa fields + if (mnproc == 1) then + write(lp,'(a)')'Memory allocation for variable swa_stream ...' + write(lp,'(a,i10)')'First dimension : ',idm + write(lp,'(a,i10)')'Second dimension : ',jdm + endif + allocate (swa_stream(idm,jdm),stat=errstat) + if(errstat /= 0) stop 'not enough memory swa_stream' + swa_stream(:,:) = 0.0 + + end subroutine ocn_stream_swa_init + + !================================================================ + subroutine ocn_stream_swa_interp(model_clock, omask, rc) + + use dshr_strdata_mod , only : shr_strdata_advance + use dshr_methods_mod , only : dshr_fldbun_getfldptr + use mod_checksum , only : csdiag, chksummsk + + ! input/output variables + type(ESMF_Clock), intent(in) :: model_clock + real , intent(in) :: omask(:,:) ! land/ocean mask (1=ocean) + integer , intent(out) :: rc + + ! local variables + type(ESMF_Time) :: date + integer :: i,j,n + integer :: jjcpl + 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 :: dataptr1(:) + real(r8), parameter :: mval = -1.e12_r8 + real(r8), parameter :: fval = -1.e13_r8 + !----------------------------------------------------------------------- + + ! Advance sdat stream + call ESMF_ClockGet( model_clock, currTime=date, rc=rc ) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + call ESMF_TimeGet(date, yy=year, mm=mon, dd=day, s=sec, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + mcdate = year*10000 + mon*100 + day + + call shr_strdata_advance(sdat_swa, ymd=mcdate, tod=sec, logunit=lp, istr='swa', rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + + ! Get pointer for stream data that is time and spatially interpolated to model time and grid + call dshr_fldbun_getFldPtr(sdat_swa%pstrm(1)%fldbun_model, stream_swa_varname, fldptr1=dataptr1, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + + ! Set the j-extent of the local ocean domain to be exchanged. Needed because of + ! duplication of the last global domain row when using a tripolar grid. + ! dimensions.F is created at build time by the bash script blom_dimensions and contains + + if (nreg == 2 .and. nproc == jpr) then + jjcpl = jj - 1 + else + jjcpl = jj + endif + + do j = 1, jjcpl + do i = 1, ii + if (ip(i,j) == 0) then + swa_stream(i,j) = mval + elseif (cplmsk(i,j) == 0) then + swa_stream(i,j) = fval + else + n = (j - 1)*ii + i + swa_stream(i,j) = dataptr1(n) + end if + end do + end do + + if (csdiag) then + if (mnproc == 1) then + write(lp,*) 'ocn_stream_swa_interp:' + end if + call chksummsk(swa_stream(1-nbdy,1-nbdy),ip,1,'swa_stream') + end if + + ! set flux to zero over land + do j=1,jdm + do i=1,idm + if (omask(i,j) < 0.5) then + swa_stream(i,j) = 0.0 + end if + enddo + enddo + + end subroutine ocn_stream_swa_interp + +end module ocn_stream_swa diff --git a/hamocc/mo_hamocc_step.F90 b/hamocc/mo_hamocc_step.F90 index 39515374..abef42cf 100644 --- a/hamocc/mo_hamocc_step.F90 +++ b/hamocc/mo_hamocc_step.F90 @@ -33,8 +33,9 @@ subroutine hamocc_step(m,n,mm,nn,k1m,k1n) use mod_time, only: date,nday_of_year,nstep,nstep_in_day use mod_grid, only: plat use mod_state, only: temp,saln - use mod_forcing, only: swa,slp,abswnd,atmco2,flxco2,flxdms,atmbrf,flxbrf, & - atmn2o,flxn2o,atmnh3,flxnh3,atmnhxdep,atmnoydep + use mod_forcing, only: swa,slp,abswnd,atmco2,flxco2,flxdms,atmbrf,flxbrf, & + atmn2o,flxn2o,atmnh3,flxnh3,atmnhxdep,atmnoydep, & + use_stream_dust, dust_stream use mod_seaice, only: ficem use mo_bgcmean, only: nbgc,bgcwrt, diagfq_bgc,diagmon_bgc,diagann_bgc use mo_intfcblom, only: bgc_dx,bgc_dy,bgc_dp,bgc_rho,omask,blom2hamocc,hamocc2blom @@ -74,10 +75,23 @@ subroutine hamocc_step(m,n,mm,nn,k1m,k1n) end if enddo - call get_fedep(idm,jdm,date%month,dust) + if (use_stream_dust) then + do j = 1,jdm + do i = 1,idm + dust(i,j) = dust_stream(i,j) + end do + end do + else + call get_fedep(idm,jdm,date%month,dust) + end if + call get_ndep(idm,jdm,nbdy,date%year,date%month,omask,ndep,atmnhxdep,atmnoydep) + call get_oafx(idm,jdm,date%year,date%month,omask,oafx) - if(with_dmsph) call get_pi_ph(idm,jdm,date%month) + + if (with_dmsph) then + call get_pi_ph(idm,jdm,date%month) + end if call hamocc4bcm(idm,jdm,kdm,nbdy,date%year,date%month,date%day,ldtday,bgc_dx,bgc_dy,bgc_dp, & & bgc_rho,plat,omask,dust,rivflx,ndep,oafx,pi_ph,swa,ficem,slp,abswnd, & diff --git a/phy/mod_blom_init.F90 b/phy/mod_blom_init.F90 index cde3bcdd..b9ba2e40 100644 --- a/phy/mod_blom_init.F90 +++ b/phy/mod_blom_init.F90 @@ -65,6 +65,7 @@ subroutine blom_init() use mod_restart, only: restart_read use mod_ifdefs, only: use_TRC, use_TKE use mod_tracers_update, only: initrc + use mod_forcing, only: use_stream_swa use netcdf ! Local variables diff --git a/phy/mod_forcing.F90 b/phy/mod_forcing.F90 index ecec1143..0f977075 100644 --- a/phy/mod_forcing.F90 +++ b/phy/mod_forcing.F90 @@ -96,8 +96,14 @@ module mod_forcing sst_stream, & ! Sea-surface temperature [deg C] from stream data. ice_stream, & ! Sea-ice concentration [] from stream data. sss_stream ! Sea-surface salinity [g kg-1] from stream data. - logical :: use_stream_relaxation ! If true, use nuopc stream relaxation capability + + real(r8), dimension(idm,jdm) :: & + dust_stream, & ! iron dust deposition for hamocc + chloro_stream, & ! chlorophyll concentration + swa_stream ! short wave radiation absorbed + + logical :: use_stream_dust ! If true, use nuopc stream dust capability (hamocc only) logical :: use_stream_chloro ! If true, use nuopc stream chlorophyll capability logical :: use_stream_swa ! If true, use nuopc stream swa capability @@ -185,7 +191,8 @@ module mod_forcing ustar, ustarb, ustar3, wstar3, buoyfl, t_sw_nonloc, t_rs_nonloc, & s_br_nonloc, s_rs_nonloc, inivar_forcing, fwbbal, & sss_stream, sst_stream, ice_stream, & - use_stream_relaxation, use_stream_swa + dust_stream, & + use_stream_relaxation, use_stream_swa, use_stream_dust, use_stream_chloro contains diff --git a/phy/mod_rdlim.F90 b/phy/mod_rdlim.F90 index 8f163453..70ba381a 100644 --- a/phy/mod_rdlim.F90 +++ b/phy/mod_rdlim.F90 @@ -45,7 +45,8 @@ module mod_rdlim trxday, srxday, trxdpt, srxdpt, trxlim, & srxlim, srxbal, sprfac, & srxlim, srxbal, sprfac, & - use_stream_relaxation, use_stream_swa + use_stream_relaxation, use_stream_swa, & + use_stream_chloro, use_stream_dust use mod_swabs, only: swamth, jwtype, chlopt, ccfile use mod_diffusion, only: readnml_diffusion use mod_eddtra, only: mlrmth, ce, cl, tau_mlr, tau_growing_hbl, & @@ -145,7 +146,8 @@ subroutine rdlim() cnsvdi, & csdiag, & rstfrq,rstfmt,rstcmp,iotype,& - use_stream_relaxation, use_stream_swa + use_stream_relaxation, use_stream_swa, use_stream_chloro, & + use_stream_dust ! read limits namelist @@ -251,6 +253,8 @@ subroutine rdlim() write (lp,*) 'IOTYPE',IOTYPE write (lp,*) 'USE_STREAM_RELAXATION',use_stream_relaxation write (lp,*) 'USE_STREAM_SWA',use_stream_swa + write (lp,*) 'USE_STREAM_CHLORO',use_stream_chloro + write (lp,*) 'USE_STREAM_DUST',use_stream_dust write (lp,*) end if @@ -335,6 +339,8 @@ subroutine rdlim() call xcbcst(iotype) call xcbcst(use_stream_relaxation) call xcbcst(use_stream_swa) + call xcbcst(use_stream_chloro) + call xcbcst(use_stream_dust) ! resolve options select case (trim(wavsrc)) From c77fd369ec6272a5cd280a98a13b65d943afa0cc Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Tue, 17 Sep 2024 19:37:42 +0200 Subject: [PATCH 03/16] generalized stream functionality in hamoocc --- cime_config/namelist_definition_blom.xml | 48 +++++++------ drivers/nuopc/mod_output_forcing.F90 | 86 ++++++++++++++++++++++++ drivers/nuopc/ocn_comp_nuopc.F90 | 5 +- drivers/nuopc/ocn_stream_dust.F90 | 37 +++++----- hamocc/mo_hamocc4bcm.F90 | 2 +- hamocc/mo_hamocc_step.F90 | 44 ++++++------ hamocc/mo_read_fedep.F90 | 18 +++-- hamocc/mo_read_ndep.F90 | 58 ++++++++-------- hamocc/mo_read_oafx.F90 | 42 +++++++----- phy/mod_forcing.F90 | 50 +++++++------- 10 files changed, 240 insertions(+), 150 deletions(-) create mode 100644 drivers/nuopc/mod_output_forcing.F90 diff --git a/cime_config/namelist_definition_blom.xml b/cime_config/namelist_definition_blom.xml index 94b6b77c..0b37052b 100644 --- a/cime_config/namelist_definition_blom.xml +++ b/cime_config/namelist_definition_blom.xml @@ -8686,18 +8686,6 @@ if .true., use NUOPC stream relaxation capability - - - logical - limits - limits - - .false. - .true. - - if .true., use NUOPC stream swabs capability - - char stream_sss @@ -8838,6 +8826,17 @@ + + logical + limits + limits + + .false. + .true. + + if .true., use NUOPC stream swabs capability + + char stream_swa @@ -8907,16 +8906,24 @@ + + logical + limits + limits + + .false. + .true. + + if .true., use NUOPC stream dust capability + + char stream_dust stream_dust stream mesh file - $DIN_LOC_ROOT/share/meshes/tnx2v1_20230815_cdf5_ESMFmesh.nc - $DIN_LOC_ROOT/share/meshes/tnx1v4_20170601_cdf5_ESMFmesh.nc - $DIN_LOC_ROOT/share/meshes/tnx0.25v4_ESMFmesh_cdf5_c20231006.nc - FILL_THIS_IN + $DIN_LOC_ROOT/ocn/blom/bndcon/dustdep_mhw2006_T42_ESMFmesh_cdf5.nc @@ -8927,10 +8934,7 @@ file name(s) containing dust deposition data - $DIN_LOC_ROOT/ocn/blom/bndcon/dustdep_mhw2006_tnx2v1_20130506.nc - $DIN_LOC_ROOT/ocn/blom/bndcon/dustdep_mhw2006_tnx1v4_20171107.nc - $DIN_LOC_ROOT/ocn/blom/bndcon/dustdep_mhw2006_tnx0.25v4_20181004.nc - $DIN_LOC_ROOT/ocn/blom/bndcon/dustdep_mhw2006_tnx0.125v4_20221013.nc + $DIN_LOC_ROOT/ocn/blom/bndcon/dustdep_mhw2006_T42.nc @@ -8963,7 +8967,7 @@ Last year in stream to use - 1 + 1850 @@ -8974,7 +8978,7 @@ Align stream_year_first with this model year - 1 + 1850 diff --git a/drivers/nuopc/mod_output_forcing.F90 b/drivers/nuopc/mod_output_forcing.F90 new file mode 100644 index 00000000..aaaeac95 --- /dev/null +++ b/drivers/nuopc/mod_output_forcing.F90 @@ -0,0 +1,86 @@ +module mod_output_forcing + + use netcdf, only: nf90_64bit_offset, nf90_global, nf90_noerr, nf90_nofill, nf90_def_dim, & + nf90_enddef, nf90_close, nf90_create, nf90_strerror, & + nf90_double, nf90_def_var, nf90_put_var, nf90_put_att + use mod_types, only: r8 + use mod_xc + + implicit none + private + + public :: output_forcing + +contains + + subroutine output_forcing(filename, varname, vardata) + + ! Arguments + character(len=*) , intent(in) :: filename + character(len=*) , intent(in) :: varname + real(r8) , intent(in) :: vardata(1-nbdy:idm+nbdy, 1-nbdy:jdm+nbdy) + + ! Local variables + integer :: ncid,ncvarid,ncstat,ncdims(2),nclatid,nclonid + integer :: i,j + integer :: start(2),count(2) + real :: arr_g(itdm,jtdm) + real :: arr_l(1-nbdy:idm+nbdy, 1-nbdy:jdm+nbdy, 1) + + if (mnproc==1) then + write(lp,*) 'creating netcdf file for dust stream' + + ! open file + ncstat = nf90_create('dustdep_stream.nc', NF90_64BIT_OFFSET, ncid) + if ( ncstat /= NF90_NOERR ) then + call xchalt('(cannot open dustdep_stream.nc)'); stop + endif + + ! defined dimensions + ncstat = nf90_def_dim(ncid, 'lon', itdm, nclonid) + if ( ncstat /= NF90_NOERR ) then + call xchalt('(cannot create lon dim)'); stop + endif + ncstat = nf90_def_dim(ncid, 'lat', jtdm, nclatid) + if ( ncstat /= NF90_NOERR ) then + call xchalt('(cannot create lat dim)'); stop + endif + ncdims(1) = nclonid + ncdims(2) = nclatid + + ! define variable + ncstat = NF90_DEF_VAR(ncid, trim(varname), NF90_DOUBLE, ncdims, ncvarid) + if ( ncstat /= NF90_NOERR ) then + call xchalt('(cannot define variable)'); stop + endif + + ncstat = nf90_enddef(ncid) + end if + + arr_l(:,:,:) = 0.0 + start(1) = 1; count(1) = itdm + start(2) = 1; count(2) = jtdm + + do j=1,jdm + do i=1,idm + arr_l(i,j,1) = vardata(i,j) + enddo + enddo + call xcaget(arr_g, arr_l, 1) + + if (mnproc == 1) then + ncstat = nf90_put_var(ncid, ncvarid, arr_g, start, count) + if (ncstat /= nf90_noerr) then + write(lp,'(4a)') 'nf90_put_var: ',trim(varname),': ',nf90_strerror(ncstat) + call xchalt('(write_netcdf_var)'); stop + endif + end if + + ncstat = nf90_close(ncid) + if ( ncstat /= NF90_NOERR ) then + call xchalt('(cannot close file)'); stop + endif + + end subroutine output_forcing + + end module mod_output_forcing diff --git a/drivers/nuopc/ocn_comp_nuopc.F90 b/drivers/nuopc/ocn_comp_nuopc.F90 index c394cc91..e8409a99 100644 --- a/drivers/nuopc/ocn_comp_nuopc.F90 +++ b/drivers/nuopc/ocn_comp_nuopc.F90 @@ -539,9 +539,9 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) if (ChkErr(rc, __LINE__, u_FILE_u)) return if (isPresent .and. isSet) then read(cvalue,*) flds_dms +#ifndef HAMOCC ! if not defined HAMOCC and request to export dms, abort if (flds_dms) then -#ifndef HAMOCC write(lp,'(a)') subname//' cannot export dms with out HAMOCC defined' call xchalt(subname) stop subname @@ -573,8 +573,8 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) call xchalt(subname) stop subname end if - end if #endif + end if write(msg,'(a,l1)') subname//': export brf ', flds_brf call blom_logwrite(msg) @@ -762,7 +762,6 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) ! Initialize sdat for dust deposition climatology if appropriate call ocn_stream_dust_init(Emesh, clock, rc) if (ChkErr(rc, __LINE__, u_FILE_u)) return - end if #endif if (dbug > 5) call ESMF_LogWrite(subname//': done', ESMF_LOGMSG_INFO) diff --git a/drivers/nuopc/ocn_stream_dust.F90 b/drivers/nuopc/ocn_stream_dust.F90 index e5b50b3a..5e526592 100644 --- a/drivers/nuopc/ocn_stream_dust.F90 +++ b/drivers/nuopc/ocn_stream_dust.F90 @@ -24,7 +24,7 @@ module ocn_stream_dust character(len=CS) :: stream_dust_varname='DUST' ! Array to store dust flux after reading from file - real, allocatable, public :: dust_stream(:,:) + real(r8) :: dust_stream(1-nbdy:idm+nbdy, 1-nbdy:jdm+nbdy) integer, parameter :: nfiles_max = 100 ! maximum number of stream files character(len=*), parameter :: sourcefile = & @@ -173,15 +173,6 @@ subroutine ocn_stream_dust_init(model_mesh, model_clock, rc) end if ! allocate field to hold dust fields - if (mnproc == 1) then - write(lp,'(a)')'Memory allocation for variable dust_stream ...' - write(lp,'(a,i10)')'First dimension : ',idm - write(lp,'(a,i10)')'Second dimension : ',jdm - endif - allocate (dust_stream(jdm,idm),stat=errstat) - if (errstat /= 0) then - stop 'not enough memory dust_stream' - end if dust_stream(:,:) = 0.0 end subroutine ocn_stream_dust_init @@ -189,10 +180,11 @@ end subroutine ocn_stream_dust_init !================================================================ subroutine ocn_stream_dust_interp(model_clock, omask, rc) - use dshr_strdata_mod , only : shr_strdata_advance - use dshr_methods_mod , only : dshr_fldbun_getfldptr - use mod_forcing , only : dust_stream - use mod_checksum , only : csdiag, chksummsk + use dshr_strdata_mod , only : shr_strdata_advance + use dshr_methods_mod , only : dshr_fldbun_getfldptr + use mod_forcing , only : dust_stream + use mod_checksum , only : csdiag, chksummsk + use mod_output_forcing , only : output_forcing ! input/output variables type(ESMF_Clock), intent(in) :: model_clock @@ -211,6 +203,7 @@ subroutine ocn_stream_dust_interp(model_clock, omask, rc) real(r8), pointer :: dataptr1(:) real(r8), parameter :: mval = -1.e12_r8 real(r8), parameter :: fval = -1.e13_r8 + logical :: first_time = .true. !----------------------------------------------------------------------- ! Advance sdat stream @@ -255,6 +248,10 @@ subroutine ocn_stream_dust_interp(model_clock, omask, rc) n = (j - 1)*ii + i dust_stream(i,j) = dataptr1(n) end if + ! set flux to zero over land + if (omask(i,j) < 0.5) then + dust_stream(i,j) = 0.0 + end if end do end do @@ -265,14 +262,10 @@ subroutine ocn_stream_dust_interp(model_clock, omask, rc) call chksummsk(dust_stream,ip,1,'dust_stream') end if - ! set flux to zero over land - do j=1,kdm - do i=1,idm - if (omask(i,j) < 0.5) then - dust_stream(i,j) = 0.0 - end if - enddo - enddo + if (first_time) then + call output_forcing('dustdep_stream.nc', 'dustdep', dust_stream) + first_time = .false. + end if end subroutine ocn_stream_dust_interp diff --git a/hamocc/mo_hamocc4bcm.F90 b/hamocc/mo_hamocc4bcm.F90 index d194f18b..a826416e 100644 --- a/hamocc/mo_hamocc4bcm.F90 +++ b/hamocc/mo_hamocc4bcm.F90 @@ -88,7 +88,7 @@ subroutine hamocc4bcm(kpie,kpje,kpke,kbnd,kplyear,kplmon,kplday,kldtday,pdlxp,pd real, intent(in) :: prho (kpie,kpje,kpke) ! density [g/cm^3]. real, intent(in) :: pglat (1-kbnd:kpie+kbnd,1-kbnd:kpje+kbnd) ! latitude of grid cells [deg north]. real, intent(in) :: omask (kpie,kpje) ! land/ocean mask. - real, intent(in) :: dust (kpie,kpje) ! dust deposition flux [kg/m2/month]. + real, intent(in) :: dust (1-kbnd:kpie+kbnd,1-kbnd:kpje+kbnd) ! dust deposition flux [kg/m2/month]. real, intent(in) :: rivin (kpie,kpje,nriv) ! riverine input [kmol m-2 yr-1]. real, intent(in) :: ndep (kpie,kpje,nndep) ! nitrogen deposition [kmol m-2 yr-1]. real, intent(in) :: oafx (kpie,kpje) ! alkalinity flux from alkalinization [kmol m-2 yr-1] diff --git a/hamocc/mo_hamocc_step.F90 b/hamocc/mo_hamocc_step.F90 index abef42cf..1db21cd4 100644 --- a/hamocc/mo_hamocc_step.F90 +++ b/hamocc/mo_hamocc_step.F90 @@ -35,7 +35,7 @@ subroutine hamocc_step(m,n,mm,nn,k1m,k1n) use mod_state, only: temp,saln use mod_forcing, only: swa,slp,abswnd,atmco2,flxco2,flxdms,atmbrf,flxbrf, & atmn2o,flxn2o,atmnh3,flxnh3,atmnhxdep,atmnoydep, & - use_stream_dust, dust_stream + use_stream_dust, dust_stream, ndep_stream, oafx_stream use mod_seaice, only: ficem use mo_bgcmean, only: nbgc,bgcwrt, diagfq_bgc,diagmon_bgc,diagann_bgc use mo_intfcblom, only: bgc_dx,bgc_dy,bgc_dp,bgc_rho,omask,blom2hamocc,hamocc2blom @@ -55,9 +55,6 @@ subroutine hamocc_step(m,n,mm,nn,k1m,k1n) ! Local variables integer :: l,ldtday - real :: ndep(idm,jdm,nndep) - real :: dust(idm,jdm) - real :: oafx(idm,jdm) call trc_limitc(nn) @@ -67,41 +64,38 @@ subroutine hamocc_step(m,n,mm,nn,k1m,k1n) do l=1,nbgc bgcwrt(l)=.false. - if (((diagann_bgc(l).and.nday_of_year.eq.1.or.diagmon_bgc(l) & - & .and.date%day.eq.1).and.mod(nstep,nstep_in_day).eq.0).or. & - & .not.(diagann_bgc(l).or.diagmon_bgc(l)).and. & - & mod(nstep+.5,diagfq_bgc(l)).lt.1.) then + if (((diagann_bgc(l).and.nday_of_year.eq.1.or.diagmon_bgc(l) & + .and.date%day.eq.1).and.mod(nstep,nstep_in_day).eq.0).or. & + .not.(diagann_bgc(l).or.diagmon_bgc(l)).and. & + mod(nstep+.5,diagfq_bgc(l)).lt.1.) then bgcwrt(l)=.true. end if enddo - if (use_stream_dust) then - do j = 1,jdm - do i = 1,idm - dust(i,j) = dust_stream(i,j) - end do - end do - else - call get_fedep(idm,jdm,date%month,dust) + if (.not. use_stream_dust) then + call get_fedep(date%month, dust_stream) end if - call get_ndep(idm,jdm,nbdy,date%year,date%month,omask,ndep,atmnhxdep,atmnoydep) + if (.not. allocated(ndep_stream)) then + allocate(ndep_stream(1-nbdy:idm+nbdy, 1-nbdy:jdm+nbdy, nndep)) + end if + call get_ndep(date%year, date%month, omask, ndep_stream, atmnhxdep, atmnoydep) - call get_oafx(idm,jdm,date%year,date%month,omask,oafx) + call get_oafx(date%year, date%month, omask, oafx_stream) if (with_dmsph) then call get_pi_ph(idm,jdm,date%month) end if - call hamocc4bcm(idm,jdm,kdm,nbdy,date%year,date%month,date%day,ldtday,bgc_dx,bgc_dy,bgc_dp, & - & bgc_rho,plat,omask,dust,rivflx,ndep,oafx,pi_ph,swa,ficem,slp,abswnd, & - & temp(1-nbdy,1-nbdy,1+nn),saln(1-nbdy,1-nbdy,1+nn), & - & atmco2,flxco2,flxdms,atmbrf,flxbrf, & - & atmn2o,flxn2o,atmnh3,flxnh3) + call hamocc4bcm(idm, jdm, kdm, nbdy, & + date%year, date%month, date%day, ldtday, bgc_dx, bgc_dy, bgc_dp, & + bgc_rho, plat, omask, dust_stream, rivflx, ndep_stream, oafx_stream, & + pi_ph, swa, ficem, slp, abswnd, & + temp(1-nbdy,1-nbdy,1+nn), saln(1-nbdy,1-nbdy,1+nn), & + atmco2, flxco2, flxdms, atmbrf, flxbrf, & + atmn2o, flxn2o, atmnh3, flxnh3) - ! ! --- accumulate fields and write output - ! call accfields(idm,jdm,kdm,bgc_dx,bgc_dy,bgc_dp,omask) call hamocc2blom(m,n,mm,nn) diff --git a/hamocc/mo_read_fedep.F90 b/hamocc/mo_read_fedep.F90 index a04d476b..911d1f5e 100644 --- a/hamocc/mo_read_fedep.F90 +++ b/hamocc/mo_read_fedep.F90 @@ -114,9 +114,7 @@ subroutine ini_read_fedep(kpie,kpje,omask) do l=1,12 do j=1,kpje do i=1,kpie - if(omask(i,j).lt.0.5) dustflx(i,j,l) = 0.0 - enddo enddo enddo @@ -124,7 +122,7 @@ subroutine ini_read_fedep(kpie,kpje,omask) end subroutine ini_read_fedep - subroutine get_fedep(kpie,kpje,kplmon,dust) + subroutine get_fedep(kplmon, dust) !*********************************************************************************************** ! Get iron (dust) deposition for current month @@ -132,12 +130,18 @@ subroutine get_fedep(kpie,kpje,kplmon,dust) ! J.Schwinger *NORCE Climate, Bergen* 2020-05-19 !*********************************************************************************************** - integer, intent(in) :: kpie ! 1st dimension of model grid - integer, intent(in) :: kpje ! 2nd dimension of model grid + use mod_xc, only: idm, jdm, nbdy + integer, intent(in) :: kplmon ! current month. - real, intent(out) :: dust(kpie,kpje) ! dust flux for current month + real, intent(out) :: dust(1-nbdy:idm+nbdy, 1-nbdy:jdm+nbdy) ! dust flux for current month + + integer :: i,j - dust = dustflx(:,:,kplmon) + do j = 1,jdm + do i = 1,idm + dust(i,j) = dustflx(i,j,kplmon) + end do + end do end subroutine get_fedep diff --git a/hamocc/mo_read_ndep.F90 b/hamocc/mo_read_ndep.F90 index 723e2c24..bd8c5672 100644 --- a/hamocc/mo_read_ndep.F90 +++ b/hamocc/mo_read_ndep.F90 @@ -90,14 +90,14 @@ subroutine ini_read_ndep(kpie,kpje) ! Return if N deposition is turned off if (.not. do_ndep) then - if (mnproc.eq.1) then + if (mnproc == 1) then write(io_stdo_bgc,*) '' write(io_stdo_bgc,*) 'ini_read_ndep: N deposition is not activated.' endif return endif if (do_ndep_coupled) then - if (mnproc.eq.1) then + if (mnproc == 1) then write(io_stdo_bgc,*) '' write(io_stdo_bgc,*) 'ini_read_ndep: N deposition in interactive mode.' endif @@ -107,7 +107,7 @@ subroutine ini_read_ndep(kpie,kpje) ! Initialise the module if (.not. lini) then - if (mnproc.eq.1) then + if (mnproc == 1) then write(io_stdo_bgc,*)' ' write(io_stdo_bgc,*)'***************************************************' write(io_stdo_bgc,*)'iHAMOCC: Initialization of module mo_read_ndep:' @@ -116,7 +116,7 @@ subroutine ini_read_ndep(kpie,kpje) ! Check if nitrogen deposition file exists. If not, abort. inquire(file=ndepfile,exist=file_exists) - if (.not. file_exists .and. mnproc.eq.1) then + if (.not. file_exists .and. mnproc == 1) then write(io_stdo_bgc,*) '' write(io_stdo_bgc,*) 'ini_read_ndep: Cannot find N deposition file... ' call xchalt('(ini_read_ndep)') @@ -125,7 +125,7 @@ subroutine ini_read_ndep(kpie,kpje) if (use_extNcycle) then ! Allocate field to hold N-deposition fluxes - if (mnproc.eq.1) then + if (mnproc == 1) then write(io_stdo_bgc,*)'Memory allocation for variable nhxdepread ...' write(io_stdo_bgc,*)'First dimension : ',kpie write(io_stdo_bgc,*)'Second dimension : ',kpje @@ -134,7 +134,7 @@ subroutine ini_read_ndep(kpie,kpje) if(errstat.ne.0) stop 'not enough memory nhxdepread' nhxdepread(:,:) = 0.0 - if (mnproc.eq.1) then + if (mnproc == 1) then write(io_stdo_bgc,*)'Memory allocation for variable noydepread ...' write(io_stdo_bgc,*)'First dimension : ',kpie write(io_stdo_bgc,*)'Second dimension : ',kpje @@ -144,7 +144,7 @@ subroutine ini_read_ndep(kpie,kpje) noydepread(:,:) = 0.0 else ! Allocate field to hold N-deposition fluxes - if (mnproc.eq.1) then + if (mnproc == 1) then write(io_stdo_bgc,*)'Memory allocation for variable ndepread ...' write(io_stdo_bgc,*)'First dimension : ',kpie write(io_stdo_bgc,*)'Second dimension : ',kpje @@ -160,7 +160,7 @@ subroutine ini_read_ndep(kpie,kpje) call ncgeti('endyear',endyear) call ncfcls - if (mnproc.eq.1) then + if (mnproc == 1) then write(io_stdo_bgc,*) '' write(io_stdo_bgc,*) 'ini_read_ndep: Using N deposition file '//trim(ndepfile) endif @@ -172,7 +172,7 @@ subroutine ini_read_ndep(kpie,kpje) end subroutine ini_read_ndep - subroutine get_ndep(kpie,kpje,kbnd,kplyear,kplmon,omask,ndep,patmnhxdep,patmnoydep) + subroutine get_ndep(kplyear, kplmon, omask, ndep, patmnhxdep, patmnoydep) !*********************************************************************************************** ! Read and return CMIP6 n-deposition data for a given month or use atmosphere input @@ -180,7 +180,7 @@ subroutine get_ndep(kpie,kpje,kbnd,kplyear,kplmon,omask,ndep,patmnhxdep,patmnoyd ! S. Gao *Gfi, Bergen* 19.08.2017 !*********************************************************************************************** - use mod_xc, only: mnproc + use mod_xc, only: idm, jdm, nbdy, mnproc use netcdf, only: nf90_open,nf90_close,nf90_nowrite use mo_control_bgc, only: io_stdo_bgc,do_ndep,use_extNcycle, do_ndep_coupled use mo_netcdf_bgcrw, only: read_netcdf_var @@ -188,16 +188,12 @@ subroutine get_ndep(kpie,kpje,kbnd,kplyear,kplmon,omask,ndep,patmnhxdep,patmnoyd use mo_chemcon, only: mw_nitrogen ! Arguments - integer, intent(in) :: kpie ! 1st dimension of model grid. - integer, intent(in) :: kpje ! 2nd dimension of model grid. - integer, intent(in) :: kbnd ! - integer, intent(in) :: kplyear ! current year. - integer, intent(in) :: kplmon ! current month. - real, intent(in) :: omask(kpie,kpje) ! land/ocean mask (1=ocean) - real, intent(out) :: ndep(kpie,kpje,nndep) ! N-deposition field for current year and month - real, intent(in) :: patmnhxdep(1-kbnd:kpie+kbnd,1-kbnd:kpje+kbnd) ! Atmospheric NHx deposition [kgN m-2 s-1] - real, intent(in) :: patmnoydep(1-kbnd:kpie+kbnd,1-kbnd:kpje+kbnd) ! Atmospheric NOy deposition [kgN m-2 s-1] - + integer, intent(in) :: kplyear ! current year. + integer, intent(in) :: kplmon ! current month. + real, intent(in) :: omask(idm,jdm) ! land/ocean mask (1=ocean) + real, intent(out) :: ndep(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy,nndep) ! N-deposition field for current year and month + real, intent(in) :: patmnhxdep(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy) ! Atmospheric NHx deposition [kgN m-2 s-1] + real, intent(in) :: patmnoydep(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy) ! Atmospheric NOy deposition [kgN m-2 s-1] ! local variables integer :: month_in_file, ncstat, ncid, i, j @@ -214,9 +210,10 @@ subroutine get_ndep(kpie,kpje,kbnd,kplyear,kplmon,omask,ndep,patmnhxdep,patmnoyd ! get N-deposition from atmosphere fatmndep = 365.*86400./mw_nitrogen ndep(:,:,:) = 0. - !$OMP PARALLEL DO PRIVATE(i) - do j=1,kpje - do i=1,kpie + + !$omp parallel do private(i) + do j=1,jdm + do i=1,idm ! convert from kgN/m2/s to climatological input file units: kmolN/m2/yr if (patmnoydep(i,j) > 0.) then ndep(i,j,idepnoy) = patmnoydep(i,j)*fatmndep @@ -226,8 +223,8 @@ subroutine get_ndep(kpie,kpje,kbnd,kplyear,kplmon,omask,ndep,patmnhxdep,patmnoyd endif enddo enddo - !$OMP END PARALLEL DO - if (mnproc .eq. 1) then + !$omp end parallel do + if (mnproc == 1) then write (io_stdo_bgc,*) 'iHAMOCC: getting NOy and NHx deposition from atm' endif @@ -236,7 +233,7 @@ subroutine get_ndep(kpie,kpje,kbnd,kplyear,kplmon,omask,ndep,patmnhxdep,patmnoyd ! read ndep data from file if (kplmon.ne.oldmonth) then month_in_file=(max(startyear,min(endyear,kplyear))-startyear)*12+kplmon - if (mnproc.eq.1) then + if (mnproc == 1) then write(io_stdo_bgc,*) 'Read N deposition month ',month_in_file,' from file ',trim(ndepfile) endif ncstat=nf90_open(trim(ndepfile),nf90_nowrite,ncid) @@ -250,10 +247,10 @@ subroutine get_ndep(kpie,kpje,kbnd,kplyear,kplmon,omask,ndep,patmnhxdep,patmnoyd oldmonth=kplmon endif - !$OMP PARALLEL DO PRIVATE(i) + !$omp parallel do private(i) ! 1 = NO3; 2 = NH4 - do j=1,kpje - do i=1,kpie + do j=1,jdm + do i=1,idm if (use_extNcycle) then ndep(i,j,idepnoy) = noydepread(i,j) ndep(i,j,idepnhx) = nhxdepread(i,j) @@ -262,9 +259,10 @@ subroutine get_ndep(kpie,kpje,kbnd,kplyear,kplmon,omask,ndep,patmnhxdep,patmnoyd endif enddo enddo - !$OMP END PARALLEL DO + !$omp end parallel do endif + end subroutine get_ndep end module mo_read_ndep diff --git a/hamocc/mo_read_oafx.F90 b/hamocc/mo_read_oafx.F90 index c7c88ef6..200a3c62 100644 --- a/hamocc/mo_read_oafx.F90 +++ b/hamocc/mo_read_oafx.F90 @@ -206,8 +206,7 @@ subroutine ini_read_oafx(kpie,kpje,pdlxp,pdlyp,pglat,omask) ztmp1(:,:)=0.0 do j=1,kpje do i=1,kpie - if( omask(i,j).gt.0.5 .and. pglat(i,j)cdrmip_latmin ) then + if( omask(i,j)>0.5 .and. pglat(i,j)cdrmip_latmin ) then ztmp1(i,j)=ztmp1(i,j)+pdlxp(i,j)*pdlyp(i,j) endif enddo @@ -231,11 +230,9 @@ subroutine ini_read_oafx(kpie,kpje,pdlxp,pdlyp,pglat,omask) write(io_stdo_bgc,*)' ' endif - do j=1,kpje do i=1,kpie - if( omask(i,j).gt.0.5 .and. pglat(i,j)cdrmip_latmin ) then + if( omask(i,j).gt.0.5 .and. pglat(i,j)cdrmip_latmin ) then oalkflx(i,j) = avflx endif enddo @@ -262,7 +259,7 @@ subroutine ini_read_oafx(kpie,kpje,pdlxp,pdlyp,pglat,omask) end subroutine ini_read_oafx - subroutine get_oafx(kpie,kpje,kplyear,kplmon,omask,oafx) + subroutine get_oafx(kplyear, kplmon, omask, oafx) !*********************************************************************************************** ! Return ocean alkalinization flux. @@ -270,22 +267,21 @@ subroutine get_oafx(kpie,kpje,kplyear,kplmon,omask,oafx) ! J. Schwinger *NORCE Climate, Bergen* 2021-11-15 !*********************************************************************************************** - use mod_xc, only: xchalt,mnproc + use mod_xc, only: xchalt,mnproc,idm,jdm,nbdy use netcdf, only: nf90_open,nf90_close,nf90_nowrite use mo_control_bgc, only: io_stdo_bgc,do_oalk use mod_time, only: nday_of_year use mo_netcdf_bgcrw, only: read_netcdf_var ! Arguments - integer, intent(in) :: kpie ! 1st dimension of model grid. - integer, intent(in) :: kpje ! 2nd dimension of model grid. - integer, intent(in) :: kplyear ! current year. - integer, intent(in) :: kplmon ! current month. - real, intent(in) :: omask(kpie,kpje) ! land/ocean mask (1=ocean) - real, intent(out) :: oafx(kpie,kpje) ! alkalinization flux [kmol m-2 yr-1] + integer, intent(in) :: kplyear ! current year. + integer, intent(in) :: kplmon ! current month. + real, intent(in) :: omask(idm,jdm) ! land/ocean mask (1=ocean) + real, intent(out) :: oafx(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy) ! alkalinization flux [kmol m-2 yr-1] ! local variables integer :: month_in_file,ncstat,ncid,current_day + integer :: i,j if (.not. do_oalk) then oafx(:,:) = 0.0 @@ -298,7 +294,11 @@ subroutine get_oafx(kpie,kpje,kplyear,kplmon,omask,oafx) ! Scenarios of constant fluxes !-------------------------------- - oafx(:,:) = oalkflx(:,:) + do j = 1,jdm + do i = 1,idm + oafx(i,j) = oalkflx(i,j) + end do + end do elseif(trim(oalkscen)=='ramp' ) then @@ -309,13 +309,21 @@ subroutine get_oafx(kpie,kpje,kplyear,kplmon,omask,oafx) if(kplyear.lt.ramp_start ) then oafx(:,:) = 0.0 elseif(kplyear.ge.ramp_end ) then - oafx(:,:) = oalkflx(:,:) + do j = 1,jdm + do i = 1,idm + oafx(i,j) = oalkflx(i,j) + end do + end do else current_day = (kplyear-ramp_start)*365+nday_of_year - oafx(:,:) = oalkflx(:,:) * current_day / ((ramp_end-ramp_start)*365.) + do j = 1,jdm + do i = 1,idm + oafx(i,j) = oalkflx(i,j) * current_day / ((ramp_end-ramp_start)*365.) + end do + end do endif - elseif(trim(oalkscen)=='file' ) then + else if(trim(oalkscen)=='file' ) then !-------------------------------- ! Scenario from OA file diff --git a/phy/mod_forcing.F90 b/phy/mod_forcing.F90 index 0f977075..85e1c16a 100644 --- a/phy/mod_forcing.F90 +++ b/phy/mod_forcing.F90 @@ -98,10 +98,13 @@ module mod_forcing sss_stream ! Sea-surface salinity [g kg-1] from stream data. logical :: use_stream_relaxation ! If true, use nuopc stream relaxation capability - real(r8), dimension(idm,jdm) :: & - dust_stream, & ! iron dust deposition for hamocc - chloro_stream, & ! chlorophyll concentration - swa_stream ! short wave radiation absorbed + real(r8), dimension(1 - nbdy:idm + nbdy, 1 - nbdy:jdm + nbdy) :: & + swa_stream, & ! absorbed short wave radiation flux + dust_stream, & ! iron dust deposition flux (hamocc) + chloro_stream, & ! chlorophyll concentration (hamocc) + oafx_stream ! alkalinization flux (hamocc) + real(r8), allocatable :: ndep_stream(:,:,:) ! nitrogen deposition fluxes + real(r8), allocatable :: rivin_stream(:,:,:) ! riverine fluxes logical :: use_stream_dust ! If true, use nuopc stream dust capability (hamocc only) logical :: use_stream_chloro ! If true, use nuopc stream chlorophyll capability @@ -191,7 +194,7 @@ module mod_forcing ustar, ustarb, ustar3, wstar3, buoyfl, t_sw_nonloc, t_rs_nonloc, & s_br_nonloc, s_rs_nonloc, inivar_forcing, fwbbal, & sss_stream, sst_stream, ice_stream, & - dust_stream, & + dust_stream, chloro_stream, swa_stream, ndep_stream, oafx_stream, & use_stream_relaxation, use_stream_swa, use_stream_dust, use_stream_chloro contains @@ -203,7 +206,7 @@ subroutine inivar_forcing integer :: i, j, k, l - !$omp parallel do private(i) + !$omp parallel do private(i) do j = 1 - nbdy, jj + nbdy do i = 1 - nbdy, ii + nbdy eiacc(i, j) = spval @@ -252,9 +255,9 @@ subroutine inivar_forcing wstar3(i, j) = spval enddo enddo - !$omp end parallel do + !$omp end parallel do - !$omp parallel do private(k, i) + !$omp parallel do private(k, i) do j = 1 - nbdy, jj + nbdy do k = 1, kk + 1 do i = 1 - nbdy, ii + nbdy @@ -266,9 +269,9 @@ subroutine inivar_forcing enddo enddo enddo - !$omp end parallel do + !$omp end parallel do - !$omp parallel do private(l, i, k) + !$omp parallel do private(l, i, k) do j = 1, jj do l = 1, isp(j) do i = max(1, ifp(j, l)), min(ii, ilp(j, l)) @@ -285,8 +288,9 @@ subroutine inivar_forcing enddo enddo enddo - !$omp end parallel do - !$omp parallel do private(l, i) + !$omp end parallel do + + !$omp parallel do private(l, i) do j = 1, jj do l = 1, isp(j) do i = max(1, ifp(j, l)), min(ii, ilp(j, l)) @@ -303,9 +307,9 @@ subroutine inivar_forcing enddo enddo enddo - !$omp end parallel do + !$omp end parallel do - !$omp parallel do private(k, l, i) + !$omp parallel do private(k, l, i) do j = 1, jj do k = 1, kk + 1 do l = 1, isp(j) @@ -315,11 +319,11 @@ subroutine inivar_forcing enddo enddo enddo - !$omp end parallel do + !$omp end parallel do if (sprfac) then prfac = 1._r8 - !$omp parallel do private(l, i) + !$omp parallel do private(l, i) do j = 1, jj do l = 1, isp(j) do i = max(1, ifp(j, l)), min(ii, ilp(j, l)) @@ -328,7 +332,7 @@ subroutine inivar_forcing enddo enddo enddo - !$omp end parallel do + !$omp end parallel do endif end subroutine inivar_forcing @@ -351,7 +355,7 @@ subroutine fwbbal(m, n, mm, nn, k1m, k1n) ! sea-ice melting/freezing and the other is precipitation and runoff. The ! fresh water fluxes are weighted with the time step in case it varies ! during the accumulation period. - !$omp parallel do private(l, i) + !$omp parallel do private(l, i) do j = 1, jj do l = 1, isp(j) do i = max(1, ifp(j, l)), min(ii, ilp(j, l)) @@ -362,7 +366,7 @@ subroutine fwbbal(m, n, mm, nn, k1m, k1n) enddo enddo enddo - !$omp end parallel do + !$omp end parallel do ! Compute new correction factor at the end of a year and reset ! accumulation arrays. @@ -370,7 +374,7 @@ subroutine fwbbal(m, n, mm, nn, k1m, k1n) ! Weight the accumulated fluxes with grid cell area and do global sums, ! but only including grid cells connected to the world ocean. - !$omp parallel do private(l, i) + !$omp parallel do private(l, i) do j = 1, jj do l = 1, isp(j) do i = max(1, ifp(j, l)), min(ii, ilp(j, l)) @@ -379,7 +383,7 @@ subroutine fwbbal(m, n, mm, nn, k1m, k1n) enddo enddo enddo - !$omp end parallel do + !$omp end parallel do call xcsum(totei, eiacc, ipwocn) call xcsum(totpr, pracc, ipwocn) @@ -392,7 +396,7 @@ subroutine fwbbal(m, n, mm, nn, k1m, k1n) endif ! Reset accumulation arrays. - !$omp parallel do private(l, i) + !$omp parallel do private(l, i) do j = 1, jj do l = 1, isp(j) do i = max(1, ifp(j, l)), min(ii, ilp(j, l)) @@ -401,7 +405,7 @@ subroutine fwbbal(m, n, mm, nn, k1m, k1n) enddo enddo enddo - !$omp end parallel do + !$omp end parallel do endif From 6fd92e5fd034f84502cee427595d03969204260c Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Tue, 17 Sep 2024 19:47:04 +0200 Subject: [PATCH 04/16] updated stream logic in cap --- drivers/nuopc/ocn_comp_nuopc.F90 | 28 ++++++++++++++++++---------- hamocc/mo_hamocc_init.F90 | 4 +++- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/drivers/nuopc/ocn_comp_nuopc.F90 b/drivers/nuopc/ocn_comp_nuopc.F90 index e8409a99..71b00ab1 100644 --- a/drivers/nuopc/ocn_comp_nuopc.F90 +++ b/drivers/nuopc/ocn_comp_nuopc.F90 @@ -50,19 +50,19 @@ module ocn_comp_nuopc use mod_cesm, only: runid_cesm, runtyp_cesm, ocn_cpl_dt_cesm use mod_config, only: inst_index, inst_name, inst_suffix use mod_time, only: blom_time - use mod_forcing, only: srxday, trxday + use mod_forcing, only: srxday, trxday, use_stream_dust, use_stream_swa use mod_swabs, only: swamth, chlopt use mod_constants, only: epsilt use mod_blom_init, only: blom_init use mod_blom_step, only: blom_step use mod_fill_global, only: fill_global use mod_restart, only: restart_write + use mod_xc, only: mnproc, xcstop use ocn_stream_sss, only: ocn_stream_sss_init, ocn_stream_sss_interp use ocn_stream_sst, only: ocn_stream_sst_init, ocn_stream_sst_interp use ocn_stream_swa, only: ocn_stream_swa_init, ocn_stream_swa_interp use ocn_stream_dust, only: ocn_stream_dust_init, ocn_stream_dust_interp use ocn_stream_chloro, only: ocn_stream_chloro_init, ocn_stream_chloro_interp - use mod_xc, only: mnproc, xcstop #ifdef HAMOCC use mo_control_bgc, only: use_BROMO use mo_intfcblom, only: omask @@ -756,12 +756,16 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) #ifdef HAMOCC ! Initialize sdat for swa climatology if appropriate - call ocn_stream_swa_init(Emesh, clock, rc) - if (ChkErr(rc, __LINE__, u_FILE_u)) return + if (use_stream_swa) then + call ocn_stream_swa_init(Emesh, clock, rc) + if (ChkErr(rc, __LINE__, u_FILE_u)) return + end if ! Initialize sdat for dust deposition climatology if appropriate - call ocn_stream_dust_init(Emesh, clock, rc) - if (ChkErr(rc, __LINE__, u_FILE_u)) return + if (use_stream_dust) then + call ocn_stream_dust_init(Emesh, clock, rc) + if (ChkErr(rc, __LINE__, u_FILE_u)) return + end if #endif if (dbug > 5) call ESMF_LogWrite(subname//': done', ESMF_LOGMSG_INFO) @@ -934,12 +938,16 @@ subroutine ModelAdvance(gcomp, rc) #ifdef HAMOCC ! Advance swa stream input if appropriate - call ocn_stream_swa_interp(clock, omask, rc) - if (ChkErr(rc, __LINE__, u_FILE_u)) return + if (use_stream_swa) then + call ocn_stream_swa_interp(clock, omask, rc) + if (ChkErr(rc, __LINE__, u_FILE_u)) return + end if ! Advance dust stream input if appropriate - call ocn_stream_dust_interp(clock, omask, rc) - if (ChkErr(rc, __LINE__, u_FILE_u)) return + if (use_stream_dust) then + call ocn_stream_dust_interp(clock, omask, rc) + if (ChkErr(rc, __LINE__, u_FILE_u)) return + end if #endif ! Advance the model a time step. diff --git a/hamocc/mo_hamocc_init.F90 b/hamocc/mo_hamocc_init.F90 index 11a8bbeb..c873416a 100644 --- a/hamocc/mo_hamocc_init.F90 +++ b/hamocc/mo_hamocc_init.F90 @@ -106,7 +106,9 @@ subroutine hamocc_init(read_rest,rstfnm_hamocc) ! ! --- Read the HAMOCC BGCNML namelist and check the value of some variables. ! - if(.not. allocated(bgc_namelist)) call get_bgc_namelist + if(.not. allocated(bgc_namelist)) then + call get_bgc_namelist + end if open (newunit=iounit, file=bgc_namelist, status='old', action='read') read (unit=iounit, nml=BGCNML) close (unit=iounit) From 311afcb84847584f01e7a851fd372df570a564ea Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Tue, 17 Sep 2024 21:29:24 +0200 Subject: [PATCH 05/16] updated namelist_definition_blom.xml --- cime_config/namelist_definition_blom.xml | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/cime_config/namelist_definition_blom.xml b/cime_config/namelist_definition_blom.xml index 0b37052b..80c4d7f9 100644 --- a/cime_config/namelist_definition_blom.xml +++ b/cime_config/namelist_definition_blom.xml @@ -3798,16 +3798,6 @@ Switch for M4AGO settling scheme - - logical - bgcnml - bgcnml - - .false. - - Switch for cyano-bluefix in euphotic zone only - - logical bgcnml @@ -4134,6 +4124,17 @@ add desc + + logical + config_bgc + config_bgc + + .true. + .false. + + activate the HAMOCC preformed tracers code + + From 9053a482c2731289604c1d9d780039af186734de Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Wed, 18 Sep 2024 12:21:11 +0200 Subject: [PATCH 06/16] more changes for fe deposition validation --- cime_config/buildnml | 3 +- cime_config/namelist_definition_blom.xml | 88 ++++++++++++++++++- drivers/nuopc/ocn_stream_dust.F90 | 11 ++- hamocc/mo_hamocc_step.F90 | 9 +- hamocc/mo_read_fedep.F90 | 14 ++- phy/mod_forcing.F90 | 8 +- {drivers/nuopc => phy}/mod_output_forcing.F90 | 25 +++--- phy/mod_rdlim.F90 | 10 ++- 8 files changed, 136 insertions(+), 32 deletions(-) rename {drivers/nuopc => phy}/mod_output_forcing.F90 (79%) diff --git a/cime_config/buildnml b/cime_config/buildnml index 6ef0f906..d4464ab5 100755 --- a/cime_config/buildnml +++ b/cime_config/buildnml @@ -256,7 +256,8 @@ def buildnml(case, caseroot, compname): namelist_file += inst_string # Create BLOM namelist - groups=['limits','diffusion','merdia','secdia','diaphy','stream_sss','stream_sst' ] + groups=['limits','diffusion','merdia','secdia','diaphy', + 'stream_sss','stream_sst','stream_swa','stream_dust','stream_oafx'] groups.append('cwmod') diff --git a/cime_config/namelist_definition_blom.xml b/cime_config/namelist_definition_blom.xml index 80c4d7f9..e2e5800b 100644 --- a/cime_config/namelist_definition_blom.xml +++ b/cime_config/namelist_definition_blom.xml @@ -8833,7 +8833,7 @@ limits .false. - .true. + .false. if .true., use NUOPC stream swabs capability @@ -8852,10 +8852,10 @@ stream_swa stream_swa - file name(s) containing salinity relaxation data + file name(s) containing swa climatology - $DIN_LOC_ROOT/ocn/blom/bndcon/swa_clim_core_tnx0.25v4_20240512_cdf5.nc + $DIN_LOC_ROOT/ocn/blom/bndcon/Annual_clim_swa_tnx1v4_20210415.nc @@ -8946,7 +8946,7 @@ variable name on stream file - DUST + dustdep @@ -8983,4 +8983,84 @@ + + + + + + logical + limits + limits + + .false. + .false. + + if .true., use NUOPC stream ocean alkalinity capability + + + + char + stream_oalk + stream_oalk + stream mesh file + + '' + + + + char(10) + stream_oalk + stream_oalk + + file name(s) containing oalk deposition data + + + '' + + + + char + stream_oalk + stream_oalk + + variable name on stream file + + + '' + + + + integer + stream_oalk + stream_oalk + + First year in stream to use + + + 1 + + + + integer + stream_oalk + stream_oalk + + Last year in stream to use + + + 1 + + + + integer + stream_oalk + stream_oalk + + Align stream_year_first with this model year + + + 1 + + + diff --git a/drivers/nuopc/ocn_stream_dust.F90 b/drivers/nuopc/ocn_stream_dust.F90 index 5e526592..988e1b16 100644 --- a/drivers/nuopc/ocn_stream_dust.F90 +++ b/drivers/nuopc/ocn_stream_dust.F90 @@ -21,7 +21,7 @@ module ocn_stream_dust public :: ocn_stream_dust_interp ! interpolates between two years of dust file data type(shr_strdata_type) :: sdat_dust ! input data stream - character(len=CS) :: stream_dust_varname='DUST' + character(len=CS) :: stream_dust_varname='dustdep' ! Array to store dust flux after reading from file real(r8) :: dust_stream(1-nbdy:idm+nbdy, 1-nbdy:jdm+nbdy) @@ -147,6 +147,7 @@ subroutine ocn_stream_dust_init(model_mesh, model_clock, rc) endif ! Initialize the cdeps data type sdat_dust + ! tintalgo can be one of [lower,upper,nearest,linear,coszen] call shr_strdata_init_from_inline(sdat_dust, & my_task = mnproc, & logunit = lp, & @@ -166,7 +167,7 @@ subroutine ocn_stream_dust_init(model_mesh, model_clock, rc) stream_taxmode = 'cycle', & stream_dtlimit = 1.0e30_r8, & stream_tintalgo = 'linear', & - stream_name = 'Dust Deposition', & + stream_name = 'Fe Dust Deposition', & rc = rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then call ESMF_Finalize(endflag=ESMF_END_ABORT) @@ -203,6 +204,7 @@ subroutine ocn_stream_dust_interp(model_clock, omask, rc) real(r8), pointer :: dataptr1(:) real(r8), parameter :: mval = -1.e12_r8 real(r8), parameter :: fval = -1.e13_r8 + integer :: seconds_per_month = 2592000 ! assuming 30 days per month logical :: first_time = .true. !----------------------------------------------------------------------- @@ -246,7 +248,8 @@ subroutine ocn_stream_dust_interp(model_clock, omask, rc) dust_stream(i,j) = fval else n = (j - 1)*ii + i - dust_stream(i,j) = dataptr1(n) + ! need dust_stream in units of kg/m2/month not kg/m2/s which is in the file + dust_stream(i,j) = dataptr1(n)*seconds_per_month end if ! set flux to zero over land if (omask(i,j) < 0.5) then @@ -263,7 +266,7 @@ subroutine ocn_stream_dust_interp(model_clock, omask, rc) end if if (first_time) then - call output_forcing('dustdep_stream.nc', 'dustdep', dust_stream) + call output_forcing('fedep_stream.nc', 'fedep', dust_stream) first_time = .false. end if diff --git a/hamocc/mo_hamocc_step.F90 b/hamocc/mo_hamocc_step.F90 index 1db21cd4..ec0124be 100644 --- a/hamocc/mo_hamocc_step.F90 +++ b/hamocc/mo_hamocc_step.F90 @@ -35,7 +35,8 @@ subroutine hamocc_step(m,n,mm,nn,k1m,k1n) use mod_state, only: temp,saln use mod_forcing, only: swa,slp,abswnd,atmco2,flxco2,flxdms,atmbrf,flxbrf, & atmn2o,flxn2o,atmnh3,flxnh3,atmnhxdep,atmnoydep, & - use_stream_dust, dust_stream, ndep_stream, oafx_stream + use_stream_dust, use_stream_oalk, & + dust_stream, ndep_stream, oalk_stream use mod_seaice, only: ficem use mo_bgcmean, only: nbgc,bgcwrt, diagfq_bgc,diagmon_bgc,diagann_bgc use mo_intfcblom, only: bgc_dx,bgc_dy,bgc_dp,bgc_rho,omask,blom2hamocc,hamocc2blom @@ -81,7 +82,9 @@ subroutine hamocc_step(m,n,mm,nn,k1m,k1n) end if call get_ndep(date%year, date%month, omask, ndep_stream, atmnhxdep, atmnoydep) - call get_oafx(date%year, date%month, omask, oafx_stream) + if (.not. use_stream_oalk) then + call get_oafx(date%year, date%month, omask, oalk_stream) + end if if (with_dmsph) then call get_pi_ph(idm,jdm,date%month) @@ -89,7 +92,7 @@ subroutine hamocc_step(m,n,mm,nn,k1m,k1n) call hamocc4bcm(idm, jdm, kdm, nbdy, & date%year, date%month, date%day, ldtday, bgc_dx, bgc_dy, bgc_dp, & - bgc_rho, plat, omask, dust_stream, rivflx, ndep_stream, oafx_stream, & + bgc_rho, plat, omask, dust_stream, rivflx, ndep_stream, oalk_stream, & pi_ph, swa, ficem, slp, abswnd, & temp(1-nbdy,1-nbdy,1+nn), saln(1-nbdy,1-nbdy,1+nn), & atmco2, flxco2, flxdms, atmbrf, flxbrf, & diff --git a/hamocc/mo_read_fedep.F90 b/hamocc/mo_read_fedep.F90 index 911d1f5e..35455bad 100644 --- a/hamocc/mo_read_fedep.F90 +++ b/hamocc/mo_read_fedep.F90 @@ -62,8 +62,8 @@ subroutine ini_read_fedep(kpie,kpje,omask) real, intent(in) :: omask(kpie,kpje) ! land/ocean mask (1=ocean) ! Local variables - integer :: i,j,l - integer :: ncid,ncstat,ncvarid,errstat + integer :: i,j,l + integer :: ncid,ncstat,ncvarid,errstat ! allocate field to hold iron deposition fluxes if (mnproc.eq.1) then @@ -131,11 +131,14 @@ subroutine get_fedep(kplmon, dust) !*********************************************************************************************** use mod_xc, only: idm, jdm, nbdy + use mod_output_forcing, only : output_forcing integer, intent(in) :: kplmon ! current month. real, intent(out) :: dust(1-nbdy:idm+nbdy, 1-nbdy:jdm+nbdy) ! dust flux for current month integer :: i,j + logical :: debug = .true. + logical :: first_time = .true. do j = 1,jdm do i = 1,idm @@ -143,6 +146,13 @@ subroutine get_fedep(kplmon, dust) end do end do + if (debug) then + if (first_time) then + call output_forcing('fedep_orig.nc', 'fedep', dust) + first_time = .false. + end if + end if + end subroutine get_fedep end module mo_read_fedep diff --git a/phy/mod_forcing.F90 b/phy/mod_forcing.F90 index 85e1c16a..882b58a9 100644 --- a/phy/mod_forcing.F90 +++ b/phy/mod_forcing.F90 @@ -102,13 +102,14 @@ module mod_forcing swa_stream, & ! absorbed short wave radiation flux dust_stream, & ! iron dust deposition flux (hamocc) chloro_stream, & ! chlorophyll concentration (hamocc) - oafx_stream ! alkalinization flux (hamocc) + oalk_stream ! alkalinization flux (hamocc) real(r8), allocatable :: ndep_stream(:,:,:) ! nitrogen deposition fluxes real(r8), allocatable :: rivin_stream(:,:,:) ! riverine fluxes logical :: use_stream_dust ! If true, use nuopc stream dust capability (hamocc only) logical :: use_stream_chloro ! If true, use nuopc stream chlorophyll capability logical :: use_stream_swa ! If true, use nuopc stream swa capability + logical :: use_stream_oalk ! If true, use nuopc stream for ocean alkalinity capability ! Variables related to balancing the freshwater forcing budget. real(r8) :: & @@ -194,8 +195,9 @@ module mod_forcing ustar, ustarb, ustar3, wstar3, buoyfl, t_sw_nonloc, t_rs_nonloc, & s_br_nonloc, s_rs_nonloc, inivar_forcing, fwbbal, & sss_stream, sst_stream, ice_stream, & - dust_stream, chloro_stream, swa_stream, ndep_stream, oafx_stream, & - use_stream_relaxation, use_stream_swa, use_stream_dust, use_stream_chloro + dust_stream, chloro_stream, swa_stream, ndep_stream, oalk_stream, & + use_stream_relaxation, use_stream_swa, use_stream_dust, use_stream_chloro, & + use_stream_oalk contains diff --git a/drivers/nuopc/mod_output_forcing.F90 b/phy/mod_output_forcing.F90 similarity index 79% rename from drivers/nuopc/mod_output_forcing.F90 rename to phy/mod_output_forcing.F90 index aaaeac95..5e8d0ab0 100644 --- a/drivers/nuopc/mod_output_forcing.F90 +++ b/phy/mod_output_forcing.F90 @@ -28,12 +28,12 @@ subroutine output_forcing(filename, varname, vardata) real :: arr_l(1-nbdy:idm+nbdy, 1-nbdy:jdm+nbdy, 1) if (mnproc==1) then - write(lp,*) 'creating netcdf file for dust stream' + write(lp,'(a)') 'creating netcdf file '//trim(filename) ! open file - ncstat = nf90_create('dustdep_stream.nc', NF90_64BIT_OFFSET, ncid) + ncstat = nf90_create(trim(filename), NF90_64BIT_OFFSET, ncid) if ( ncstat /= NF90_NOERR ) then - call xchalt('(cannot open dustdep_stream.nc)'); stop + call xchalt('(cannot open output forcing data file)'); stop endif ! defined dimensions @@ -54,6 +54,7 @@ subroutine output_forcing(filename, varname, vardata) call xchalt('(cannot define variable)'); stop endif + ! end definition ncstat = nf90_enddef(ncid) end if @@ -69,17 +70,19 @@ subroutine output_forcing(filename, varname, vardata) call xcaget(arr_g, arr_l, 1) if (mnproc == 1) then - ncstat = nf90_put_var(ncid, ncvarid, arr_g, start, count) - if (ncstat /= nf90_noerr) then + ! Output variable data + ncstat = nf90_put_var(ncid, ncvarid, arr_g, start, count) + if (ncstat /= nf90_noerr) then write(lp,'(4a)') 'nf90_put_var: ',trim(varname),': ',nf90_strerror(ncstat) call xchalt('(write_netcdf_var)'); stop - endif - end if + endif - ncstat = nf90_close(ncid) - if ( ncstat /= NF90_NOERR ) then - call xchalt('(cannot close file)'); stop - endif + ! Close file + ncstat = nf90_close(ncid) + if ( ncstat /= NF90_NOERR ) then + call xchalt('(cannot close file)'); stop + endif + end if end subroutine output_forcing diff --git a/phy/mod_rdlim.F90 b/phy/mod_rdlim.F90 index 70ba381a..a62726bf 100644 --- a/phy/mod_rdlim.F90 +++ b/phy/mod_rdlim.F90 @@ -46,7 +46,7 @@ module mod_rdlim srxlim, srxbal, sprfac, & srxlim, srxbal, sprfac, & use_stream_relaxation, use_stream_swa, & - use_stream_chloro, use_stream_dust + use_stream_chloro, use_stream_dust, use_stream_oalk use mod_swabs, only: swamth, jwtype, chlopt, ccfile use mod_diffusion, only: readnml_diffusion use mod_eddtra, only: mlrmth, ce, cl, tau_mlr, tau_growing_hbl, & @@ -147,7 +147,7 @@ subroutine rdlim() csdiag, & rstfrq,rstfmt,rstcmp,iotype,& use_stream_relaxation, use_stream_swa, use_stream_chloro, & - use_stream_dust + use_stream_dust, use_stream_oalk ! read limits namelist @@ -251,10 +251,11 @@ subroutine rdlim() write (lp,*) 'RSTFMT',RSTFMT write (lp,*) 'RSTCMP',RSTCMP write (lp,*) 'IOTYPE',IOTYPE + write (lp,*) 'USE_STREAM_CHLORO',use_stream_chloro write (lp,*) 'USE_STREAM_RELAXATION',use_stream_relaxation write (lp,*) 'USE_STREAM_SWA',use_stream_swa - write (lp,*) 'USE_STREAM_CHLORO',use_stream_chloro write (lp,*) 'USE_STREAM_DUST',use_stream_dust + write (lp,*) 'USE_STREAM_OALK',use_stream_oalk write (lp,*) end if @@ -338,9 +339,10 @@ subroutine rdlim() call xcbcst(rstcmp) call xcbcst(iotype) call xcbcst(use_stream_relaxation) - call xcbcst(use_stream_swa) call xcbcst(use_stream_chloro) + call xcbcst(use_stream_swa) call xcbcst(use_stream_dust) + call xcbcst(use_stream_oalk) ! resolve options select case (trim(wavsrc)) From 8a39eb29517e284b79da9eda3e2efa45ebb5904e Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Wed, 18 Sep 2024 12:57:16 +0200 Subject: [PATCH 07/16] set stream capability for dust as false for now --- cime_config/namelist_definition_blom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cime_config/namelist_definition_blom.xml b/cime_config/namelist_definition_blom.xml index e2e5800b..f999d217 100644 --- a/cime_config/namelist_definition_blom.xml +++ b/cime_config/namelist_definition_blom.xml @@ -8913,7 +8913,7 @@ limits .false. - .true. + .false. if .true., use NUOPC stream dust capability From e967a943c04a35287a670b7a4be9a076c9ffa84e Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Thu, 19 Sep 2024 19:21:52 +0200 Subject: [PATCH 08/16] added new code for riverine flux input - still need to fix all compilation problems --- drivers/nuopc/mod_blom_pio.F90 | 142 ++++++++++++++++++ drivers/nuopc/ocn_comp_nuopc.F90 | 14 +- drivers/nuopc/ocn_stream_dust.F90 | 7 +- drivers/nuopc/ocn_stream_rivin.F90 | 231 +++++++++++++++++++++++++++++ hamocc/mo_hamocc_init.F90 | 25 +++- hamocc/mo_hamocc_step.F90 | 26 ++-- hamocc/mo_read_fedep.F90 | 18 +-- hamocc/mo_read_rivin.F90 | 48 +++--- phy/mod_forcing.F90 | 35 +++-- phy/mod_rdlim.F90 | 11 +- 10 files changed, 476 insertions(+), 81 deletions(-) create mode 100644 drivers/nuopc/mod_blom_pio.F90 create mode 100644 drivers/nuopc/ocn_stream_rivin.F90 diff --git a/drivers/nuopc/mod_blom_pio.F90 b/drivers/nuopc/mod_blom_pio.F90 new file mode 100644 index 00000000..6057153d --- /dev/null +++ b/drivers/nuopc/mod_blom_pio.F90 @@ -0,0 +1,142 @@ +module mod_blom_pio + + use ESMF + use pio + use mod_types , only : r8, r4 + use mod_xc , only : lp, mnproc + use shr_pio_mod , only : shr_pio_getiosys, shr_pio_getiotype, shr_pio_getioformat + use shr_pio_mod , only : shr_pio_getiosys, shr_pio_getiotype + use shr_sys_mod , only : shr_sys_abort + use nuopc_shr_methods , only : chkerr + + implicit none + private + + public :: blom_pio_init + public :: blom_pio_getdata + private :: blom_pio_iodesc + + integer , public :: pio_iotype + integer , public :: pio_ioformat + type(iosystem_desc_t), pointer , public :: pio_iosystem + + character(len=*), parameter :: u_FILE_u = & + __FILE__ + +#include + +!================================================================================ +contains +!================================================================================ + + subroutine blom_pio_init() + pio_iosystem => shr_pio_getiosys('OCN') + pio_iotype = shr_pio_getiotype('OCN') + pio_ioformat = shr_pio_getioformat('OCN') + end subroutine blom_pio_init + + subroutine blom_pio_getdata(pioid, varname, mesh_i, data_i, rc) + + ! input/output variables + type(file_desc_t), intent(inout) :: pioid + character(len=*) , intent(in) :: varname ! field name in rawdata file + type(ESMF_Mesh) , intent(in) :: mesh_i + real(r8) , intent(inout) :: data_i(:) ! input raw data + integer , intent(out) :: rc + + ! local variables + type(io_desc_t) :: pio_iodesc + type(var_desc_t) :: pio_varid + integer :: pio_vartype + real(r4), allocatable :: data_real(:) + integer :: lsize + integer :: rcode + character(len=*), parameter :: subname = 'blom_pio_getdata' + !------------------------------------------------- + + rc = ESMF_SUCCESS + + ! Create io descriptor for input raw data + ! This will query the raw data file for the dimensions of the variable varname and + ! create iodesc for either single or multi level input data + call blom_pio_iodesc(mesh_i, trim(varname), pioid, pio_varid, pio_vartype, pio_iodesc, rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Read the input data + if (pio_vartype == PIO_REAL) then + lsize = size(data_i) + allocate(data_real(lsize)) + call pio_read_darray(pioid, pio_varid, pio_iodesc, data_real, rcode) + data_i(:) = real(data_real(:), kind=r8) + deallocate(data_real) + else if (pio_vartype == PIO_DOUBLE) then + call pio_read_darray(pioid, pio_varid, pio_iodesc, data_i, rcode) + else + call shr_sys_abort(subName//" ERROR: supported variable type not found for "//trim(varname)) + end if + + call pio_freedecomp(pioid, pio_iodesc) + + end subroutine blom_pio_getdata + + !=============================================================== + subroutine blom_pio_iodesc( mesh, varname, pioid, pio_varid, pio_vartype, pio_iodesc, rc) + + ! Determine pio io descriptor for variable on rawdata file + + ! input/output variables + type(ESMF_Mesh) , intent(in) :: mesh + character(len=*) , intent(in) :: varname + type(file_desc_t) , intent(inout) :: pioid + type(var_desc_t) , intent(out) :: pio_varid + integer , intent(out) :: pio_vartype + type(io_desc_t) , intent(inout) :: pio_iodesc + integer , intent(out) :: rc + + ! local variables + type(ESMF_DistGrid) :: distGrid + integer :: n, ndims + integer, allocatable :: compdof(:) + integer, allocatable :: dimids(:) + integer, allocatable :: dimlens(:) + integer :: lsize + integer :: rCode ! pio return code (only used when pio error handling is PIO_BCAST_ERROR) + character(*), parameter :: subname = '(pio_iodesc) ' + !------------------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + call ESMF_MeshGet(mesh, elementdistGrid=distGrid, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_DistGridGet(distGrid, localDe=0, elementCount=lsize, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + allocate(compdof(lsize)) + call ESMF_DistGridGet(distGrid, localDe=0, seqIndexList=compdof, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! get pio variable id, type and number of dimensions + rcode = pio_inq_varid(pioid, trim(varname), pio_varid) + rcode = pio_inq_vartype(pioid, pio_varid, pio_vartype) + rcode = pio_inq_varndims(pioid, pio_varid, ndims) + + ! get variable dimension sizes + allocate(dimids(ndims)) + allocate(dimlens(ndims)) + rcode = pio_inq_vardimid(pioid, pio_varid, dimids(1:ndims)) + do n = 1, ndims + rcode = pio_inq_dimlen(pioid, dimids(n), dimlens(n)) + end do + + ! determine io descriptor for this variable + call pio_initdecomp(pio_iosystem, pio_vartype, (/dimlens(1),dimlens(2)/), compdof, pio_iodesc) + if (mnproc == 1) then + write(lp,'(a,i8,i8)') ' set iodesc for rawdata: '//trim(varname)//' with dim(1),dim(2) = ',& + dimlens(1),dimlens(2) + end if + + ! deallocate memory + deallocate(compdof) + + end subroutine blom_pio_iodesc + +end module mod_blom_pio diff --git a/drivers/nuopc/ocn_comp_nuopc.F90 b/drivers/nuopc/ocn_comp_nuopc.F90 index 71b00ab1..00239741 100644 --- a/drivers/nuopc/ocn_comp_nuopc.F90 +++ b/drivers/nuopc/ocn_comp_nuopc.F90 @@ -61,19 +61,18 @@ module ocn_comp_nuopc use ocn_stream_sss, only: ocn_stream_sss_init, ocn_stream_sss_interp use ocn_stream_sst, only: ocn_stream_sst_init, ocn_stream_sst_interp use ocn_stream_swa, only: ocn_stream_swa_init, ocn_stream_swa_interp - use ocn_stream_dust, only: ocn_stream_dust_init, ocn_stream_dust_interp use ocn_stream_chloro, only: ocn_stream_chloro_init, ocn_stream_chloro_interp #ifdef HAMOCC use mo_control_bgc, only: use_BROMO use mo_intfcblom, only: omask + use ocn_stream_dust, only: ocn_stream_dust_init, ocn_stream_dust_interp + use ocn_stream_rivin, only: ocn_stream_rivin_init #endif implicit none - private - integer, parameter :: cslen = 80 ! Short character string length. - integer, parameter :: cllen = 265 ! Long character string length. + integer, parameter :: cllen = 256 ! Long character string length. character(len=*), parameter :: modname = '(ocn_comp_nuopc)' character(len=*), parameter :: u_FILE_u = & __FILE__ @@ -380,7 +379,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) type(ESMF_VM) :: vm type(ESMF_TimeInterval) :: timeStep integer :: localPet, nthrds, shrlogunit, n - character(len=cslen) :: starttype, stdname + character(len=cllen) :: starttype, stdname character(len=cllen) :: msg, cvalue logical :: isPresent, isSet logical :: ocn2glc_coupling @@ -766,6 +765,11 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) call ocn_stream_dust_init(Emesh, clock, rc) if (ChkErr(rc, __LINE__, u_FILE_u)) return end if + + if (use_stream_rivin) then + call ocn_stream_rivin_init(Emesh, rc) + if (ChkErr(rc, __LINE__, u_FILE_u)) return + end if #endif if (dbug > 5) call ESMF_LogWrite(subname//': done', ESMF_LOGMSG_INFO) diff --git a/drivers/nuopc/ocn_stream_dust.F90 b/drivers/nuopc/ocn_stream_dust.F90 index 988e1b16..7756f194 100644 --- a/drivers/nuopc/ocn_stream_dust.F90 +++ b/drivers/nuopc/ocn_stream_dust.F90 @@ -1,5 +1,5 @@ module ocn_stream_dust - +#ifdef HAMOCC !----------------------------------------------------------------------- ! Contains methods for reading in dust forcing file !----------------------------------------------------------------------- @@ -12,6 +12,7 @@ module ocn_stream_dust 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 shr_sys_mod , only : shr_sys_abort + use mod_forcing , only : dust_stream use mod_xc implicit none @@ -23,9 +24,6 @@ module ocn_stream_dust type(shr_strdata_type) :: sdat_dust ! input data stream character(len=CS) :: stream_dust_varname='dustdep' - ! Array to store dust flux after reading from file - real(r8) :: dust_stream(1-nbdy:idm+nbdy, 1-nbdy:jdm+nbdy) - integer, parameter :: nfiles_max = 100 ! maximum number of stream files character(len=*), parameter :: sourcefile = & __FILE__ @@ -272,4 +270,5 @@ subroutine ocn_stream_dust_interp(model_clock, omask, rc) end subroutine ocn_stream_dust_interp +#endif end module ocn_stream_dust diff --git a/drivers/nuopc/ocn_stream_rivin.F90 b/drivers/nuopc/ocn_stream_rivin.F90 new file mode 100644 index 00000000..ef739327 --- /dev/null +++ b/drivers/nuopc/ocn_stream_rivin.F90 @@ -0,0 +1,231 @@ +module ocn_stream_rivin + +#ifdef HAMOCC + !************************************************************************************************* + ! Routine for reading riverine nutrient data + ! + ! Riverine carbon and nutrient input is activated through a logical switch 'do_rivinpt' read + ! from HAMOCC's bgcnml namelist. When coupled to NorESM, this is achieved by setting + ! BLOM_RIVER_NUTRIENTS to TRUE in env_run.xml. + ! + ! The model attempts to read nutrient fluxes from a NetCDF file + ! derived from the GNEWS 2000 data base, which is specified through the + ! namelist. The nutrient fluxes are then interpolated to the model ocean grid. + ! + ! The nutrient discharge is distributed on the ocean grid in manner that is + ! consistent with how model distributes its freshwater runoff. + ! + ! Since only alkalinity is available from measurements, DIC is updated using + ! the assumtions that a_t=a_c+a_n and DIC=a_c (a_t: total alkalinity, + ! a_c: carbonate alkalinity, a_n: contribution of nutrients to a_t). + !************************************************************************************************* + + use ESMF , only: ESMF_Finalize, ESMF_LogFoundError + use ESMF , only: ESMF_Mesh, ESMF_MeshCreate, ESMF_FieldCreate + use ESMF , only: ESMF_Field, ESMF_FieldCreate, ESMF_FieldGet + use ESMF , only: ESMF_FieldSMMStore, ESMF_FieldRegrid, ESMF_RouteHandle + use ESMF , only: ESMF_SUCCESS, ESMF_LOGERR_PASSTHRU, ESMF_END_ABORT + use ESMF , only: ESMF_FILEFORMAT_ESMFMESH, ESMF_MESHLOC_ELEMENT, ESMF_TYPEKIND_R8 + use ESMF , only: ESMF_REGION_TOTAL, ESMF_TERMORDER_SRCSEQ + use pio , only: pio_openfile, pio_closefile, pio_nowrite, file_desc_t + use shr_pio_mod , only: shr_pio_getiosys, shr_pio_getiotype + 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 shr_sys_mod , only: shr_sys_abort + use shr_nl_mod , only: shr_nl_find_group_name + use nuopc_shr_methods , only: chkerr + use mod_blom_pio , only: pio_iosystem, pio_iotype, blom_pio_getdata + use mod_forcing , only: rivflx_stream + use mod_output_forcing, only: output_forcing + use mo_param1_bgc , only: nriv,irdin,irdip,irsi,iralk,iriron,irdoc,irdet + use mod_xc + + implicit none + private + + public :: ocn_stream_rivin_init ! position datasets for dynamic rivin + + character(len=*), parameter :: sourcefile = & + __FILE__ + +!============================================================================== +contains +!============================================================================== + + subroutine ocn_stream_rivin_init(mesh_model, omask, rc) + + ! input/output variables + type(ESMF_Mesh) , intent(in) :: mesh_model + real , intent(in) :: omask(:,:) ! land/ocean mask (1=ocean) + integer , intent(out) :: rc + + ! local variables + integer :: nu_nml ! unit for namelist file + integer :: nml_error ! namelist i/o error flag + integer :: ierr ! error status + type(file_desc_t) :: pioid + character(len=CL) :: filein + character(len=CL) :: stream_rivin_mesh_filename + character(len=CL) :: stream_rivin_data_filename + character(len=CL) :: stream_rivin_map_filename + character(len=CL) :: stream_rivin_varname + integer :: errstat + type(ESMF_MESH) :: mesh_file + type(ESMF_Field) :: field_file + type(ESMF_Field) :: field_model + type(ESMF_RouteHandle) :: rhandle_file2model + integer :: srcMaskValue = 0 ! ignore source points where the mesh mask is 0 + integer :: dstMaskValue = -987987 ! don't ingore any destination points + integer :: srcTermProcessing_Value = 0 + real(r8), pointer :: data_file(:) + real(r8), pointer :: data_model(:) + integer :: nf,i,j,n + integer :: jjcpl + integer :: index + character(len=CL) :: output_filename + logical :: first_time = .true. + character(len=3) :: fldnames(7) + integer :: indices(7) + integer :: rcode + logical :: checkflag = .false. + real(r8), parameter :: mval = -1.e12_r8 + real(r8), parameter :: fval = -1.e13_r8 + character(*), parameter :: subName = "('ocn_stream_rivin_init')" + !----------------------------------------------------------------------- + + namelist /stream_rivin/ & + stream_rivin_data_filename, & + stream_rivin_mesh_filename, & + stream_rivin_map_filename, & + stream_rivin_varname + + rc = ESMF_SUCCESS + + fldnames = (/'DIN', 'DIP', 'DSi', 'DIC', 'Fe ', 'DOC', 'DET'/) + indices = (/irdin, irdip, irsi, iralk, iriron, irdoc, irdet/) + + ! Default values for namelist + stream_rivin_data_filename(:) = ' ' + stream_rivin_mesh_filename = ' ' + stream_rivin_map_filename = ' ' + stream_rivin_varname = ' ' + + ! Read stream_rivin namelist + if (mnproc == 1) then + filein = "ocn_in" + open( newunit=nu_nml, file=trim(filein), status='old', iostat=nml_error ) + if (nml_error /= 0) then + call shr_sys_abort(subName//': ERROR opening '//trim(filein)//errMsg(sourcefile, __LINE__)) + end if + call shr_nl_find_group_name(nu_nml, 'stream_rivin', status=nml_error) + if (nml_error == 0) then + read(nu_nml, nml=stream_rivin, iostat=nml_error) + if (nml_error /= 0) then + call shr_sys_abort(' ERROR reading stream_rivin namelist: '//errMsg(sourcefile, __LINE__)) + end if + else + call shr_sys_abort(' ERROR finding stream_rivin namelist: '//errMsg(sourcefile, __LINE__)) + end if + close(nu_nml) + endif + + call xcbcst(stream_rivin_data_filename) + call xcbcst(stream_rivin_mesh_filename) + call xcbcst(stream_rivin_varname) + + ! Write out info + if (mnproc == 1) then + write(lp,'(a)' ) ' ' + write(lp,'(a)' ) 'stream rivin settings:' + write(lp,'(a,a)' ) ' stream_rivin_data_filename = ',trim(stream_rivin_data_filename) + write(lp,'(a,a)' ) ' stream_rivin_mesh_filename = ',trim(stream_rivin_mesh_filename) + write(lp,'(a,a)' ) ' stream_rivin_map_filename = ',trim(stream_rivin_map_filename) + write(lp,'(a,a,a)') ' stream_rivin_varnames = ',trim(stream_rivin_varname) + write(lp,'(a)' ) ' ' + endif + + ! allocate field to hold rivin fields + allocate (rivflx_stream(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy,nriv),stat=errstat) + if(errstat /= 0) stop 'not enough memory rivflx allocation' + rivflx_stream(:,:,:) = 0.0 + + ! read riverine nutrient fluxes from file + if (mnproc.eq.1) then + write(lp,*) '' + write(lp,'(a)') 'ini_read_rivin: read riverine nutrients from ',trim(stream_rivin_data_filename) + endif + + ! Read in the mesh with the above distgrid + mesh_file = ESMF_MeshCreate(filename=stream_rivin_mesh_filename, fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) + if (ChkErr(rc, __LINE__, sourcefile)) return + + ! Creat fields used in remapping + field_file = ESMF_FieldCreate(mesh_file, ESMF_TYPEKIND_R8, meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (ChkErr(rc,__LINE__,sourcefile)) return + field_model = ESMF_FieldCreate(mesh_model, ESMF_TYPEKIND_R8, meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (ChkErr(rc,__LINE__,sourcefile)) return + + ! Compute a route handle between the model mesh and data mesh + call ESMF_FieldSMMStore(field_file, field_model, stream_rivin_map_filename, routehandle=rhandle_file2model, & + ignoreUnmatchedIndices=.true., srcTermProcessing=srcTermProcessing_Value, rc=rc) + if (chkerr(rc,__LINE__,sourcefile)) return + + ! Open input data file + rcode = pio_openfile(pio_iosystem, pioid, pio_iotype, trim(stream_rivin_data_filename), pio_nowrite) + + do nf = 1,size(fldnames) + + ! Get pointer to data_file array + call ESMF_FieldGet(field_file, farrayptr=data_file, rc=rc) + if (chkerr(rc,__LINE__,sourcefile)) return + + ! Read the data (fill in the data_file array) + call blom_pio_getdata(pioid, fldnames(nf), mesh_file, data_file, rc=rc) + if (chkerr(rc,__LINE__,sourcefile)) return + + ! Regrid the data + call ESMF_FieldRegrid(field_file, field_model, routehandle=rhandle_file2model, & + termorderflag=ESMF_TERMORDER_SRCSEQ, checkflag=checkflag, zeroregion=ESMF_REGION_TOTAL, rc=rc) + if (chkerr(rc,__LINE__,sourcefile)) return + + ! Get pointer to mapped field + call ESMF_FieldGet(field_model, farrayptr=data_model, rc=rc) + if (chkerr(rc,__LINE__,sourcefile)) return + + ! Fill in the blom data structures + if (nreg == 2 .and. nproc == jpr) then + jjcpl = jj - 1 + else + jjcpl = jj + endif + + index = indices(nf) + do j = 1, jjcpl + do i = 1, ii + if (ip(i,j) == 0) then + rivflx_stream(i,j,index) = mval + elseif (cplmsk(i,j) == 0) then + rivflx_stream(i,j,index) = fval + else + n = (j - 1)*ii + i + rivflx_stream(i,j,index) = data_file(n) + end if + ! set flux to zero over land + if (omask(i,j) < 0.5) then + rivflx_stream(i,j,index) = 0.0 + end if + end do + end do + + if (first_time) then + output_filename = 'frivin_stream_'//trim(fldnames(nf))//'.nc' + call output_forcing(trim(output_filename), trim(fldnames(nf)), rivflx_stream(:,:,index)) + end if + end do + + first_time = .false. + + end subroutine ocn_stream_rivin_init + +#endif +end module ocn_stream_rivin diff --git a/hamocc/mo_hamocc_init.F90 b/hamocc/mo_hamocc_init.F90 index c873416a..4980e656 100644 --- a/hamocc/mo_hamocc_init.F90 +++ b/hamocc/mo_hamocc_init.F90 @@ -38,7 +38,8 @@ subroutine hamocc_init(read_rest,rstfnm_hamocc) use mod_time, only: date,baclin use mod_xc, only: ii,jj,kk,idm,jdm,kdm,nbdy,isp,ifp,ilp,mnproc,lp,xchalt use mod_grid, only: plon,plat - use mod_forcing, only: use_stream_swa + use mod_forcing, only: use_stream_swa, use_stream_rivin, use_stream_dust, use_stream_ndep, & + use_stream_oalk use mod_tracers, only: ntrbgc,ntr,itrbgc,trc use mo_control_bgc, only: bgc_namelist,get_bgc_namelist,do_ndep,do_rivinpt,do_oalk, & do_sedspinup,sedspin_yr_s,sedspin_yr_e,sedspin_ncyc, & @@ -200,12 +201,22 @@ subroutine hamocc_init(read_rest,rstfnm_hamocc) ! ! --- Initialise reading of input data (dust, n-deposition, river, etc.) ! - call ini_read_fedep(idm,jdm,omask) - call ini_read_ndep(idm,jdm) - call ini_read_rivin(idm,jdm,omask) - call ini_read_oafx(idm,jdm,bgc_dx,bgc_dy,plat,omask) - if (use_BROMO .and. .not. use_stream_swa) then - call ini_swa_clim(idm,jdm,omask) + if (.not. use_stream_dust) then + call ini_read_fedep(omask) + end if + if (.not. use_stream_ndep) then + call ini_read_ndep(idm,jdm) + end if + if (.not. use_stream_rivin) then + call ini_read_rivin(omask) + end if + if (.not. use_stream_oalk) then + call ini_read_oafx(idm,jdm,bgc_dx,bgc_dy,plat,omask) + end if + if (.not. use_stream_swa) then + if (use_BROMO) then + call ini_swa_clim(idm,jdm,omask) + end if endif call ini_pi_ph(idm,jdm,omask) ! diff --git a/hamocc/mo_hamocc_step.F90 b/hamocc/mo_hamocc_step.F90 index ec0124be..bc438cbd 100644 --- a/hamocc/mo_hamocc_step.F90 +++ b/hamocc/mo_hamocc_step.F90 @@ -35,12 +35,11 @@ subroutine hamocc_step(m,n,mm,nn,k1m,k1n) use mod_state, only: temp,saln use mod_forcing, only: swa,slp,abswnd,atmco2,flxco2,flxdms,atmbrf,flxbrf, & atmn2o,flxn2o,atmnh3,flxnh3,atmnhxdep,atmnoydep, & - use_stream_dust, use_stream_oalk, & - dust_stream, ndep_stream, oalk_stream + use_stream_dust, use_stream_oalk, use_stream_ndep, & + dust_stream, ndep_stream, oalk_stream, rivflx_stream use mod_seaice, only: ficem use mo_bgcmean, only: nbgc,bgcwrt, diagfq_bgc,diagmon_bgc,diagann_bgc use mo_intfcblom, only: bgc_dx,bgc_dy,bgc_dp,bgc_rho,omask,blom2hamocc,hamocc2blom - use mo_read_rivin, only: rivflx use mo_read_fedep, only: get_fedep use mo_read_ndep, only: get_ndep use mo_read_oafx, only: get_oafx @@ -77,10 +76,12 @@ subroutine hamocc_step(m,n,mm,nn,k1m,k1n) call get_fedep(date%month, dust_stream) end if - if (.not. allocated(ndep_stream)) then - allocate(ndep_stream(1-nbdy:idm+nbdy, 1-nbdy:jdm+nbdy, nndep)) + if (.not. use_stream_ndep) then + if (.not. allocated(ndep_stream)) then + allocate(ndep_stream(1-nbdy:idm+nbdy, 1-nbdy:jdm+nbdy, nndep)) + end if + call get_ndep(date%year, date%month, omask, ndep_stream, atmnhxdep, atmnoydep) end if - call get_ndep(date%year, date%month, omask, ndep_stream, atmnhxdep, atmnoydep) if (.not. use_stream_oalk) then call get_oafx(date%year, date%month, omask, oalk_stream) @@ -90,12 +91,13 @@ subroutine hamocc_step(m,n,mm,nn,k1m,k1n) call get_pi_ph(idm,jdm,date%month) end if - call hamocc4bcm(idm, jdm, kdm, nbdy, & - date%year, date%month, date%day, ldtday, bgc_dx, bgc_dy, bgc_dp, & - bgc_rho, plat, omask, dust_stream, rivflx, ndep_stream, oalk_stream, & - pi_ph, swa, ficem, slp, abswnd, & - temp(1-nbdy,1-nbdy,1+nn), saln(1-nbdy,1-nbdy,1+nn), & - atmco2, flxco2, flxdms, atmbrf, flxbrf, & + call hamocc4bcm(idm, jdm, kdm, nbdy, & + date%year, date%month, date%day, ldtday, bgc_dx, bgc_dy, bgc_dp, & + bgc_rho, plat, omask, & + dust_stream, rivflx_stream, ndep_stream, oalk_stream, & + pi_ph, swa, ficem, slp, abswnd, & + temp(1-nbdy,1-nbdy,1+nn), saln(1-nbdy,1-nbdy,1+nn), & + atmco2, flxco2, flxdms, atmbrf, flxbrf, & atmn2o, flxn2o, atmnh3, flxnh3) ! --- accumulate fields and write output diff --git a/hamocc/mo_read_fedep.F90 b/hamocc/mo_read_fedep.F90 index 35455bad..40580374 100644 --- a/hamocc/mo_read_fedep.F90 +++ b/hamocc/mo_read_fedep.F90 @@ -43,7 +43,7 @@ module mo_read_fedep contains - subroutine ini_read_fedep(kpie,kpje,omask) + subroutine ini_read_fedep(omask) !*********************************************************************************************** ! Initialise the iron deposition module, read in the iron (dust) data set. @@ -52,14 +52,12 @@ subroutine ini_read_fedep(kpie,kpje,omask) !*********************************************************************************************** use netcdf, only: nf90_noerr,nf90_nowrite,nf90_close,nf90_open - use mod_xc, only: mnproc,xchalt + use mod_xc, only: mnproc,xchalt,idm,jdm use mo_control_bgc, only: io_stdo_bgc use mo_netcdf_bgcrw, only: read_netcdf_var ! Arguments - integer, intent(in) :: kpie ! 1st dimension of model grid. - integer, intent(in) :: kpje ! 2nd dimension of model grid. - real, intent(in) :: omask(kpie,kpje) ! land/ocean mask (1=ocean) + real, intent(in) :: omask(idm,jdm) ! land/ocean mask (1=ocean) ! Local variables integer :: i,j,l @@ -75,12 +73,12 @@ subroutine ini_read_fedep(kpie,kpje,omask) if (mnproc.eq.1) then write(io_stdo_bgc,*)'Memory allocation for variable dustflx ...' - write(io_stdo_bgc,*)'First dimension : ',kpie - write(io_stdo_bgc,*)'Second dimension : ',kpje + write(io_stdo_bgc,*)'First dimension : ',idm + write(io_stdo_bgc,*)'Second dimension : ',jdm write(io_stdo_bgc,*)'Third dimension : 12' endif - allocate (dustflx(kpie,kpje,12),stat=errstat) + allocate (dustflx(idm,jdm,12),stat=errstat) if(errstat.ne.0) stop 'not enough memory dustflx' dustflx(:,:,:) = 0.0 @@ -112,8 +110,8 @@ subroutine ini_read_fedep(kpie,kpje,omask) ! set flux to zero over land do l=1,12 - do j=1,kpje - do i=1,kpie + do j=1,jdm + do i=1,idm if(omask(i,j).lt.0.5) dustflx(i,j,l) = 0.0 enddo enddo diff --git a/hamocc/mo_read_rivin.F90 b/hamocc/mo_read_rivin.F90 index b939d59b..ef177fc9 100644 --- a/hamocc/mo_read_rivin.F90 +++ b/hamocc/mo_read_rivin.F90 @@ -21,8 +21,8 @@ module mo_read_rivin !************************************************************************************************* ! Routines for reading riverine nutrient and carbon input data ! - ! Riverine carbon and nutrient input is activated through a logical switch 'do_rivinpt' read - ! from HAMOCC's bgcnml namelist. When coupled to NorESM, this is achieved by setting + ! Riverine carbon and nutrient input is activated through a logical switch 'do_rivinpt' read + ! from HAMOCC's bgcnml namelist. When coupled to NorESM, this is achieved by setting ! BLOM_RIVER_NUTRIENTS to TRUE in env_run.xml. ! ! The model attempts to read nutrient fluxes from a NetCDF file @@ -50,8 +50,9 @@ module mo_read_rivin ! data are seperated into two distinct modules !************************************************************************************************* - use dimensions, only: idm,jdm - use mod_xc , only: nbdy + use dimensions, only: idm,jdm + use mod_xc , only: nbdy + use mod_forcing, only: rivflx_stream ! here will holds input data as read from file implicit none private @@ -61,9 +62,7 @@ module mo_read_rivin ! File name (incl. full path) for input data, set through namelist in mo_hamocc_init character(len=256), public :: rivinfile = '' - real, allocatable, public :: rivflx(:,:,:) ! holds input data as read from file - ! arrays for reading riverine inputs on the model grid real, dimension(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy) :: riv_DIN2d real, dimension(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy) :: riv_DIP2d real, dimension(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy) :: riv_DSI2d @@ -74,21 +73,19 @@ module mo_read_rivin contains - subroutine ini_read_rivin(kpie,kpje,omask) + subroutine ini_read_rivin(omask) !*********************************************************************************************** ! Initialise reading of riverine input data (GNEWS 2000) !*********************************************************************************************** - use mod_xc, only: mnproc + use mod_xc, only: mnproc,idm,jdm use mod_dia, only: iotype use mod_nctools, only: ncfopn,ncread,ncfcls use mo_control_bgc, only: io_stdo_bgc,do_rivinpt use mo_param1_bgc, only: nriv,irdin,irdip,irsi,iralk,iriron,irdoc,irdet ! Arguments - integer, intent(in) :: kpie ! 1st dimension of model grid. - integer , intent(in) :: kpje ! 2nd dimension of model grid. - real, intent(in) :: omask(kpie,kpje) ! ocean mask + real, intent(in) :: omask(idm,jdm) ! ocean mask ! local variables integer :: i,j,errstat,dummymask(2) @@ -103,14 +100,14 @@ subroutine ini_read_rivin(kpie,kpje,omask) ! Allocate field to hold river fluxes if (mnproc.eq.1) then write(io_stdo_bgc,*)'Memory allocation for variable rivflx ...' - write(io_stdo_bgc,*)'First dimension : ',kpie - write(io_stdo_bgc,*)'Second dimension : ',kpje + write(io_stdo_bgc,*)'First dimension : ',idm + write(io_stdo_bgc,*)'Second dimension : ',jdm write(io_stdo_bgc,*)'Third dimension : ',nriv endif - allocate (rivflx(kpie,kpje,nriv),stat=errstat) + allocate (rivflx_stream(idm,jdm,nriv),stat=errstat) if(errstat.ne.0) stop 'not enough memory rivflx' - rivflx(:,:,:) = 0.0 + rivflx_stream(:,:,:) = 0.0 ! Return if riverine input is turned off if (.not. do_rivinpt) then @@ -126,6 +123,7 @@ subroutine ini_read_rivin(kpie,kpje,omask) write(io_stdo_bgc,*) '' write(io_stdo_bgc,'(a)') 'ini_read_rivin: read riverine nutrients from ',trim(rivinfile) endif + call ncfopn(trim(rivinfile),'r',' ',1,iotype) call ncread('DIN',riv_DIN2d,dummymask,0,0.) call ncread('DIP',riv_DIP2d,dummymask,0,0.) @@ -136,18 +134,16 @@ subroutine ini_read_rivin(kpie,kpje,omask) call ncread('DET',riv_idet2d,dummymask,0,0.) call ncfcls - do j=1,kpje - do i=1,kpie + do j=1,jdm + do i=1,idm if (omask(i,j) > 0.5) then - - rivflx(i,j,irdin) = riv_DIN2d(i,j) - rivflx(i,j,irdip) = riv_DIP2d(i,j) - rivflx(i,j,irsi) = riv_DSI2d(i,j) - rivflx(i,j,iralk) = riv_DIC2d(i,j) - rivflx(i,j,iriron) = riv_DFe2d(i,j) - rivflx(i,j,irdoc) = riv_idoc2d(i,j) - rivflx(i,j,irdet) = riv_idet2d(i,j) - + rivflx_stream(i,j,irdin) = riv_DIN2d(i,j) + rivflx_stream(i,j,irdip) = riv_DIP2d(i,j) + rivflx_stream(i,j,irsi) = riv_DSI2d(i,j) + rivflx_stream(i,j,iralk) = riv_DIC2d(i,j) + rivflx_stream(i,j,iriron) = riv_DFe2d(i,j) + rivflx_stream(i,j,irdoc) = riv_idoc2d(i,j) + rivflx_stream(i,j,irdet) = riv_idet2d(i,j) endif enddo enddo diff --git a/phy/mod_forcing.F90 b/phy/mod_forcing.F90 index 882b58a9..ee22b188 100644 --- a/phy/mod_forcing.F90 +++ b/phy/mod_forcing.F90 @@ -99,17 +99,26 @@ module mod_forcing logical :: use_stream_relaxation ! If true, use nuopc stream relaxation capability real(r8), dimension(1 - nbdy:idm + nbdy, 1 - nbdy:jdm + nbdy) :: & - swa_stream, & ! absorbed short wave radiation flux - dust_stream, & ! iron dust deposition flux (hamocc) - chloro_stream, & ! chlorophyll concentration (hamocc) - oalk_stream ! alkalinization flux (hamocc) - real(r8), allocatable :: ndep_stream(:,:,:) ! nitrogen deposition fluxes - real(r8), allocatable :: rivin_stream(:,:,:) ! riverine fluxes - - logical :: use_stream_dust ! If true, use nuopc stream dust capability (hamocc only) - logical :: use_stream_chloro ! If true, use nuopc stream chlorophyll capability - logical :: use_stream_swa ! If true, use nuopc stream swa capability - logical :: use_stream_oalk ! If true, use nuopc stream for ocean alkalinity capability + swa_stream ! absorbed short wave radiation flux + logical :: use_stream_swa = .false. ! If true, use nuopc stream swa capability + + real(r8), dimension(1 - nbdy:idm + nbdy, 1 - nbdy:jdm + nbdy) :: & + dust_stream ! iron dust deposition flux (hamocc) + logical :: use_stream_dust = .false. ! If true, use nuopc stream dust capability (hamocc only) + + real(r8), dimension(1 - nbdy:idm + nbdy, 1 - nbdy:jdm + nbdy) :: & + chloro_stream ! chlorophyll concentration (hamocc) + logical :: use_stream_chloro = .false. ! If true, use nuopc stream chlorophyll capability + + real(r8), dimension(1 - nbdy:idm + nbdy, 1 - nbdy:jdm + nbdy) :: & + oalk_stream ! alkalinization flux (hamocc) + logical :: use_stream_oalk = .false. ! If true, use nuopc stream for ocean alkalinity capability + + real(r8), allocatable :: rivflx_stream(:,:,:) ! riverine fluxes + logical :: use_stream_rivin = .false. ! If true, use nuopc input for rivin fluxes + + real(r8), allocatable :: ndep_stream(:,:,:) ! nitrogen deposition fluxes + logical :: use_stream_ndep = .false. ! If true, use nuopc input for rivin fluxes ! Variables related to balancing the freshwater forcing budget. real(r8) :: & @@ -195,9 +204,9 @@ module mod_forcing ustar, ustarb, ustar3, wstar3, buoyfl, t_sw_nonloc, t_rs_nonloc, & s_br_nonloc, s_rs_nonloc, inivar_forcing, fwbbal, & sss_stream, sst_stream, ice_stream, & - dust_stream, chloro_stream, swa_stream, ndep_stream, oalk_stream, & + dust_stream, chloro_stream, swa_stream, ndep_stream, oalk_stream, rivflx_stream, & use_stream_relaxation, use_stream_swa, use_stream_dust, use_stream_chloro, & - use_stream_oalk + use_stream_oalk, use_stream_rivin, use_stream_ndep contains diff --git a/phy/mod_rdlim.F90 b/phy/mod_rdlim.F90 index a62726bf..a0cc9bd9 100644 --- a/phy/mod_rdlim.F90 +++ b/phy/mod_rdlim.F90 @@ -46,7 +46,8 @@ module mod_rdlim srxlim, srxbal, sprfac, & srxlim, srxbal, sprfac, & use_stream_relaxation, use_stream_swa, & - use_stream_chloro, use_stream_dust, use_stream_oalk + use_stream_chloro, use_stream_dust, use_stream_oalk, & + use_stream_rivin, use_stream_ndep use mod_swabs, only: swamth, jwtype, chlopt, ccfile use mod_diffusion, only: readnml_diffusion use mod_eddtra, only: mlrmth, ce, cl, tau_mlr, tau_growing_hbl, & @@ -147,7 +148,7 @@ subroutine rdlim() csdiag, & rstfrq,rstfmt,rstcmp,iotype,& use_stream_relaxation, use_stream_swa, use_stream_chloro, & - use_stream_dust, use_stream_oalk + use_stream_dust, use_stream_oalk, use_stream_rivin, use_stream_ndep ! read limits namelist @@ -251,11 +252,13 @@ subroutine rdlim() write (lp,*) 'RSTFMT',RSTFMT write (lp,*) 'RSTCMP',RSTCMP write (lp,*) 'IOTYPE',IOTYPE - write (lp,*) 'USE_STREAM_CHLORO',use_stream_chloro write (lp,*) 'USE_STREAM_RELAXATION',use_stream_relaxation - write (lp,*) 'USE_STREAM_SWA',use_stream_swa + write (lp,*) 'USE_STREAM_CHLORO',use_stream_chloro write (lp,*) 'USE_STREAM_DUST',use_stream_dust write (lp,*) 'USE_STREAM_OALK',use_stream_oalk + write (lp,*) 'USE_STREAM_RIVIN',use_stream_rivin + write (lp,*) 'USE_STREAM_NDEP',use_stream_ndep + write (lp,*) 'USE_STREAM_SWA',use_stream_swa write (lp,*) end if From 41c5fc83599cb6bc45131c0e42c6ae1bf347dea6 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Sat, 21 Sep 2024 23:11:55 +0200 Subject: [PATCH 09/16] added riverine nutrient forcing in nuopc --- cime_config/buildnml | 3 +- cime_config/namelist_definition_blom.xml | 53 +++++++++++++++++ drivers/nuopc/mod_blom_pio.F90 | 2 +- drivers/nuopc/ocn_comp_nuopc.F90 | 13 +++-- drivers/nuopc/ocn_stream_dust.F90 | 4 +- drivers/nuopc/ocn_stream_rivin.F90 | 72 +++++++++++++++--------- drivers/nuopc/ocn_stream_swa.F90 | 4 +- hamocc/mo_hamocc_init.F90 | 1 + phy/mod_forcing.F90 | 32 ++++++----- phy/mod_rdlim.F90 | 2 + 10 files changed, 134 insertions(+), 52 deletions(-) diff --git a/cime_config/buildnml b/cime_config/buildnml index d4464ab5..c9bcde5e 100755 --- a/cime_config/buildnml +++ b/cime_config/buildnml @@ -257,7 +257,8 @@ def buildnml(case, caseroot, compname): # Create BLOM namelist groups=['limits','diffusion','merdia','secdia','diaphy', - 'stream_sss','stream_sst','stream_swa','stream_dust','stream_oafx'] + 'stream_sss','stream_sst','stream_swa','stream_dust', + 'stream_oalk', 'stream_rivin'] groups.append('cwmod') diff --git a/cime_config/namelist_definition_blom.xml b/cime_config/namelist_definition_blom.xml index f999d217..adcdd6aa 100644 --- a/cime_config/namelist_definition_blom.xml +++ b/cime_config/namelist_definition_blom.xml @@ -9063,4 +9063,57 @@ + + + + + + logical + limits + limits + + .false. + .false. + + if .true., use NUOPC stream ocean river nutrient capability + + + + char + stream_rivin + stream_rivin + stream mesh file + + + $DIN_LOC_ROOT/share/meshes/tnx1v4_20170601_cdf5_ESMFmesh.nc + + + + char(10) + stream_rivin + stream_rivin + + file name(s) containing rivin deposition data + + + + $DIN_LOC_ROOT//ocn/blom/bndcon/river_nutrients_GNEWS2000_tnx1v4_20170820.nc + + + + char + stream_rivin + stream_rivin + + map of stream resolution data to model resolution data + + + unset + $DIN_LOC_ROOT/cpl/cpl6/map_r05_to_tnx1v4_e1000r300_170609.nc + $DIN_LOC_ROOT/cpl/cpl6/map_r05_to_tnx0.5v1_e300r100_20240702.nc + unset + unset + + + diff --git a/drivers/nuopc/mod_blom_pio.F90 b/drivers/nuopc/mod_blom_pio.F90 index 6057153d..94883a11 100644 --- a/drivers/nuopc/mod_blom_pio.F90 +++ b/drivers/nuopc/mod_blom_pio.F90 @@ -5,7 +5,6 @@ module mod_blom_pio use mod_types , only : r8, r4 use mod_xc , only : lp, mnproc use shr_pio_mod , only : shr_pio_getiosys, shr_pio_getiotype, shr_pio_getioformat - use shr_pio_mod , only : shr_pio_getiosys, shr_pio_getiotype use shr_sys_mod , only : shr_sys_abort use nuopc_shr_methods , only : chkerr @@ -35,6 +34,7 @@ subroutine blom_pio_init() pio_ioformat = shr_pio_getioformat('OCN') end subroutine blom_pio_init + !=============================================================== subroutine blom_pio_getdata(pioid, varname, mesh_i, data_i, rc) ! input/output variables diff --git a/drivers/nuopc/ocn_comp_nuopc.F90 b/drivers/nuopc/ocn_comp_nuopc.F90 index 00239741..fd973430 100644 --- a/drivers/nuopc/ocn_comp_nuopc.F90 +++ b/drivers/nuopc/ocn_comp_nuopc.F90 @@ -50,7 +50,8 @@ module ocn_comp_nuopc use mod_cesm, only: runid_cesm, runtyp_cesm, ocn_cpl_dt_cesm use mod_config, only: inst_index, inst_name, inst_suffix use mod_time, only: blom_time - use mod_forcing, only: srxday, trxday, use_stream_dust, use_stream_swa + use mod_forcing, only: srxday, trxday, use_stream_dust, use_stream_swa, & + use_stream_rivin use mod_swabs, only: swamth, chlopt use mod_constants, only: epsilt use mod_blom_init, only: blom_init @@ -58,13 +59,13 @@ module ocn_comp_nuopc use mod_fill_global, only: fill_global use mod_restart, only: restart_write use mod_xc, only: mnproc, xcstop + use mod_blom_pio, only: blom_pio_init use ocn_stream_sss, only: ocn_stream_sss_init, ocn_stream_sss_interp use ocn_stream_sst, only: ocn_stream_sst_init, ocn_stream_sst_interp use ocn_stream_swa, only: ocn_stream_swa_init, ocn_stream_swa_interp use ocn_stream_chloro, only: ocn_stream_chloro_init, ocn_stream_chloro_interp #ifdef HAMOCC use mo_control_bgc, only: use_BROMO - use mo_intfcblom, only: omask use ocn_stream_dust, only: ocn_stream_dust_init, ocn_stream_dust_interp use ocn_stream_rivin, only: ocn_stream_rivin_init #endif @@ -727,6 +728,9 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) flds_scalar_name, flds_scalar_num, rc) if (ChkErr(rc, __LINE__, u_FILE_u)) return + ! Initialize pio subsystem + call blom_pio_init() + ! Initialize sdat for relaxation to sss if appropriate if (srxday > epsilt) then call ocn_stream_sss_init(Emesh, clock, rc) @@ -766,6 +770,7 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) if (ChkErr(rc, __LINE__, u_FILE_u)) return end if + ! Initialize time independent riverine nutrient input if (use_stream_rivin) then call ocn_stream_rivin_init(Emesh, rc) if (ChkErr(rc, __LINE__, u_FILE_u)) return @@ -943,13 +948,13 @@ subroutine ModelAdvance(gcomp, rc) #ifdef HAMOCC ! Advance swa stream input if appropriate if (use_stream_swa) then - call ocn_stream_swa_interp(clock, omask, rc) + call ocn_stream_swa_interp(clock, rc) if (ChkErr(rc, __LINE__, u_FILE_u)) return end if ! Advance dust stream input if appropriate if (use_stream_dust) then - call ocn_stream_dust_interp(clock, omask, rc) + call ocn_stream_dust_interp(clock, rc) if (ChkErr(rc, __LINE__, u_FILE_u)) return end if #endif diff --git a/drivers/nuopc/ocn_stream_dust.F90 b/drivers/nuopc/ocn_stream_dust.F90 index 7756f194..19818517 100644 --- a/drivers/nuopc/ocn_stream_dust.F90 +++ b/drivers/nuopc/ocn_stream_dust.F90 @@ -13,6 +13,7 @@ module ocn_stream_dust use shr_log_mod , only : errMsg => shr_log_errMsg use shr_sys_mod , only : shr_sys_abort use mod_forcing , only : dust_stream + use mo_intfcblom , only : omask use mod_xc implicit none @@ -177,7 +178,7 @@ subroutine ocn_stream_dust_init(model_mesh, model_clock, rc) end subroutine ocn_stream_dust_init !================================================================ - subroutine ocn_stream_dust_interp(model_clock, omask, rc) + subroutine ocn_stream_dust_interp(model_clock, rc) use dshr_strdata_mod , only : shr_strdata_advance use dshr_methods_mod , only : dshr_fldbun_getfldptr @@ -187,7 +188,6 @@ subroutine ocn_stream_dust_interp(model_clock, omask, rc) ! input/output variables type(ESMF_Clock), intent(in) :: model_clock - real , intent(in) :: omask(:,:) ! land/ocean mask (1=ocean) integer , intent(out) :: rc ! local variables diff --git a/drivers/nuopc/ocn_stream_rivin.F90 b/drivers/nuopc/ocn_stream_rivin.F90 index ef739327..f1d52fd5 100644 --- a/drivers/nuopc/ocn_stream_rivin.F90 +++ b/drivers/nuopc/ocn_stream_rivin.F90 @@ -21,9 +21,11 @@ module ocn_stream_rivin !************************************************************************************************* use ESMF , only: ESMF_Finalize, ESMF_LogFoundError - use ESMF , only: ESMF_Mesh, ESMF_MeshCreate, ESMF_FieldCreate + use ESMF , only: ESMF_Mesh, ESMF_MeshCreate, ESMF_MeshGet, ESMF_FieldCreate use ESMF , only: ESMF_Field, ESMF_FieldCreate, ESMF_FieldGet - use ESMF , only: ESMF_FieldSMMStore, ESMF_FieldRegrid, ESMF_RouteHandle + use ESMF , only: ESMF_FieldSMMStore, ESMF_FieldRedistStore + use ESMF , only: ESMF_FieldRegrid, ESMF_RouteHandle + use ESMF , only: ESMF_DistGrid, ESMF_DistGridGet use ESMF , only: ESMF_SUCCESS, ESMF_LOGERR_PASSTHRU, ESMF_END_ABORT use ESMF , only: ESMF_FILEFORMAT_ESMFMESH, ESMF_MESHLOC_ELEMENT, ESMF_TYPEKIND_R8 use ESMF , only: ESMF_REGION_TOTAL, ESMF_TERMORDER_SRCSEQ @@ -38,6 +40,7 @@ module ocn_stream_rivin use mod_forcing , only: rivflx_stream use mod_output_forcing, only: output_forcing use mo_param1_bgc , only: nriv,irdin,irdip,irsi,iralk,iriron,irdoc,irdet + use mo_intfcblom , only : omask use mod_xc implicit none @@ -52,11 +55,10 @@ module ocn_stream_rivin contains !============================================================================== - subroutine ocn_stream_rivin_init(mesh_model, omask, rc) + subroutine ocn_stream_rivin_init(mesh_model, rc) ! input/output variables type(ESMF_Mesh) , intent(in) :: mesh_model - real , intent(in) :: omask(:,:) ! land/ocean mask (1=ocean) integer , intent(out) :: rc ! local variables @@ -71,19 +73,21 @@ subroutine ocn_stream_rivin_init(mesh_model, omask, rc) character(len=CL) :: stream_rivin_varname integer :: errstat type(ESMF_MESH) :: mesh_file + type(ESMF_DistGrid) :: distgrid type(ESMF_Field) :: field_file type(ESMF_Field) :: field_model type(ESMF_RouteHandle) :: rhandle_file2model integer :: srcMaskValue = 0 ! ignore source points where the mesh mask is 0 integer :: dstMaskValue = -987987 ! don't ingore any destination points integer :: srcTermProcessing_Value = 0 - real(r8), pointer :: data_file(:) - real(r8), pointer :: data_model(:) + real(r8), pointer :: dataptr_file(:) + real(r8), pointer :: dataptr_model(:) + real(r8), allocatable :: data_file(:) integer :: nf,i,j,n + integer :: lsize integer :: jjcpl integer :: index character(len=CL) :: output_filename - logical :: first_time = .true. character(len=3) :: fldnames(7) integer :: indices(7) integer :: rcode @@ -96,8 +100,7 @@ subroutine ocn_stream_rivin_init(mesh_model, omask, rc) namelist /stream_rivin/ & stream_rivin_data_filename, & stream_rivin_mesh_filename, & - stream_rivin_map_filename, & - stream_rivin_varname + stream_rivin_map_filename rc = ESMF_SUCCESS @@ -108,7 +111,6 @@ subroutine ocn_stream_rivin_init(mesh_model, omask, rc) stream_rivin_data_filename(:) = ' ' stream_rivin_mesh_filename = ' ' stream_rivin_map_filename = ' ' - stream_rivin_varname = ' ' ! Read stream_rivin namelist if (mnproc == 1) then @@ -131,7 +133,7 @@ subroutine ocn_stream_rivin_init(mesh_model, omask, rc) call xcbcst(stream_rivin_data_filename) call xcbcst(stream_rivin_mesh_filename) - call xcbcst(stream_rivin_varname) + call xcbcst(stream_rivin_map_filename) ! Write out info if (mnproc == 1) then @@ -140,7 +142,6 @@ subroutine ocn_stream_rivin_init(mesh_model, omask, rc) write(lp,'(a,a)' ) ' stream_rivin_data_filename = ',trim(stream_rivin_data_filename) write(lp,'(a,a)' ) ' stream_rivin_mesh_filename = ',trim(stream_rivin_mesh_filename) write(lp,'(a,a)' ) ' stream_rivin_map_filename = ',trim(stream_rivin_map_filename) - write(lp,'(a,a,a)') ' stream_rivin_varnames = ',trim(stream_rivin_varname) write(lp,'(a)' ) ' ' endif @@ -155,7 +156,7 @@ subroutine ocn_stream_rivin_init(mesh_model, omask, rc) write(lp,'(a)') 'ini_read_rivin: read riverine nutrients from ',trim(stream_rivin_data_filename) endif - ! Read in the mesh with the above distgrid + ! Read in the mesh mesh_file = ESMF_MeshCreate(filename=stream_rivin_mesh_filename, fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) if (ChkErr(rc, __LINE__, sourcefile)) return @@ -166,30 +167,49 @@ subroutine ocn_stream_rivin_init(mesh_model, omask, rc) if (ChkErr(rc,__LINE__,sourcefile)) return ! Compute a route handle between the model mesh and data mesh - call ESMF_FieldSMMStore(field_file, field_model, stream_rivin_map_filename, routehandle=rhandle_file2model, & - ignoreUnmatchedIndices=.true., srcTermProcessing=srcTermProcessing_Value, rc=rc) - if (chkerr(rc,__LINE__,sourcefile)) return + if (stream_rivin_map_filename == 'unset') then + ! create a redist route handle + call ESMF_FieldRedistStore(field_file, field_model, routehandle=rhandle_file2model, & + ignoreUnmatchedIndices = .true., rc=rc) + if (chkerr(rc,__LINE__,sourcefile)) return + else + ! create a route handle from the input mapping file + call ESMF_FieldSMMStore(field_file, field_model, stream_rivin_map_filename, routehandle=rhandle_file2model, & + ignoreUnmatchedIndices=.true., srcTermProcessing=srcTermProcessing_Value, rc=rc) + if (chkerr(rc,__LINE__,sourcefile)) return + end if + + ! Determine local size of input data from file + call ESMF_MeshGet(mesh_file, elementdistGrid=distgrid, rc=rc) + if (ChkErr(rc,__LINE__,sourcefile)) return + call ESMF_DistGridGet(distgrid, localDe=0, elementCount=lsize, rc=rc) + if (ChkErr(rc,__LINE__,sourcefile)) return + + ! Allocate data_file + allocate(data_file(lsize), stat=errstat) + if (errstat /= 0) stop 'not enough memory for data_fileallocation' ! Open input data file rcode = pio_openfile(pio_iosystem, pioid, pio_iotype, trim(stream_rivin_data_filename), pio_nowrite) do nf = 1,size(fldnames) - ! Get pointer to data_file array - call ESMF_FieldGet(field_file, farrayptr=data_file, rc=rc) - if (chkerr(rc,__LINE__,sourcefile)) return - ! Read the data (fill in the data_file array) call blom_pio_getdata(pioid, fldnames(nf), mesh_file, data_file, rc=rc) if (chkerr(rc,__LINE__,sourcefile)) return + ! Get pointer to data_file array and fill it in with data_file valus + call ESMF_FieldGet(field_file, farrayptr=dataptr_file, rc=rc) + if (chkerr(rc,__LINE__,sourcefile)) return + dataptr_file(:) = data_file(:) + ! Regrid the data call ESMF_FieldRegrid(field_file, field_model, routehandle=rhandle_file2model, & termorderflag=ESMF_TERMORDER_SRCSEQ, checkflag=checkflag, zeroregion=ESMF_REGION_TOTAL, rc=rc) if (chkerr(rc,__LINE__,sourcefile)) return ! Get pointer to mapped field - call ESMF_FieldGet(field_model, farrayptr=data_model, rc=rc) + call ESMF_FieldGet(field_model, farrayptr=dataptr_model, rc=rc) if (chkerr(rc,__LINE__,sourcefile)) return ! Fill in the blom data structures @@ -208,7 +228,7 @@ subroutine ocn_stream_rivin_init(mesh_model, omask, rc) rivflx_stream(i,j,index) = fval else n = (j - 1)*ii + i - rivflx_stream(i,j,index) = data_file(n) + rivflx_stream(i,j,index) = dataptr_model(n) end if ! set flux to zero over land if (omask(i,j) < 0.5) then @@ -217,13 +237,11 @@ subroutine ocn_stream_rivin_init(mesh_model, omask, rc) end do end do - if (first_time) then - output_filename = 'frivin_stream_'//trim(fldnames(nf))//'.nc' - call output_forcing(trim(output_filename), trim(fldnames(nf)), rivflx_stream(:,:,index)) - end if + output_filename = 'frivin_stream_'//trim(fldnames(nf))//'.nc' + call output_forcing(trim(output_filename), trim(fldnames(nf)), rivflx_stream(:,:,index)) end do - first_time = .false. + call pio_closefile(pioid) end subroutine ocn_stream_rivin_init diff --git a/drivers/nuopc/ocn_stream_swa.F90 b/drivers/nuopc/ocn_stream_swa.F90 index 45c52744..6a0d13f7 100644 --- a/drivers/nuopc/ocn_stream_swa.F90 +++ b/drivers/nuopc/ocn_stream_swa.F90 @@ -12,6 +12,7 @@ module ocn_stream_swa 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 shr_sys_mod , only : shr_sys_abort + use mo_intfcblom , only : omask use mod_xc implicit none @@ -186,7 +187,7 @@ subroutine ocn_stream_swa_init(model_mesh, model_clock, rc) end subroutine ocn_stream_swa_init !================================================================ - subroutine ocn_stream_swa_interp(model_clock, omask, rc) + subroutine ocn_stream_swa_interp(model_clock, rc) use dshr_strdata_mod , only : shr_strdata_advance use dshr_methods_mod , only : dshr_fldbun_getfldptr @@ -194,7 +195,6 @@ subroutine ocn_stream_swa_interp(model_clock, omask, rc) ! input/output variables type(ESMF_Clock), intent(in) :: model_clock - real , intent(in) :: omask(:,:) ! land/ocean mask (1=ocean) integer , intent(out) :: rc ! local variables diff --git a/hamocc/mo_hamocc_init.F90 b/hamocc/mo_hamocc_init.F90 index 4980e656..b7c4cc1e 100644 --- a/hamocc/mo_hamocc_init.F90 +++ b/hamocc/mo_hamocc_init.F90 @@ -207,6 +207,7 @@ subroutine hamocc_init(read_rest,rstfnm_hamocc) if (.not. use_stream_ndep) then call ini_read_ndep(idm,jdm) end if + write(6,*)'DEBUG: use_stream_rivin = ',use_stream_rivin if (.not. use_stream_rivin) then call ini_read_rivin(omask) end if diff --git a/phy/mod_forcing.F90 b/phy/mod_forcing.F90 index ee22b188..79e7adfa 100644 --- a/phy/mod_forcing.F90 +++ b/phy/mod_forcing.F90 @@ -93,32 +93,34 @@ module mod_forcing sssclm ! Sea-surface salinity [g kg-1]. real(r8), dimension(1 - nbdy:idm + nbdy, 1 - nbdy:jdm + nbdy) :: & - sst_stream, & ! Sea-surface temperature [deg C] from stream data. - ice_stream, & ! Sea-ice concentration [] from stream data. - sss_stream ! Sea-surface salinity [g kg-1] from stream data. + sst_stream, & ! Sea-surface temperature [deg C] from stream data. + ice_stream, & ! Sea-ice concentration [] from stream data. + sss_stream ! Sea-surface salinity [g kg-1] from stream data. logical :: use_stream_relaxation ! If true, use nuopc stream relaxation capability real(r8), dimension(1 - nbdy:idm + nbdy, 1 - nbdy:jdm + nbdy) :: & - swa_stream ! absorbed short wave radiation flux - logical :: use_stream_swa = .false. ! If true, use nuopc stream swa capability + swa_stream ! absorbed short wave radiation flux + logical :: use_stream_swa ! If true, use nuopc stream swa capability real(r8), dimension(1 - nbdy:idm + nbdy, 1 - nbdy:jdm + nbdy) :: & - dust_stream ! iron dust deposition flux (hamocc) - logical :: use_stream_dust = .false. ! If true, use nuopc stream dust capability (hamocc only) + dust_stream ! iron dust deposition flux (hamocc) + logical :: use_stream_dust ! If true, use nuopc stream dust capability (hamocc only) real(r8), dimension(1 - nbdy:idm + nbdy, 1 - nbdy:jdm + nbdy) :: & - chloro_stream ! chlorophyll concentration (hamocc) - logical :: use_stream_chloro = .false. ! If true, use nuopc stream chlorophyll capability + chloro_stream ! chlorophyll concentration (hamocc) + logical :: use_stream_chloro ! If true, use nuopc stream chlorophyll capability real(r8), dimension(1 - nbdy:idm + nbdy, 1 - nbdy:jdm + nbdy) :: & - oalk_stream ! alkalinization flux (hamocc) - logical :: use_stream_oalk = .false. ! If true, use nuopc stream for ocean alkalinity capability + oalk_stream ! alkalinization flux (hamocc) + logical :: use_stream_oalk ! If true, use nuopc stream for ocean alkalinity capability - real(r8), allocatable :: rivflx_stream(:,:,:) ! riverine fluxes - logical :: use_stream_rivin = .false. ! If true, use nuopc input for rivin fluxes + real(r8), allocatable :: & + rivflx_stream(:,:,:) ! riverine fluxes + logical :: use_stream_rivin ! If true, use nuopc input for rivin fluxes - real(r8), allocatable :: ndep_stream(:,:,:) ! nitrogen deposition fluxes - logical :: use_stream_ndep = .false. ! If true, use nuopc input for rivin fluxes + real(r8), allocatable :: & + ndep_stream(:,:,:) ! nitrogen deposition fluxes + logical :: use_stream_ndep ! If true, use nuopc input for rivin fluxes ! Variables related to balancing the freshwater forcing budget. real(r8) :: & diff --git a/phy/mod_rdlim.F90 b/phy/mod_rdlim.F90 index a0cc9bd9..381fcd91 100644 --- a/phy/mod_rdlim.F90 +++ b/phy/mod_rdlim.F90 @@ -346,6 +346,8 @@ subroutine rdlim() call xcbcst(use_stream_swa) call xcbcst(use_stream_dust) call xcbcst(use_stream_oalk) + call xcbcst(use_stream_rivin) + call xcbcst(use_stream_ndep) ! resolve options select case (trim(wavsrc)) From 199aabb583254cf5cda4a28f7ad48b6fa0979386 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Mon, 23 Sep 2024 10:14:11 +0200 Subject: [PATCH 10/16] add namelist for stream ndep --- cime_config/namelist_definition_blom.xml | 70 ++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/cime_config/namelist_definition_blom.xml b/cime_config/namelist_definition_blom.xml index adcdd6aa..0af3dd63 100644 --- a/cime_config/namelist_definition_blom.xml +++ b/cime_config/namelist_definition_blom.xml @@ -9116,4 +9116,74 @@ + + + + + + char + stream_ndep + stream_ndep + stream mesh file + + $DIN_LOC_ROOT/atm/cam/sst/sst_HadOIBl_bc_1x1_clim_c101029_ESMFmesh_120520.nc + + + + char(10) + stream_ndep + stream_ndep + + file name(s) containing nitrogen deposition data + + + $DIN_LOC_ROOT/lnd/clm2/ndepdata/fndep_clm_WACCM6_CMIP6piControl001_y21-50avg_1850monthly_0.95x1.25_c180802.nc + + + + char(2) + stream_ndep + stream_ndep + + variable name on stream file + + + NDEP_NHx_month, NDEP_NOy_month + + + + integer + stream_ndep + stream_ndep + + First year in stream to use + + + 1 + + + + integer + stream_ndep + stream_ndep + + Last year in stream to use + + + 1 + + + + integer + stream_ndep + stream_ndep + + Align stream_year_first with this model year + + + 1 + + + + From ea2c59ed5184afbc3924194bb6ac43b368af7cb5 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Mon, 23 Sep 2024 10:41:28 +0200 Subject: [PATCH 11/16] added new ocn_stream_ndep.F90 - still have to prove it works --- drivers/nuopc/ocn_stream_ndep.F90 | 268 ++++++++++++++++++++++++++++++ 1 file changed, 268 insertions(+) create mode 100644 drivers/nuopc/ocn_stream_ndep.F90 diff --git a/drivers/nuopc/ocn_stream_ndep.F90 b/drivers/nuopc/ocn_stream_ndep.F90 new file mode 100644 index 00000000..1b2465cd --- /dev/null +++ b/drivers/nuopc/ocn_stream_ndep.F90 @@ -0,0 +1,268 @@ +module ocn_stream_ndep + + !----------------------------------------------------------------------- + ! Contains methods for reading in nitrogen deposition data file + ! Also includes functions for dynamic ndep file handling and + ! interpolation. + !----------------------------------------------------------------------- + ! + use ESMF , only : ESMF_Clock, ESMF_Mesh, ESMF_Time, ESMF_ClockGet, ESMF_TimeGet + 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 shr_sys_mod , only : shr_sys_abort + use mod_fill_global , only : fill_global + use mod_xc + + implicit none + private + + public :: ocn_stream_ndep_init ! position datasets for dynamic ndep + public :: ocn_stream_ndep_interp ! interpolates between two years of ndep file data + + type(shr_strdata_type) :: sdat_ndep ! input data stream + character(len=CS) :: stream_ndep_varname(2) + + integer, parameter :: nfiles_max = 100 ! maximum number of stream files + character(len=*), parameter :: sourcefile = & + __FILE__ + +!============================================================================== +contains +!============================================================================== + + subroutine ocn_stream_ndep_init(model_mesh, model_clock, rc) + ! + ! Initialize data stream information. + + ! Uses + use shr_nl_mod , only: shr_nl_find_group_name + use dshr_strdata_mod , only: shr_strdata_init_from_inline + + ! input/output variables + type(ESMF_CLock), intent(in) :: model_clock + type(ESMF_Mesh) , intent(in) :: model_mesh + integer , intent(out) :: rc + + ! local variables + integer :: nu_nml ! unit for namelist file + integer :: nml_error ! namelist i/o error flag + integer :: ierr ! error status + character(len=CL) :: filein ! ocn namelist file + 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 + character(len=CL) :: stream_ndep_mesh_filename + character(len=CL) :: stream_ndep_data_filename(nfiles_max) + character(len=CL), allocatable :: stream_filenames(:) + character(len=4) :: tmpchar + integer :: nfiles + integer :: nf + integer :: errstat + character(*), parameter :: subName = "('ocn_stream_ndep_init')" + !----------------------------------------------------------------------- + + namelist /stream_ndep/ & + stream_ndep_data_filename, & + stream_ndep_mesh_filename, & + stream_ndep_varname, & + stream_ndep_year_first, & + stream_ndep_year_last, & + stream_ndep_year_align + + rc = ESMF_SUCCESS + + ! Default values for namelist + stream_ndep_data_filename(:) = ' ' + stream_ndep_mesh_filename = ' ' + stream_ndep_varname = ' ' + 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 + + ! Read stream_ndep namelist + if (mnproc == 1) then + filein = "ocn_in" + open( newunit=nu_nml, file=trim(filein), status='old', iostat=nml_error ) + if (nml_error /= 0) then + call shr_sys_abort(subName//': ERROR opening '//trim(filein)//errMsg(sourcefile, __LINE__)) + end if + call shr_nl_find_group_name(nu_nml, 'stream_ndep', status=nml_error) + if (nml_error == 0) then + read(nu_nml, nml=stream_ndep, iostat=nml_error) + if (nml_error /= 0) then + call shr_sys_abort(' ERROR reading stream_ndep namelist: '//errMsg(sourcefile, __LINE__)) + end if + else + call shr_sys_abort(' ERROR finding stream_ndep namelist: '//errMsg(sourcefile, __LINE__)) + end if + close(nu_nml) + endif + + do nf = 1,nfiles_max + call xcbcst(stream_ndep_data_filename(nf)) + end do + call xcbcst(stream_ndep_mesh_filename) + do nf = 1,2 + call xcbcst(stream_ndep_varname(nf)) + end do + call xcbcst(stream_ndep_year_first) + call xcbcst(stream_ndep_year_last) + call xcbcst(stream_ndep_year_align) + + ! Determine the actual number and filenames of stream files that will be used + nfiles = 0 + do nf = 1,nfiles_max + if (stream_ndep_data_filename(nf) == '') then + exit + else + nfiles = nfiles + 1 + end if + end do + allocate(stream_filenames(nfiles), stat=errstat) + if (errstat /= 0) then + write(lp,*) 'Failed to allocate stream_filenames' + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + end if + do nf = 1,nfiles + stream_filenames(nf) = trim(stream_ndep_data_filename(nf)) + end do + + ! Write out info + if (mnproc == 1) then + write(lp,'(a)' ) ' ' + write(lp,'(a,i8)') 'stream ndep settings:' + do nf = 1,nfiles + write(tmpchar,'(i0)') nf + write(lp,'(a,a)' ) ' stream_ndep_data_filename('//trim(tmpchar)//') = ',trim(stream_filenames(nf)) + end do + write(lp,'(a,a)' ) ' stream_ndep_mesh_filename = ',trim(stream_ndep_mesh_filename) + write(lp,'(a,a,a)') ' stream_ndep_varnames = ',trim(stream_ndep_varname(1)),trim(stream_ndep_varname(2)) + write(lp,'(a,i8)') ' stream_ndep_year_first = ',stream_ndep_year_first + write(lp,'(a,i8)') ' stream_ndep_year_last = ',stream_ndep_year_last + write(lp,'(a,i8)') ' stream_ndep_year_align = ',stream_ndep_year_align + write(lp,'(a)' ) ' ' + endif + + ! Initialize the cdeps data type sdat_ndep + call shr_strdata_init_from_inline(sdat_ndep, & + my_task = mnproc, & + logunit = lp, & + compname = 'OCN', & + model_clock = model_clock, & + model_mesh = model_mesh, & + stream_meshfile = trim(stream_ndep_mesh_filename), & + stream_filenames = stream_filenames, & + stream_yearFirst = stream_ndep_year_first, & + stream_yearLast = stream_ndep_year_last, & + stream_yearAlign = stream_ndep_year_align, & + stream_fldlistFile = stream_ndep_varname, & + stream_fldlistModel = stream_ndep_varname, & + stream_lev_dimname = 'null', & + stream_mapalgo = 'bilinear', & + stream_offset = 0, & + stream_taxmode = 'cycle', & + stream_dtlimit = 1.0e30_r8, & + stream_tintalgo = 'linear', & + stream_name = 'Sea surface temperature ', & + rc = rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + + end subroutine ocn_stream_ndep_init + + !================================================================ + subroutine ocn_stream_ndep_interp(model_clock, rc) + + use dshr_strdata_mod , only : shr_strdata_advance + use dshr_methods_mod , only : dshr_fldbun_getfldptr + use mod_forcing , only : ndep_stream, ice_stream + use mod_checksum , only : csdiag, chksummsk + + ! input/output variables + type(ESMF_Clock), intent(in) :: model_clock + integer , intent(out) :: rc + + ! local variables + type(ESMF_Time) :: date + integer :: i,j,n + integer :: jjcpl + 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 :: dataptr1(:) + real(r8), pointer :: dataptr2(:) + real(r8), parameter :: mval = -1.e12_r8 + real(r8), parameter :: fval = -1.e13_r8 + !----------------------------------------------------------------------- + + ! Advance sdat stream + call ESMF_ClockGet( model_clock, currTime=date, rc=rc ) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + call ESMF_TimeGet(date, yy=year, mm=mon, dd=day, s=sec, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + mcdate = year*10000 + mon*100 + day + + call shr_strdata_advance(sdat_ndep, ymd=mcdate, tod=sec, logunit=lp, istr='ndepdyn', rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + + ! Get pointer for stream data that is time and spatially interpolated to model time and grid + call dshr_fldbun_getFldPtr(sdat_ndep%pstrm(1)%fldbun_model, stream_ndep_varname(1), fldptr1=dataptr1, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + call dshr_fldbun_getFldPtr(sdat_ndep%pstrm(1)%fldbun_model, stream_ndep_varname(2), fldptr1=dataptr2, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + + ! Set the j-extent of the local ocean domain to be exchanged. Needed because of + ! duplication of the last global domain row when using a tripolar grid. + ! dimensions.F is created at build time by the bash script blom_dimensions and contains + + ! Now sum them for for ndep_stream + if (nreg == 2 .and. nproc == jpr) then + jjcpl = jj - 1 + else + jjcpl = jj + endif + + do j = 1, jjcpl + do i = 1, ii + if (ip(i,j) == 0) then + ndep_stream(i,j) = mval + elseif (cplmsk(i,j) == 0) then + ndep_stream(i,j) = fval + else + n = (j - 1)*ii + i + ndep_stream(i,j) = dataptr1(n) + dataptr2(n) + end if + end do + end do + + call fill_global(mval, fval, halo_ps, ndep_stream(1-nbdy,1-nbdy)) + + if (csdiag) then + if (mnproc == 1) then + write(lp,*) 'ocn_stream_ndep_interp:' + end if + call chksummsk(ndep_stream(1-nbdy,1-nbdy),ip,1,'ndep_stream') + end if + + end subroutine ocn_stream_ndep_interp + +end module ocn_stream_ndep From f09ca8a3c9da777a1ded633ee66a6bb23e51677d Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Tue, 24 Sep 2024 20:07:07 +0200 Subject: [PATCH 12/16] many updates to clean up stream generation --- drivers/nuopc/ocn_stream_ndep.F90 | 268 ------------------ ..._stream_swa.F90 => ocn_stream_swaclim.F90} | 0 hamocc/mo_read_fedep.F90 | 52 ++-- hamocc/mo_read_rivin.F90 | 48 ++-- phy/mod_blom_init.F90 | 5 +- phy/mod_swabs.F90 | 3 +- 6 files changed, 48 insertions(+), 328 deletions(-) delete mode 100644 drivers/nuopc/ocn_stream_ndep.F90 rename drivers/nuopc/{ocn_stream_swa.F90 => ocn_stream_swaclim.F90} (100%) diff --git a/drivers/nuopc/ocn_stream_ndep.F90 b/drivers/nuopc/ocn_stream_ndep.F90 deleted file mode 100644 index 1b2465cd..00000000 --- a/drivers/nuopc/ocn_stream_ndep.F90 +++ /dev/null @@ -1,268 +0,0 @@ -module ocn_stream_ndep - - !----------------------------------------------------------------------- - ! Contains methods for reading in nitrogen deposition data file - ! Also includes functions for dynamic ndep file handling and - ! interpolation. - !----------------------------------------------------------------------- - ! - use ESMF , only : ESMF_Clock, ESMF_Mesh, ESMF_Time, ESMF_ClockGet, ESMF_TimeGet - 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 shr_sys_mod , only : shr_sys_abort - use mod_fill_global , only : fill_global - use mod_xc - - implicit none - private - - public :: ocn_stream_ndep_init ! position datasets for dynamic ndep - public :: ocn_stream_ndep_interp ! interpolates between two years of ndep file data - - type(shr_strdata_type) :: sdat_ndep ! input data stream - character(len=CS) :: stream_ndep_varname(2) - - integer, parameter :: nfiles_max = 100 ! maximum number of stream files - character(len=*), parameter :: sourcefile = & - __FILE__ - -!============================================================================== -contains -!============================================================================== - - subroutine ocn_stream_ndep_init(model_mesh, model_clock, rc) - ! - ! Initialize data stream information. - - ! Uses - use shr_nl_mod , only: shr_nl_find_group_name - use dshr_strdata_mod , only: shr_strdata_init_from_inline - - ! input/output variables - type(ESMF_CLock), intent(in) :: model_clock - type(ESMF_Mesh) , intent(in) :: model_mesh - integer , intent(out) :: rc - - ! local variables - integer :: nu_nml ! unit for namelist file - integer :: nml_error ! namelist i/o error flag - integer :: ierr ! error status - character(len=CL) :: filein ! ocn namelist file - 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 - character(len=CL) :: stream_ndep_mesh_filename - character(len=CL) :: stream_ndep_data_filename(nfiles_max) - character(len=CL), allocatable :: stream_filenames(:) - character(len=4) :: tmpchar - integer :: nfiles - integer :: nf - integer :: errstat - character(*), parameter :: subName = "('ocn_stream_ndep_init')" - !----------------------------------------------------------------------- - - namelist /stream_ndep/ & - stream_ndep_data_filename, & - stream_ndep_mesh_filename, & - stream_ndep_varname, & - stream_ndep_year_first, & - stream_ndep_year_last, & - stream_ndep_year_align - - rc = ESMF_SUCCESS - - ! Default values for namelist - stream_ndep_data_filename(:) = ' ' - stream_ndep_mesh_filename = ' ' - stream_ndep_varname = ' ' - 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 - - ! Read stream_ndep namelist - if (mnproc == 1) then - filein = "ocn_in" - open( newunit=nu_nml, file=trim(filein), status='old', iostat=nml_error ) - if (nml_error /= 0) then - call shr_sys_abort(subName//': ERROR opening '//trim(filein)//errMsg(sourcefile, __LINE__)) - end if - call shr_nl_find_group_name(nu_nml, 'stream_ndep', status=nml_error) - if (nml_error == 0) then - read(nu_nml, nml=stream_ndep, iostat=nml_error) - if (nml_error /= 0) then - call shr_sys_abort(' ERROR reading stream_ndep namelist: '//errMsg(sourcefile, __LINE__)) - end if - else - call shr_sys_abort(' ERROR finding stream_ndep namelist: '//errMsg(sourcefile, __LINE__)) - end if - close(nu_nml) - endif - - do nf = 1,nfiles_max - call xcbcst(stream_ndep_data_filename(nf)) - end do - call xcbcst(stream_ndep_mesh_filename) - do nf = 1,2 - call xcbcst(stream_ndep_varname(nf)) - end do - call xcbcst(stream_ndep_year_first) - call xcbcst(stream_ndep_year_last) - call xcbcst(stream_ndep_year_align) - - ! Determine the actual number and filenames of stream files that will be used - nfiles = 0 - do nf = 1,nfiles_max - if (stream_ndep_data_filename(nf) == '') then - exit - else - nfiles = nfiles + 1 - end if - end do - allocate(stream_filenames(nfiles), stat=errstat) - if (errstat /= 0) then - write(lp,*) 'Failed to allocate stream_filenames' - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then - call ESMF_Finalize(endflag=ESMF_END_ABORT) - end if - end if - do nf = 1,nfiles - stream_filenames(nf) = trim(stream_ndep_data_filename(nf)) - end do - - ! Write out info - if (mnproc == 1) then - write(lp,'(a)' ) ' ' - write(lp,'(a,i8)') 'stream ndep settings:' - do nf = 1,nfiles - write(tmpchar,'(i0)') nf - write(lp,'(a,a)' ) ' stream_ndep_data_filename('//trim(tmpchar)//') = ',trim(stream_filenames(nf)) - end do - write(lp,'(a,a)' ) ' stream_ndep_mesh_filename = ',trim(stream_ndep_mesh_filename) - write(lp,'(a,a,a)') ' stream_ndep_varnames = ',trim(stream_ndep_varname(1)),trim(stream_ndep_varname(2)) - write(lp,'(a,i8)') ' stream_ndep_year_first = ',stream_ndep_year_first - write(lp,'(a,i8)') ' stream_ndep_year_last = ',stream_ndep_year_last - write(lp,'(a,i8)') ' stream_ndep_year_align = ',stream_ndep_year_align - write(lp,'(a)' ) ' ' - endif - - ! Initialize the cdeps data type sdat_ndep - call shr_strdata_init_from_inline(sdat_ndep, & - my_task = mnproc, & - logunit = lp, & - compname = 'OCN', & - model_clock = model_clock, & - model_mesh = model_mesh, & - stream_meshfile = trim(stream_ndep_mesh_filename), & - stream_filenames = stream_filenames, & - stream_yearFirst = stream_ndep_year_first, & - stream_yearLast = stream_ndep_year_last, & - stream_yearAlign = stream_ndep_year_align, & - stream_fldlistFile = stream_ndep_varname, & - stream_fldlistModel = stream_ndep_varname, & - stream_lev_dimname = 'null', & - stream_mapalgo = 'bilinear', & - stream_offset = 0, & - stream_taxmode = 'cycle', & - stream_dtlimit = 1.0e30_r8, & - stream_tintalgo = 'linear', & - stream_name = 'Sea surface temperature ', & - rc = rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then - call ESMF_Finalize(endflag=ESMF_END_ABORT) - end if - - end subroutine ocn_stream_ndep_init - - !================================================================ - subroutine ocn_stream_ndep_interp(model_clock, rc) - - use dshr_strdata_mod , only : shr_strdata_advance - use dshr_methods_mod , only : dshr_fldbun_getfldptr - use mod_forcing , only : ndep_stream, ice_stream - use mod_checksum , only : csdiag, chksummsk - - ! input/output variables - type(ESMF_Clock), intent(in) :: model_clock - integer , intent(out) :: rc - - ! local variables - type(ESMF_Time) :: date - integer :: i,j,n - integer :: jjcpl - 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 :: dataptr1(:) - real(r8), pointer :: dataptr2(:) - real(r8), parameter :: mval = -1.e12_r8 - real(r8), parameter :: fval = -1.e13_r8 - !----------------------------------------------------------------------- - - ! Advance sdat stream - call ESMF_ClockGet( model_clock, currTime=date, rc=rc ) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then - call ESMF_Finalize(endflag=ESMF_END_ABORT) - end if - call ESMF_TimeGet(date, yy=year, mm=mon, dd=day, s=sec, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then - call ESMF_Finalize(endflag=ESMF_END_ABORT) - end if - mcdate = year*10000 + mon*100 + day - - call shr_strdata_advance(sdat_ndep, ymd=mcdate, tod=sec, logunit=lp, istr='ndepdyn', rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then - call ESMF_Finalize(endflag=ESMF_END_ABORT) - end if - - ! Get pointer for stream data that is time and spatially interpolated to model time and grid - call dshr_fldbun_getFldPtr(sdat_ndep%pstrm(1)%fldbun_model, stream_ndep_varname(1), fldptr1=dataptr1, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then - call ESMF_Finalize(endflag=ESMF_END_ABORT) - end if - call dshr_fldbun_getFldPtr(sdat_ndep%pstrm(1)%fldbun_model, stream_ndep_varname(2), fldptr1=dataptr2, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then - call ESMF_Finalize(endflag=ESMF_END_ABORT) - end if - - ! Set the j-extent of the local ocean domain to be exchanged. Needed because of - ! duplication of the last global domain row when using a tripolar grid. - ! dimensions.F is created at build time by the bash script blom_dimensions and contains - - ! Now sum them for for ndep_stream - if (nreg == 2 .and. nproc == jpr) then - jjcpl = jj - 1 - else - jjcpl = jj - endif - - do j = 1, jjcpl - do i = 1, ii - if (ip(i,j) == 0) then - ndep_stream(i,j) = mval - elseif (cplmsk(i,j) == 0) then - ndep_stream(i,j) = fval - else - n = (j - 1)*ii + i - ndep_stream(i,j) = dataptr1(n) + dataptr2(n) - end if - end do - end do - - call fill_global(mval, fval, halo_ps, ndep_stream(1-nbdy,1-nbdy)) - - if (csdiag) then - if (mnproc == 1) then - write(lp,*) 'ocn_stream_ndep_interp:' - end if - call chksummsk(ndep_stream(1-nbdy,1-nbdy),ip,1,'ndep_stream') - end if - - end subroutine ocn_stream_ndep_interp - -end module ocn_stream_ndep diff --git a/drivers/nuopc/ocn_stream_swa.F90 b/drivers/nuopc/ocn_stream_swaclim.F90 similarity index 100% rename from drivers/nuopc/ocn_stream_swa.F90 rename to drivers/nuopc/ocn_stream_swaclim.F90 diff --git a/hamocc/mo_read_fedep.F90 b/hamocc/mo_read_fedep.F90 index 40580374..a04d476b 100644 --- a/hamocc/mo_read_fedep.F90 +++ b/hamocc/mo_read_fedep.F90 @@ -43,7 +43,7 @@ module mo_read_fedep contains - subroutine ini_read_fedep(omask) + subroutine ini_read_fedep(kpie,kpje,omask) !*********************************************************************************************** ! Initialise the iron deposition module, read in the iron (dust) data set. @@ -52,16 +52,18 @@ subroutine ini_read_fedep(omask) !*********************************************************************************************** use netcdf, only: nf90_noerr,nf90_nowrite,nf90_close,nf90_open - use mod_xc, only: mnproc,xchalt,idm,jdm + use mod_xc, only: mnproc,xchalt use mo_control_bgc, only: io_stdo_bgc use mo_netcdf_bgcrw, only: read_netcdf_var ! Arguments - real, intent(in) :: omask(idm,jdm) ! land/ocean mask (1=ocean) + integer, intent(in) :: kpie ! 1st dimension of model grid. + integer, intent(in) :: kpje ! 2nd dimension of model grid. + real, intent(in) :: omask(kpie,kpje) ! land/ocean mask (1=ocean) ! Local variables - integer :: i,j,l - integer :: ncid,ncstat,ncvarid,errstat + integer :: i,j,l + integer :: ncid,ncstat,ncvarid,errstat ! allocate field to hold iron deposition fluxes if (mnproc.eq.1) then @@ -73,12 +75,12 @@ subroutine ini_read_fedep(omask) if (mnproc.eq.1) then write(io_stdo_bgc,*)'Memory allocation for variable dustflx ...' - write(io_stdo_bgc,*)'First dimension : ',idm - write(io_stdo_bgc,*)'Second dimension : ',jdm + write(io_stdo_bgc,*)'First dimension : ',kpie + write(io_stdo_bgc,*)'Second dimension : ',kpje write(io_stdo_bgc,*)'Third dimension : 12' endif - allocate (dustflx(idm,jdm,12),stat=errstat) + allocate (dustflx(kpie,kpje,12),stat=errstat) if(errstat.ne.0) stop 'not enough memory dustflx' dustflx(:,:,:) = 0.0 @@ -110,9 +112,11 @@ subroutine ini_read_fedep(omask) ! set flux to zero over land do l=1,12 - do j=1,jdm - do i=1,idm + do j=1,kpje + do i=1,kpie + if(omask(i,j).lt.0.5) dustflx(i,j,l) = 0.0 + enddo enddo enddo @@ -120,7 +124,7 @@ subroutine ini_read_fedep(omask) end subroutine ini_read_fedep - subroutine get_fedep(kplmon, dust) + subroutine get_fedep(kpie,kpje,kplmon,dust) !*********************************************************************************************** ! Get iron (dust) deposition for current month @@ -128,28 +132,12 @@ subroutine get_fedep(kplmon, dust) ! J.Schwinger *NORCE Climate, Bergen* 2020-05-19 !*********************************************************************************************** - use mod_xc, only: idm, jdm, nbdy - use mod_output_forcing, only : output_forcing - + integer, intent(in) :: kpie ! 1st dimension of model grid + integer, intent(in) :: kpje ! 2nd dimension of model grid integer, intent(in) :: kplmon ! current month. - real, intent(out) :: dust(1-nbdy:idm+nbdy, 1-nbdy:jdm+nbdy) ! dust flux for current month - - integer :: i,j - logical :: debug = .true. - logical :: first_time = .true. - - do j = 1,jdm - do i = 1,idm - dust(i,j) = dustflx(i,j,kplmon) - end do - end do - - if (debug) then - if (first_time) then - call output_forcing('fedep_orig.nc', 'fedep', dust) - first_time = .false. - end if - end if + real, intent(out) :: dust(kpie,kpje) ! dust flux for current month + + dust = dustflx(:,:,kplmon) end subroutine get_fedep diff --git a/hamocc/mo_read_rivin.F90 b/hamocc/mo_read_rivin.F90 index ef177fc9..b939d59b 100644 --- a/hamocc/mo_read_rivin.F90 +++ b/hamocc/mo_read_rivin.F90 @@ -21,8 +21,8 @@ module mo_read_rivin !************************************************************************************************* ! Routines for reading riverine nutrient and carbon input data ! - ! Riverine carbon and nutrient input is activated through a logical switch 'do_rivinpt' read - ! from HAMOCC's bgcnml namelist. When coupled to NorESM, this is achieved by setting + ! Riverine carbon and nutrient input is activated through a logical switch 'do_rivinpt' read + ! from HAMOCC's bgcnml namelist. When coupled to NorESM, this is achieved by setting ! BLOM_RIVER_NUTRIENTS to TRUE in env_run.xml. ! ! The model attempts to read nutrient fluxes from a NetCDF file @@ -50,9 +50,8 @@ module mo_read_rivin ! data are seperated into two distinct modules !************************************************************************************************* - use dimensions, only: idm,jdm - use mod_xc , only: nbdy - use mod_forcing, only: rivflx_stream ! here will holds input data as read from file + use dimensions, only: idm,jdm + use mod_xc , only: nbdy implicit none private @@ -62,7 +61,9 @@ module mo_read_rivin ! File name (incl. full path) for input data, set through namelist in mo_hamocc_init character(len=256), public :: rivinfile = '' + real, allocatable, public :: rivflx(:,:,:) ! holds input data as read from file + ! arrays for reading riverine inputs on the model grid real, dimension(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy) :: riv_DIN2d real, dimension(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy) :: riv_DIP2d real, dimension(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy) :: riv_DSI2d @@ -73,19 +74,21 @@ module mo_read_rivin contains - subroutine ini_read_rivin(omask) + subroutine ini_read_rivin(kpie,kpje,omask) !*********************************************************************************************** ! Initialise reading of riverine input data (GNEWS 2000) !*********************************************************************************************** - use mod_xc, only: mnproc,idm,jdm + use mod_xc, only: mnproc use mod_dia, only: iotype use mod_nctools, only: ncfopn,ncread,ncfcls use mo_control_bgc, only: io_stdo_bgc,do_rivinpt use mo_param1_bgc, only: nriv,irdin,irdip,irsi,iralk,iriron,irdoc,irdet ! Arguments - real, intent(in) :: omask(idm,jdm) ! ocean mask + integer, intent(in) :: kpie ! 1st dimension of model grid. + integer , intent(in) :: kpje ! 2nd dimension of model grid. + real, intent(in) :: omask(kpie,kpje) ! ocean mask ! local variables integer :: i,j,errstat,dummymask(2) @@ -100,14 +103,14 @@ subroutine ini_read_rivin(omask) ! Allocate field to hold river fluxes if (mnproc.eq.1) then write(io_stdo_bgc,*)'Memory allocation for variable rivflx ...' - write(io_stdo_bgc,*)'First dimension : ',idm - write(io_stdo_bgc,*)'Second dimension : ',jdm + write(io_stdo_bgc,*)'First dimension : ',kpie + write(io_stdo_bgc,*)'Second dimension : ',kpje write(io_stdo_bgc,*)'Third dimension : ',nriv endif - allocate (rivflx_stream(idm,jdm,nriv),stat=errstat) + allocate (rivflx(kpie,kpje,nriv),stat=errstat) if(errstat.ne.0) stop 'not enough memory rivflx' - rivflx_stream(:,:,:) = 0.0 + rivflx(:,:,:) = 0.0 ! Return if riverine input is turned off if (.not. do_rivinpt) then @@ -123,7 +126,6 @@ subroutine ini_read_rivin(omask) write(io_stdo_bgc,*) '' write(io_stdo_bgc,'(a)') 'ini_read_rivin: read riverine nutrients from ',trim(rivinfile) endif - call ncfopn(trim(rivinfile),'r',' ',1,iotype) call ncread('DIN',riv_DIN2d,dummymask,0,0.) call ncread('DIP',riv_DIP2d,dummymask,0,0.) @@ -134,16 +136,18 @@ subroutine ini_read_rivin(omask) call ncread('DET',riv_idet2d,dummymask,0,0.) call ncfcls - do j=1,jdm - do i=1,idm + do j=1,kpje + do i=1,kpie if (omask(i,j) > 0.5) then - rivflx_stream(i,j,irdin) = riv_DIN2d(i,j) - rivflx_stream(i,j,irdip) = riv_DIP2d(i,j) - rivflx_stream(i,j,irsi) = riv_DSI2d(i,j) - rivflx_stream(i,j,iralk) = riv_DIC2d(i,j) - rivflx_stream(i,j,iriron) = riv_DFe2d(i,j) - rivflx_stream(i,j,irdoc) = riv_idoc2d(i,j) - rivflx_stream(i,j,irdet) = riv_idet2d(i,j) + + rivflx(i,j,irdin) = riv_DIN2d(i,j) + rivflx(i,j,irdip) = riv_DIP2d(i,j) + rivflx(i,j,irsi) = riv_DSI2d(i,j) + rivflx(i,j,iralk) = riv_DIC2d(i,j) + rivflx(i,j,iriron) = riv_DFe2d(i,j) + rivflx(i,j,irdoc) = riv_idoc2d(i,j) + rivflx(i,j,irdet) = riv_idet2d(i,j) + endif enddo enddo diff --git a/phy/mod_blom_init.F90 b/phy/mod_blom_init.F90 index b9ba2e40..1381a22d 100644 --- a/phy/mod_blom_init.F90 +++ b/phy/mod_blom_init.F90 @@ -65,7 +65,6 @@ subroutine blom_init() use mod_restart, only: restart_read use mod_ifdefs, only: use_TRC, use_TKE use mod_tracers_update, only: initrc - use mod_forcing, only: use_stream_swa use netcdf ! Local variables @@ -151,9 +150,7 @@ subroutine blom_init() ! Initialize shortwave radiation absorption ! ------------------------------------------------------------------ - if (.not. use_stream_swa) then - call iniswa - end if + call iniswa ! ------------------------------------------------------------------ ! Initialize second order turbulence closure closure diff --git a/phy/mod_swabs.F90 b/phy/mod_swabs.F90 index b7fcab99..e0416dd2 100644 --- a/phy/mod_swabs.F90 +++ b/phy/mod_swabs.F90 @@ -55,7 +55,6 @@ module mod_swabs use mod_time, only: xmi, l1mi, l2mi, l3mi, l4mi, l5mi use mod_checksum, only: csdiag, chksummsk use mod_intp1d, only: intp1d - use mod_forcing, only: use_stream_swa use netcdf implicit none @@ -182,7 +181,7 @@ subroutine iniswa() end do !$omp end parallel do - else if (swamth == 'chlorophyll' .and. .not. use_stream_swa) then + else if (swamth == 'chlorophyll') then ! Initialize functionality for chlorophyll concentration dependent ! shortwave radiation absorption. From 2124c35be436ecba5e1acb0abf5b9901eaea82f1 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Tue, 24 Sep 2024 20:15:59 +0200 Subject: [PATCH 13/16] many updates to clean up stream generation --- cesm/mod_cesm.F90 | 4 +- cesm/mod_thermf_cesm.F90 | 6 +- cime_config/namelist_definition_blom.xml | 190 +++++++++-------------- drivers/nuopc/ocn_comp_nuopc.F90 | 37 ++--- drivers/nuopc/ocn_import_export.F90 | 13 +- drivers/nuopc/ocn_stream_chloro.F90 | 4 +- drivers/nuopc/ocn_stream_dust.F90 | 20 +-- drivers/nuopc/ocn_stream_rivin.F90 | 16 +- drivers/nuopc/ocn_stream_swaclim.F90 | 186 +++++++++++----------- hamocc/mo_hamocc_init.F90 | 23 ++- hamocc/mo_hamocc_step.F90 | 22 +-- hamocc/mo_read_fedep.F90 | 24 ++- phy/mod_forcing.F90 | 46 +++--- phy/mod_rdlim.F90 | 38 ++--- 14 files changed, 300 insertions(+), 329 deletions(-) diff --git a/cesm/mod_cesm.F90 b/cesm/mod_cesm.F90 index 2ced6195..8c0a3f53 100644 --- a/cesm/mod_cesm.F90 +++ b/cesm/mod_cesm.F90 @@ -33,7 +33,7 @@ module mod_cesm lamult, lasl, ustokes, vstokes, atmco2, atmbrf, & flxdms, flxbrf, & atmn2o, atmnh3, atmnhxdep, atmnoydep, & - use_stream_relaxation, use_stream_swa + use_nuopc_relaxation, use_nuopc_swaclim use mod_ben02, only: initai, rdcsic, rdctsf, fnlzai use mod_rdcsss, only: rdcsss use mod_idarlx, only: idarlx @@ -130,7 +130,7 @@ end subroutine inicon_cesm subroutine inifrc_cesm ! If not using NUOPC stream capability - if (.not. use_stream_relaxation) then + if (.not. use_nuopc_relaxation) then ! If SST restoring is requested prepare interpolation and ! read climatological sea-ice concentration and surface temperature. if (trxday > 0._r8) then diff --git a/cesm/mod_thermf_cesm.F90 b/cesm/mod_thermf_cesm.F90 index 2a60245a..9d4416f7 100644 --- a/cesm/mod_thermf_cesm.F90 +++ b/cesm/mod_thermf_cesm.F90 @@ -38,7 +38,7 @@ module mod_thermf_cesm sswflx, salflx, brnflx, salrlx, ustar, & t_rs_nonloc, s_rs_nonloc, & sss_stream, sst_stream, ice_stream, & - use_stream_relaxation + use_nuopc_relaxation use mod_cesm, only: hmlt, frzpot, mltpot use mod_utility, only: util1, util2, util3, util4 use mod_checksum, only: csdiag, chksummsk @@ -200,7 +200,7 @@ subroutine thermf_cesm(m,n,mm,nn,k1m,k1n) ! If trxday>0 , apply relaxation towards observed sst if (trxday > epsilt ) then - if (use_stream_relaxation) then + if (use_nuopc_relaxation) then sstc = sst_stream(i,j) rice = ice_stream(i,j) sstc = (1.-rice)*max(sstc,tice_f) + rice*tice_f @@ -261,7 +261,7 @@ subroutine thermf_cesm(m,n,mm,nn,k1m,k1n) ! if srxday>0 , apply relaxation towards observed sss if (srxday > epsilt ) then - if (use_stream_relaxation) then + if (use_nuopc_relaxation) then sssc = sss_stream(i,j) else sssc = intp1d(sssclm(i,j,l1mi),sssclm(i,j,l2mi), & diff --git a/cime_config/namelist_definition_blom.xml b/cime_config/namelist_definition_blom.xml index 0af3dd63..255c3b93 100644 --- a/cime_config/namelist_definition_blom.xml +++ b/cime_config/namelist_definition_blom.xml @@ -8674,10 +8674,10 @@ - + - + logical limits limits @@ -8687,6 +8687,78 @@ if .true., use NUOPC stream relaxation capability + + + logical + limits + limits + + .false. + .true. + + if .true., use NUOPC stream capability to obtain chlorophyll concentration + + + + logical + limits + limits + + .false. + .false. + + if .true., use NUOPC to obtain NDEP (always imported to model) + + + + logical + limits + limits + + .false. + .false. + + if .true., use NUOPC stream dust capability + + + + logical + limits + limits + + .false. + .false. + + if .true., use NUOPC stream ocean river nutrient capability + + + + logical + limits + limits + + .false. + .false. + + if .true., use NUOPC stream ocean alkalinity capability + + + + logical + limits + limits + + .false. + .false. + + if .true., use NUOPC stream swabs capability for bromoform + + + + + + + char stream_sss @@ -8827,17 +8899,6 @@ - - logical - limits - limits - - .false. - .false. - - if .true., use NUOPC stream swabs capability - - char stream_swa @@ -8907,17 +8968,6 @@ - - logical - limits - limits - - .false. - .false. - - if .true., use NUOPC stream dust capability - - char stream_dust @@ -8987,17 +9037,6 @@ - - logical - limits - limits - - .false. - .false. - - if .true., use NUOPC stream ocean alkalinity capability - - char stream_oalk @@ -9067,17 +9106,6 @@ - - logical - limits - limits - - .false. - .false. - - if .true., use NUOPC stream ocean river nutrient capability - - char stream_rivin @@ -9116,74 +9144,4 @@ - - - - - - char - stream_ndep - stream_ndep - stream mesh file - - $DIN_LOC_ROOT/atm/cam/sst/sst_HadOIBl_bc_1x1_clim_c101029_ESMFmesh_120520.nc - - - - char(10) - stream_ndep - stream_ndep - - file name(s) containing nitrogen deposition data - - - $DIN_LOC_ROOT/lnd/clm2/ndepdata/fndep_clm_WACCM6_CMIP6piControl001_y21-50avg_1850monthly_0.95x1.25_c180802.nc - - - - char(2) - stream_ndep - stream_ndep - - variable name on stream file - - - NDEP_NHx_month, NDEP_NOy_month - - - - integer - stream_ndep - stream_ndep - - First year in stream to use - - - 1 - - - - integer - stream_ndep - stream_ndep - - Last year in stream to use - - - 1 - - - - integer - stream_ndep - stream_ndep - - Align stream_year_first with this model year - - - 1 - - - - diff --git a/drivers/nuopc/ocn_comp_nuopc.F90 b/drivers/nuopc/ocn_comp_nuopc.F90 index fd973430..f3360c6c 100644 --- a/drivers/nuopc/ocn_comp_nuopc.F90 +++ b/drivers/nuopc/ocn_comp_nuopc.F90 @@ -50,8 +50,7 @@ module ocn_comp_nuopc use mod_cesm, only: runid_cesm, runtyp_cesm, ocn_cpl_dt_cesm use mod_config, only: inst_index, inst_name, inst_suffix use mod_time, only: blom_time - use mod_forcing, only: srxday, trxday, use_stream_dust, use_stream_swa, & - use_stream_rivin + use mod_forcing, only: srxday, trxday use mod_swabs, only: swamth, chlopt use mod_constants, only: epsilt use mod_blom_init, only: blom_init @@ -62,12 +61,12 @@ module ocn_comp_nuopc use mod_blom_pio, only: blom_pio_init use ocn_stream_sss, only: ocn_stream_sss_init, ocn_stream_sss_interp use ocn_stream_sst, only: ocn_stream_sst_init, ocn_stream_sst_interp - use ocn_stream_swa, only: ocn_stream_swa_init, ocn_stream_swa_interp use ocn_stream_chloro, only: ocn_stream_chloro_init, ocn_stream_chloro_interp #ifdef HAMOCC use mo_control_bgc, only: use_BROMO - use ocn_stream_dust, only: ocn_stream_dust_init, ocn_stream_dust_interp use ocn_stream_rivin, only: ocn_stream_rivin_init + use ocn_stream_dust, only: ocn_stream_dust_init, ocn_stream_dust_interp + use ocn_stream_swaclim,only: ocn_stream_swaclim_init, ocn_stream_swaclim_interp #endif implicit none @@ -759,22 +758,16 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) #ifdef HAMOCC ! Initialize sdat for swa climatology if appropriate - if (use_stream_swa) then - call ocn_stream_swa_init(Emesh, clock, rc) - if (ChkErr(rc, __LINE__, u_FILE_u)) return - end if + call ocn_stream_swaclim_init(Emesh, clock, rc) + if (ChkErr(rc, __LINE__, u_FILE_u)) return ! Initialize sdat for dust deposition climatology if appropriate - if (use_stream_dust) then - call ocn_stream_dust_init(Emesh, clock, rc) - if (ChkErr(rc, __LINE__, u_FILE_u)) return - end if + call ocn_stream_dust_init(Emesh, clock, rc) + if (ChkErr(rc, __LINE__, u_FILE_u)) return ! Initialize time independent riverine nutrient input - if (use_stream_rivin) then - call ocn_stream_rivin_init(Emesh, rc) - if (ChkErr(rc, __LINE__, u_FILE_u)) return - end if + call ocn_stream_rivin_init(Emesh, rc) + if (ChkErr(rc, __LINE__, u_FILE_u)) return #endif if (dbug > 5) call ESMF_LogWrite(subname//': done', ESMF_LOGMSG_INFO) @@ -947,16 +940,12 @@ subroutine ModelAdvance(gcomp, rc) #ifdef HAMOCC ! Advance swa stream input if appropriate - if (use_stream_swa) then - call ocn_stream_swa_interp(clock, rc) - if (ChkErr(rc, __LINE__, u_FILE_u)) return - end if + call ocn_stream_swaclim_interp(clock, rc) + if (ChkErr(rc, __LINE__, u_FILE_u)) return ! Advance dust stream input if appropriate - if (use_stream_dust) then - call ocn_stream_dust_interp(clock, rc) - if (ChkErr(rc, __LINE__, u_FILE_u)) return - end if + call ocn_stream_dust_interp(clock, rc) + if (ChkErr(rc, __LINE__, u_FILE_u)) return #endif ! Advance the model a time step. diff --git a/drivers/nuopc/ocn_import_export.F90 b/drivers/nuopc/ocn_import_export.F90 index fdcd1611..9637460c 100644 --- a/drivers/nuopc/ocn_import_export.F90 +++ b/drivers/nuopc/ocn_import_export.F90 @@ -43,7 +43,7 @@ module ocn_import_export rnf_da, rfi_da, fmltfz_da, sfl_da, ztx_da, mty_da, & ustarw_da, slp_da, abswnd_da, ficem_da, lamult_da, & lasl_da, ustokes_da, vstokes_da, atmco2_da, & - l1ci, l2ci + atmnhxdep_da, atmnoydep_da, l1ci, l2ci use mod_utility, only: util1, util2 use mod_checksum, only: csdiag, chksummsk #ifdef HAMOCC @@ -142,6 +142,7 @@ module ocn_import_export index_Faxa_lwdn = -1, & index_Faxa_snow = -1, & index_Faxa_rain = -1, & + index_Faxa_ndep = -1, & index_Sa_pslv = -1, & index_Sa_co2diag = -1, & index_Sa_co2prog = -1 @@ -265,6 +266,8 @@ subroutine blom_advertise_imports(flds_scalar_name, fldsToOcn_num, fldsToOcn, & call fldlist_add(fldsToOcn_num, fldsToOcn, 'Faxa_lwdn' , index_Faxa_lwdn) call fldlist_add(fldsToOcn_num, fldsToOcn, 'Faxa_snow' , index_Faxa_snow) call fldlist_add(fldsToOcn_num, fldsToOcn, 'Faxa_rain' , index_Faxa_rain) + call fldlist_add(fldsToOcn_num, fldsToOcn, 'Faxa_ndep' , index_Faxa_ndep, & + ungridded_lbound=1, ungridded_ubound=2) if (flds_co2a .or. flds_co2c) then call fldlist_add(fldsToOcn_num, fldsToOcn, 'Sa_co2diag' ,index_Sa_co2diag) call fldlist_add(fldsToOcn_num, fldsToOcn, 'Sa_co2prog', index_Sa_co2prog) @@ -874,6 +877,10 @@ subroutine blom_importflds(fldlist_num, fldlist) ! Ice fraction []. ficem_da(i,j,l2ci) = fldlist(index_Si_ifrac)%dataptr(n) + ! Nitrogen deposition [kg m-2 s-1]. + atmnhxdep_da(i,j,l2ci) = fldlist(index_Faxa_ndep)%dataptr2d(n,1)*afac + atmnoydep_da(i,j,l2ci) = fldlist(index_Faxa_ndep)%dataptr2d(n,2)*afac + endif enddo @@ -891,6 +898,8 @@ subroutine blom_importflds(fldlist_num, fldlist) call xctilr(swa_da(1-nbdy,1-nbdy,l2ci), 1,1, 0,0, halo_ps) call xctilr(nsf_da(1-nbdy,1-nbdy,l2ci), 1,1, 0,0, halo_ps) call xctilr(hmlt_da(1-nbdy,1-nbdy,l2ci), 1,1, 0,0, halo_ps) + call xctilr(atmnhxdep_da(1-nbdy,1-nbdy,l2ci), 1,1, 0,0, halo_ps) + call xctilr(atmnoydep_da(1-nbdy,1-nbdy,l2ci), 1,1, 0,0, halo_ps) endif call fill_global(mval, fval, halo_ps, slp_da(1-nbdy,1-nbdy,l2ci)) @@ -1024,6 +1033,8 @@ subroutine blom_importflds(fldlist_num, fldlist) call chksummsk(abswnd_da(1-nbdy,1-nbdy,l2ci),ip,1,'abswnd') call chksummsk( ficem_da(1-nbdy,1-nbdy,l2ci),ip,1,'ficem') call chksummsk(atmco2_da(1-nbdy,1-nbdy,l2ci),ip,1,'atmco2') + call chksummsk(atmnhxdep_da(1-nbdy,1-nbdy,l2ci),ip,1,'atmnhxdep') + call chksummsk(atmnoydep_da(1-nbdy,1-nbdy,l2ci),ip,1,'atmnoydep') endif if (first_call) then diff --git a/drivers/nuopc/ocn_stream_chloro.F90 b/drivers/nuopc/ocn_stream_chloro.F90 index 3a9fe6cb..0c5f925b 100644 --- a/drivers/nuopc/ocn_stream_chloro.F90 +++ b/drivers/nuopc/ocn_stream_chloro.F90 @@ -1,7 +1,9 @@ module ocn_stream_chloro !----------------------------------------------------------------------- - ! Contains methods for reading in chlorophyll forcing file + ! Contains methods for reading in chlorophyll forcing file used in mod_swa.F90 + ! This will replace the reading of chlorophyll if the namelist setting for + ! swamth = 'chlorophyll' in subroutine iniswa. !----------------------------------------------------------------------- ! use ESMF , only : ESMF_Clock, ESMF_Mesh, ESMF_Time, ESMF_ClockGet, ESMF_TimeGet diff --git a/drivers/nuopc/ocn_stream_dust.F90 b/drivers/nuopc/ocn_stream_dust.F90 index 19818517..d6b9b181 100644 --- a/drivers/nuopc/ocn_stream_dust.F90 +++ b/drivers/nuopc/ocn_stream_dust.F90 @@ -12,7 +12,7 @@ module ocn_stream_dust 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 shr_sys_mod , only : shr_sys_abort - use mod_forcing , only : dust_stream + use mod_forcing , only : dust_forcing use mo_intfcblom , only : omask use mod_xc @@ -173,7 +173,7 @@ subroutine ocn_stream_dust_init(model_mesh, model_clock, rc) end if ! allocate field to hold dust fields - dust_stream(:,:) = 0.0 + dust_forcing(:,:) = 0.0 end subroutine ocn_stream_dust_init @@ -182,7 +182,7 @@ subroutine ocn_stream_dust_interp(model_clock, rc) use dshr_strdata_mod , only : shr_strdata_advance use dshr_methods_mod , only : dshr_fldbun_getfldptr - use mod_forcing , only : dust_stream + use mod_forcing , only : dust_forcing use mod_checksum , only : csdiag, chksummsk use mod_output_forcing , only : output_forcing @@ -241,17 +241,17 @@ subroutine ocn_stream_dust_interp(model_clock, rc) do j = 1, jjcpl do i = 1, ii if (ip(i,j) == 0) then - dust_stream(i,j) = mval + dust_forcing(i,j) = mval elseif (cplmsk(i,j) == 0) then - dust_stream(i,j) = fval + dust_forcing(i,j) = fval else n = (j - 1)*ii + i - ! need dust_stream in units of kg/m2/month not kg/m2/s which is in the file - dust_stream(i,j) = dataptr1(n)*seconds_per_month + ! need dust_forcing in units of kg/m2/month not kg/m2/s which is in the file + dust_forcing(i,j) = dataptr1(n)*seconds_per_month end if ! set flux to zero over land if (omask(i,j) < 0.5) then - dust_stream(i,j) = 0.0 + dust_forcing(i,j) = 0.0 end if end do end do @@ -260,11 +260,11 @@ subroutine ocn_stream_dust_interp(model_clock, rc) if (mnproc == 1) then write(lp,*) 'ocn_stream_dust_interp:' end if - call chksummsk(dust_stream,ip,1,'dust_stream') + call chksummsk(dust_forcing,ip,1,'dust_forcing') end if if (first_time) then - call output_forcing('fedep_stream.nc', 'fedep', dust_stream) + call output_forcing('fedep_stream.nc', 'fedep', dust_forcing) first_time = .false. end if diff --git a/drivers/nuopc/ocn_stream_rivin.F90 b/drivers/nuopc/ocn_stream_rivin.F90 index f1d52fd5..27211925 100644 --- a/drivers/nuopc/ocn_stream_rivin.F90 +++ b/drivers/nuopc/ocn_stream_rivin.F90 @@ -37,7 +37,7 @@ module ocn_stream_rivin use shr_nl_mod , only: shr_nl_find_group_name use nuopc_shr_methods , only: chkerr use mod_blom_pio , only: pio_iosystem, pio_iotype, blom_pio_getdata - use mod_forcing , only: rivflx_stream + use mod_forcing , only: rivflx_forcing use mod_output_forcing, only: output_forcing use mo_param1_bgc , only: nriv,irdin,irdip,irsi,iralk,iriron,irdoc,irdet use mo_intfcblom , only : omask @@ -146,9 +146,9 @@ subroutine ocn_stream_rivin_init(mesh_model, rc) endif ! allocate field to hold rivin fields - allocate (rivflx_stream(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy,nriv),stat=errstat) + allocate (rivflx_forcing(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy,nriv),stat=errstat) if(errstat /= 0) stop 'not enough memory rivflx allocation' - rivflx_stream(:,:,:) = 0.0 + rivflx_forcing(:,:,:) = 0.0 ! read riverine nutrient fluxes from file if (mnproc.eq.1) then @@ -223,22 +223,22 @@ subroutine ocn_stream_rivin_init(mesh_model, rc) do j = 1, jjcpl do i = 1, ii if (ip(i,j) == 0) then - rivflx_stream(i,j,index) = mval + rivflx_forcing(i,j,index) = mval elseif (cplmsk(i,j) == 0) then - rivflx_stream(i,j,index) = fval + rivflx_forcing(i,j,index) = fval else n = (j - 1)*ii + i - rivflx_stream(i,j,index) = dataptr_model(n) + rivflx_forcing(i,j,index) = dataptr_model(n) end if ! set flux to zero over land if (omask(i,j) < 0.5) then - rivflx_stream(i,j,index) = 0.0 + rivflx_forcing(i,j,index) = 0.0 end if end do end do output_filename = 'frivin_stream_'//trim(fldnames(nf))//'.nc' - call output_forcing(trim(output_filename), trim(fldnames(nf)), rivflx_stream(:,:,index)) + call output_forcing(trim(output_filename), trim(fldnames(nf)), rivflx_forcing(:,:,index)) end do call pio_closefile(pioid) diff --git a/drivers/nuopc/ocn_stream_swaclim.F90 b/drivers/nuopc/ocn_stream_swaclim.F90 index 6a0d13f7..fa3d323d 100644 --- a/drivers/nuopc/ocn_stream_swaclim.F90 +++ b/drivers/nuopc/ocn_stream_swaclim.F90 @@ -1,9 +1,10 @@ -module ocn_stream_swa +module ocn_stream_swaclim +#ifdef HAMOCC !----------------------------------------------------------------------- - ! Contains methods for reading in swa forcing file + ! Contains methods for reading in swaclim forcing file (HAMOCC only) !----------------------------------------------------------------------- - ! + use ESMF , only : ESMF_Clock, ESMF_Mesh, ESMF_Time, ESMF_ClockGet, ESMF_TimeGet use ESMF , only : ESMF_SUCCESS, ESMF_LOGERR_PASSTHRU, ESMF_END_ABORT use ESMF , only : ESMF_Finalize, ESMF_LogFoundError @@ -13,19 +14,17 @@ module ocn_stream_swa use shr_log_mod , only : errMsg => shr_log_errMsg use shr_sys_mod , only : shr_sys_abort use mo_intfcblom , only : omask + use mod_forcing , only : swaclim_forcing use mod_xc implicit none private - public :: ocn_stream_swa_init ! position datasets for dynamic swa - public :: ocn_stream_swa_interp ! interpolates between two years of swa file data - - type(shr_strdata_type) :: sdat_swa ! input data stream - character(len=CS) :: stream_swa_varname='swa' + public :: ocn_stream_swaclim_init ! position datasets for dynamic swaclim + public :: ocn_stream_swaclim_interp ! interpolates between two years of swaclim file data - ! Array to store swa flux after reading from file - real, allocatable, public :: swa_stream(:,:) + type(shr_strdata_type) :: sdat_swaclim ! input data stream + character(len=CS) :: stream_swaclim_varname='swaclim' integer, parameter :: nfiles_max = 100 ! maximum number of stream files character(len=*), parameter :: sourcefile = & @@ -35,7 +34,7 @@ module ocn_stream_swa contains !============================================================================== - subroutine ocn_stream_swa_init(model_mesh, model_clock, rc) + subroutine ocn_stream_swaclim_init(model_mesh, model_clock, rc) ! ! Initialize data stream information. @@ -49,73 +48,73 @@ subroutine ocn_stream_swa_init(model_mesh, model_clock, rc) integer , intent(out) :: rc ! local variables - integer :: nu_nml ! unit for namelist file - integer :: nml_error ! namelist i/o error flag - integer :: ierr ! error status - character(len=CL) :: filein ! ocn namelist file - integer :: stream_swa_year_first ! first year in stream to use - integer :: stream_swa_year_last ! last year in stream to use - integer :: stream_swa_year_align ! align stream_year_firstswa with - character(len=CL) :: stream_swa_mesh_filename - character(len=CL) :: stream_swa_data_filename(nfiles_max) + integer :: nu_nml ! unit for namelist file + integer :: nml_error ! namelist i/o error flag + integer :: ierr ! error status + character(len=CL) :: filein ! ocn namelist file + integer :: stream_swaclim_year_first ! first year in stream to use + integer :: stream_swaclim_year_last ! last year in stream to use + integer :: stream_swaclim_year_align ! align stream_year_first swaclim with first model year + character(len=CL) :: stream_swaclim_mesh_filename + character(len=CL) :: stream_swaclim_data_filename(nfiles_max) character(len=CL), allocatable :: stream_filenames(:) character(len=4) :: tmpchar integer :: nfiles integer :: nf integer :: errstat - character(*), parameter :: subName = "('ocn_stream_swa_init')" + character(*), parameter :: subName = "('ocn_stream_swaclim_init')" !----------------------------------------------------------------------- - namelist /stream_swa/ & - stream_swa_data_filename, & - stream_swa_mesh_filename, & - stream_swa_varname, & - stream_swa_year_first, & - stream_swa_year_last, & - stream_swa_year_align + namelist /stream_swaclim/ & + stream_swaclim_data_filename, & + stream_swaclim_mesh_filename, & + stream_swaclim_varname, & + stream_swaclim_year_first, & + stream_swaclim_year_last, & + stream_swaclim_year_align rc = ESMF_SUCCESS ! Default values for namelist - stream_swa_data_filename(:) = ' ' - stream_swa_mesh_filename = ' ' - stream_swa_varname = ' ' - stream_swa_year_first = 1 ! first year in stream to use - stream_swa_year_last = 1 ! last year in stream to use - stream_swa_year_align = 1 ! align stream_swa_year_first with this model year - - ! Read stream_swa namelist + stream_swaclim_data_filename(:) = ' ' + stream_swaclim_mesh_filename = ' ' + stream_swaclim_varname = ' ' + stream_swaclim_year_first = 1 ! first year in stream to use + stream_swaclim_year_last = 1 ! last year in stream to use + stream_swaclim_year_align = 1 ! align stream_swaclim_year_first with this model year + + ! Read stream_swaclim namelist if (mnproc == 1) then filein = "ocn_in" open( newunit=nu_nml, file=trim(filein), status='old', iostat=nml_error ) if (nml_error /= 0) then call shr_sys_abort(subName//': ERROR opening '//trim(filein)//errMsg(sourcefile, __LINE__)) end if - call shr_nl_find_group_name(nu_nml, 'stream_swa', status=nml_error) + call shr_nl_find_group_name(nu_nml, 'stream_swaclim', status=nml_error) if (nml_error == 0) then - read(nu_nml, nml=stream_swa, iostat=nml_error) + read(nu_nml, nml=stream_swaclim, iostat=nml_error) if (nml_error /= 0) then - call shr_sys_abort(' ERROR reading stream_swa namelist: '//errMsg(sourcefile, __LINE__)) + call shr_sys_abort(' ERROR reading stream_swaclim namelist: '//errMsg(sourcefile, __LINE__)) end if else - call shr_sys_abort(' ERROR finding stream_swa namelist: '//errMsg(sourcefile, __LINE__)) + call shr_sys_abort(' ERROR finding stream_swaclim namelist: '//errMsg(sourcefile, __LINE__)) end if close(nu_nml) endif do nf = 1,nfiles_max - call xcbcst(stream_swa_data_filename(nf)) + call xcbcst(stream_swaclim_data_filename(nf)) end do - call xcbcst(stream_swa_mesh_filename) - call xcbcst(stream_swa_varname) - call xcbcst(stream_swa_year_first) - call xcbcst(stream_swa_year_last) - call xcbcst(stream_swa_year_align) + call xcbcst(stream_swaclim_mesh_filename) + call xcbcst(stream_swaclim_varname) + call xcbcst(stream_swaclim_year_first) + call xcbcst(stream_swaclim_year_last) + call xcbcst(stream_swaclim_year_align) ! Determine the actual number and filenames of stream files that will be used nfiles = 0 do nf = 1,nfiles_max - if (stream_swa_data_filename(nf) == '') then + if (stream_swaclim_data_filename(nf) == '') then exit else nfiles = nfiles + 1 @@ -129,65 +128,55 @@ subroutine ocn_stream_swa_init(model_mesh, model_clock, rc) end if end if do nf = 1,nfiles - stream_filenames(nf) = trim(stream_swa_data_filename(nf)) + stream_filenames(nf) = trim(stream_swaclim_data_filename(nf)) end do ! Write out info if (mnproc == 1) then write(lp,'(a)' ) ' ' - write(lp,'(a,i8)') 'stream swa settings:' + write(lp,'(a,i8)') 'stream swaclim settings:' do nf = 1,nfiles write(tmpchar,'(i0)') nf - write(lp,'(a,a)' ) ' stream_swa_data_filename('//trim(tmpchar)//') = ',trim(stream_filenames(nf)) + write(lp,'(a,a)' ) ' stream_swaclim_data_filename('//trim(tmpchar)//') = ',trim(stream_filenames(nf)) end do - write(lp,'(a,a)' ) ' stream_swa_mesh_filename = ',trim(stream_swa_mesh_filename) - write(lp,'(a,a,a)') ' stream_swa_varnames = ',trim(stream_swa_varname) - write(lp,'(a,i8)') ' stream_swa_year_first = ',stream_swa_year_first - write(lp,'(a,i8)') ' stream_swa_year_last = ',stream_swa_year_last - write(lp,'(a,i8)') ' stream_swa_year_align = ',stream_swa_year_align + write(lp,'(a,a)' ) ' stream_swaclim_mesh_filename = ',trim(stream_swaclim_mesh_filename) + write(lp,'(a,a,a)') ' stream_swaclim_varnames = ',trim(stream_swaclim_varname) + write(lp,'(a,i8)') ' stream_swaclim_year_first = ',stream_swaclim_year_first + write(lp,'(a,i8)') ' stream_swaclim_year_last = ',stream_swaclim_year_last + write(lp,'(a,i8)') ' stream_swaclim_year_align = ',stream_swaclim_year_align write(lp,'(a)' ) ' ' endif - ! Initialize the cdeps data type sdat_swa - call shr_strdata_init_from_inline(sdat_swa, & - my_task = mnproc, & - logunit = lp, & - compname = 'OCN', & - model_clock = model_clock, & - model_mesh = model_mesh, & - stream_meshfile = trim(stream_swa_mesh_filename), & - stream_filenames = stream_filenames, & - stream_yearFirst = stream_swa_year_first, & - stream_yearLast = stream_swa_year_last, & - stream_yearAlign = stream_swa_year_align, & - stream_fldlistFile = (/stream_swa_varname/), & - stream_fldlistModel = (/stream_swa_varname/), & - stream_lev_dimname = 'null', & - stream_mapalgo = 'bilinear', & - stream_offset = 0, & - stream_taxmode = 'cycle', & - stream_dtlimit = 1.0e30_r8, & - stream_tintalgo = 'linear', & - stream_name = 'Shortwave Radiation Absorption', & + ! Initialize the cdeps data type sdat_swaclim + call shr_strdata_init_from_inline(sdat_swaclim, & + my_task = mnproc, & + logunit = lp, & + compname = 'OCN', & + model_clock = model_clock, & + model_mesh = model_mesh, & + stream_meshfile = trim(stream_swaclim_mesh_filename), & + stream_filenames = stream_filenames, & + stream_yearFirst = stream_swaclim_year_first, & + stream_yearLast = stream_swaclim_year_last, & + stream_yearAlign = stream_swaclim_year_align, & + stream_fldlistFile = (/stream_swaclim_varname/), & + stream_fldlistModel = (/stream_swaclim_varname/), & + stream_lev_dimname = 'null', & + stream_mapalgo = 'bilinear', & + stream_offset = 0, & + stream_taxmode = 'cycle', & + stream_dtlimit = 1.0e30_r8, & + stream_tintalgo = 'linear', & + stream_name = 'Climatological SWA', & rc = rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then call ESMF_Finalize(endflag=ESMF_END_ABORT) end if - ! allocate field to hold swa fields - if (mnproc == 1) then - write(lp,'(a)')'Memory allocation for variable swa_stream ...' - write(lp,'(a,i10)')'First dimension : ',idm - write(lp,'(a,i10)')'Second dimension : ',jdm - endif - allocate (swa_stream(idm,jdm),stat=errstat) - if(errstat /= 0) stop 'not enough memory swa_stream' - swa_stream(:,:) = 0.0 - - end subroutine ocn_stream_swa_init + end subroutine ocn_stream_swaclim_init !================================================================ - subroutine ocn_stream_swa_interp(model_clock, rc) + subroutine ocn_stream_swaclim_interp(model_clock, rc) use dshr_strdata_mod , only : shr_strdata_advance use dshr_methods_mod , only : dshr_fldbun_getfldptr @@ -222,13 +211,13 @@ subroutine ocn_stream_swa_interp(model_clock, rc) end if mcdate = year*10000 + mon*100 + day - call shr_strdata_advance(sdat_swa, ymd=mcdate, tod=sec, logunit=lp, istr='swa', rc=rc) + call shr_strdata_advance(sdat_swaclim, ymd=mcdate, tod=sec, logunit=lp, istr='swaclim', rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then call ESMF_Finalize(endflag=ESMF_END_ABORT) end if ! Get pointer for stream data that is time and spatially interpolated to model time and grid - call dshr_fldbun_getFldPtr(sdat_swa%pstrm(1)%fldbun_model, stream_swa_varname, fldptr1=dataptr1, rc=rc) + call dshr_fldbun_getFldPtr(sdat_swaclim%pstrm(1)%fldbun_model, stream_swaclim_varname, fldptr1=dataptr1, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then call ESMF_Finalize(endflag=ESMF_END_ABORT) end if @@ -246,32 +235,33 @@ subroutine ocn_stream_swa_interp(model_clock, rc) do j = 1, jjcpl do i = 1, ii if (ip(i,j) == 0) then - swa_stream(i,j) = mval + swaclim_forcing(i,j) = mval elseif (cplmsk(i,j) == 0) then - swa_stream(i,j) = fval + swaclim_forcing(i,j) = fval else n = (j - 1)*ii + i - swa_stream(i,j) = dataptr1(n) + swaclim_forcing(i,j) = dataptr1(n) end if end do end do if (csdiag) then if (mnproc == 1) then - write(lp,*) 'ocn_stream_swa_interp:' + write(lp,*) 'ocn_forcing_swaclim_interp:' end if - call chksummsk(swa_stream(1-nbdy,1-nbdy),ip,1,'swa_stream') + call chksummsk(swaclim_forcing(1-nbdy,1-nbdy),ip,1,'swaclim_forcing') end if ! set flux to zero over land do j=1,jdm do i=1,idm if (omask(i,j) < 0.5) then - swa_stream(i,j) = 0.0 + swaclim_forcing(i,j) = 0.0 end if enddo enddo - end subroutine ocn_stream_swa_interp + end subroutine ocn_stream_swaclim_interp -end module ocn_stream_swa +#endif +end module ocn_stream_swaclim diff --git a/hamocc/mo_hamocc_init.F90 b/hamocc/mo_hamocc_init.F90 index b7c4cc1e..d282a063 100644 --- a/hamocc/mo_hamocc_init.F90 +++ b/hamocc/mo_hamocc_init.F90 @@ -38,8 +38,8 @@ subroutine hamocc_init(read_rest,rstfnm_hamocc) use mod_time, only: date,baclin use mod_xc, only: ii,jj,kk,idm,jdm,kdm,nbdy,isp,ifp,ilp,mnproc,lp,xchalt use mod_grid, only: plon,plat - use mod_forcing, only: use_stream_swa, use_stream_rivin, use_stream_dust, use_stream_ndep, & - use_stream_oalk + use mod_forcing, only: use_nuopc_swaclim, use_nuopc_rivin, use_nuopc_dust, use_nuopc_ndep, & + use_nuopc_oalk use mod_tracers, only: ntrbgc,ntr,itrbgc,trc use mo_control_bgc, only: bgc_namelist,get_bgc_namelist,do_ndep,do_rivinpt,do_oalk, & do_sedspinup,sedspin_yr_s,sedspin_yr_e,sedspin_ncyc, & @@ -201,23 +201,20 @@ subroutine hamocc_init(read_rest,rstfnm_hamocc) ! ! --- Initialise reading of input data (dust, n-deposition, river, etc.) ! - if (.not. use_stream_dust) then - call ini_read_fedep(omask) + if (.not. use_nuopc_dust) then + call ini_read_fedep(idm,jdm,omask) end if - if (.not. use_stream_ndep) then + if (.not. use_nuopc_ndep) then call ini_read_ndep(idm,jdm) end if - write(6,*)'DEBUG: use_stream_rivin = ',use_stream_rivin - if (.not. use_stream_rivin) then - call ini_read_rivin(omask) + if (.not. use_nuopc_rivin) then + call ini_read_rivin(idm,jdm,omask) end if - if (.not. use_stream_oalk) then + if (.not. use_nuopc_oalk) then call ini_read_oafx(idm,jdm,bgc_dx,bgc_dy,plat,omask) end if - if (.not. use_stream_swa) then - if (use_BROMO) then - call ini_swa_clim(idm,jdm,omask) - end if + if (.not. use_nuopc_swaclim .and. use_BROMO) then + call ini_swa_clim(idm,jdm,omask) endif call ini_pi_ph(idm,jdm,omask) ! diff --git a/hamocc/mo_hamocc_step.F90 b/hamocc/mo_hamocc_step.F90 index bc438cbd..afe532af 100644 --- a/hamocc/mo_hamocc_step.F90 +++ b/hamocc/mo_hamocc_step.F90 @@ -35,8 +35,8 @@ subroutine hamocc_step(m,n,mm,nn,k1m,k1n) use mod_state, only: temp,saln use mod_forcing, only: swa,slp,abswnd,atmco2,flxco2,flxdms,atmbrf,flxbrf, & atmn2o,flxn2o,atmnh3,flxnh3,atmnhxdep,atmnoydep, & - use_stream_dust, use_stream_oalk, use_stream_ndep, & - dust_stream, ndep_stream, oalk_stream, rivflx_stream + use_nuopc_dust, use_nuopc_oalk, use_nuopc_ndep, & + dust_forcing, ndep_forcing, oalk_forcing, rivflx_forcing use mod_seaice, only: ficem use mo_bgcmean, only: nbgc,bgcwrt, diagfq_bgc,diagmon_bgc,diagann_bgc use mo_intfcblom, only: bgc_dx,bgc_dy,bgc_dp,bgc_rho,omask,blom2hamocc,hamocc2blom @@ -72,19 +72,19 @@ subroutine hamocc_step(m,n,mm,nn,k1m,k1n) end if enddo - if (.not. use_stream_dust) then - call get_fedep(date%month, dust_stream) + if (.not. use_nuopc_dust) then + call get_fedep(idm,jdm,date%month, dust_forcing) end if - if (.not. use_stream_ndep) then - if (.not. allocated(ndep_stream)) then - allocate(ndep_stream(1-nbdy:idm+nbdy, 1-nbdy:jdm+nbdy, nndep)) + if (.not. use_nuopc_ndep) then + if (.not. allocated(ndep_forcing)) then + allocate(ndep_forcing(1-nbdy:idm+nbdy, 1-nbdy:jdm+nbdy, nndep)) end if - call get_ndep(date%year, date%month, omask, ndep_stream, atmnhxdep, atmnoydep) + call get_ndep(date%year, date%month, omask, ndep_forcing, atmnhxdep, atmnoydep) end if - if (.not. use_stream_oalk) then - call get_oafx(date%year, date%month, omask, oalk_stream) + if (.not. use_nuopc_oalk) then + call get_oafx(date%year, date%month, omask, oalk_forcing) end if if (with_dmsph) then @@ -94,7 +94,7 @@ subroutine hamocc_step(m,n,mm,nn,k1m,k1n) call hamocc4bcm(idm, jdm, kdm, nbdy, & date%year, date%month, date%day, ldtday, bgc_dx, bgc_dy, bgc_dp, & bgc_rho, plat, omask, & - dust_stream, rivflx_stream, ndep_stream, oalk_stream, & + dust_forcing, rivflx_forcing, ndep_forcing, oalk_forcing, & pi_ph, swa, ficem, slp, abswnd, & temp(1-nbdy,1-nbdy,1+nn), saln(1-nbdy,1-nbdy,1+nn), & atmco2, flxco2, flxdms, atmbrf, flxbrf, & diff --git a/hamocc/mo_read_fedep.F90 b/hamocc/mo_read_fedep.F90 index a04d476b..c01ba41e 100644 --- a/hamocc/mo_read_fedep.F90 +++ b/hamocc/mo_read_fedep.F90 @@ -132,12 +132,34 @@ subroutine get_fedep(kpie,kpje,kplmon,dust) ! J.Schwinger *NORCE Climate, Bergen* 2020-05-19 !*********************************************************************************************** + use mod_xc , only: nbdy + use mod_output_forcing , only: output_forcing + integer, intent(in) :: kpie ! 1st dimension of model grid integer, intent(in) :: kpje ! 2nd dimension of model grid integer, intent(in) :: kplmon ! current month. real, intent(out) :: dust(kpie,kpje) ! dust flux for current month - dust = dustflx(:,:,kplmon) + integer :: i,j + logical :: debug = .true. + logical :: first_time = .true. + real, allocatable :: dust_out(:,:) + + dust(:,:) = dustflx(:,:,kplmon) + + if (debug) then + if (first_time) then + allocate (dust_out(1-nbdy:kpie+nbdy, 1-nbdy:kpje+nbdy)) + do j = 1,kpje + do i = 1,kpie + dust(i,j) = dustflx(i,j,kplmon) + end do + end do + call output_forcing('fedep_orig.nc', 'fedep', dust_out) + deallocate(dust_out) + first_time = .false. + end if + end if end subroutine get_fedep diff --git a/phy/mod_forcing.F90 b/phy/mod_forcing.F90 index 79e7adfa..40bec71c 100644 --- a/phy/mod_forcing.F90 +++ b/phy/mod_forcing.F90 @@ -93,34 +93,35 @@ module mod_forcing sssclm ! Sea-surface salinity [g kg-1]. real(r8), dimension(1 - nbdy:idm + nbdy, 1 - nbdy:jdm + nbdy) :: & - sst_stream, & ! Sea-surface temperature [deg C] from stream data. - ice_stream, & ! Sea-ice concentration [] from stream data. - sss_stream ! Sea-surface salinity [g kg-1] from stream data. - logical :: use_stream_relaxation ! If true, use nuopc stream relaxation capability + sst_stream, & ! Sea-surface temperature [deg C] from stream data. + ice_stream, & ! Sea-ice concentration [] from stream data. + sss_stream ! Sea-surface salinity [g kg-1] from stream data. + logical :: use_nuopc_relaxation ! If true, use nuopc stream relaxation capability real(r8), dimension(1 - nbdy:idm + nbdy, 1 - nbdy:jdm + nbdy) :: & - swa_stream ! absorbed short wave radiation flux - logical :: use_stream_swa ! If true, use nuopc stream swa capability + chloro_forcing ! chlorophyll concentration (hamocc) + logical :: use_nuopc_chloro ! If true, use nuopc stream chlorophyll capability - real(r8), dimension(1 - nbdy:idm + nbdy, 1 - nbdy:jdm + nbdy) :: & - dust_stream ! iron dust deposition flux (hamocc) - logical :: use_stream_dust ! If true, use nuopc stream dust capability (hamocc only) + real(r8), allocatable :: & + rivflx_forcing(:,:,:) ! riverine fluxes + logical :: use_nuopc_rivin ! If true, use nuopc input for rivin fluxes (hamocc only) + + real(r8), allocatable :: & + ndep_forcing(:,:,:) ! nitrogen deposition fluxes + logical :: use_nuopc_ndep ! If true, use nuopc input for rivin fluxes real(r8), dimension(1 - nbdy:idm + nbdy, 1 - nbdy:jdm + nbdy) :: & - chloro_stream ! chlorophyll concentration (hamocc) - logical :: use_stream_chloro ! If true, use nuopc stream chlorophyll capability + dust_forcing ! iron dust deposition flux (hamocc) + logical :: use_nuopc_dust ! If true, use nuopc stream dust capability (hamocc only) real(r8), dimension(1 - nbdy:idm + nbdy, 1 - nbdy:jdm + nbdy) :: & - oalk_stream ! alkalinization flux (hamocc) - logical :: use_stream_oalk ! If true, use nuopc stream for ocean alkalinity capability + swaclim_forcing ! absorbed short wave radiation flux + logical :: use_nuopc_swaclim ! If true, use nuopc stream swa capability (hamocc only) - real(r8), allocatable :: & - rivflx_stream(:,:,:) ! riverine fluxes - logical :: use_stream_rivin ! If true, use nuopc input for rivin fluxes + real(r8), dimension(1 - nbdy:idm + nbdy, 1 - nbdy:jdm + nbdy) :: & + oalk_forcing ! alkalinization flux (hamocc) + logical :: use_nuopc_oalk ! If true, use nuopc stream for ocean alkalinity capability - real(r8), allocatable :: & - ndep_stream(:,:,:) ! nitrogen deposition fluxes - logical :: use_stream_ndep ! If true, use nuopc input for rivin fluxes ! Variables related to balancing the freshwater forcing budget. real(r8) :: & @@ -206,9 +207,10 @@ module mod_forcing ustar, ustarb, ustar3, wstar3, buoyfl, t_sw_nonloc, t_rs_nonloc, & s_br_nonloc, s_rs_nonloc, inivar_forcing, fwbbal, & sss_stream, sst_stream, ice_stream, & - dust_stream, chloro_stream, swa_stream, ndep_stream, oalk_stream, rivflx_stream, & - use_stream_relaxation, use_stream_swa, use_stream_dust, use_stream_chloro, & - use_stream_oalk, use_stream_rivin, use_stream_ndep + dust_forcing, chloro_forcing, swaclim_forcing, & + ndep_forcing, oalk_forcing, rivflx_forcing, & + use_nuopc_relaxation, use_nuopc_swaclim, use_nuopc_dust, use_nuopc_chloro, & + use_nuopc_oalk, use_nuopc_rivin, use_nuopc_ndep contains diff --git a/phy/mod_rdlim.F90 b/phy/mod_rdlim.F90 index 381fcd91..ab5548d2 100644 --- a/phy/mod_rdlim.F90 +++ b/phy/mod_rdlim.F90 @@ -45,9 +45,9 @@ module mod_rdlim trxday, srxday, trxdpt, srxdpt, trxlim, & srxlim, srxbal, sprfac, & srxlim, srxbal, sprfac, & - use_stream_relaxation, use_stream_swa, & - use_stream_chloro, use_stream_dust, use_stream_oalk, & - use_stream_rivin, use_stream_ndep + use_nuopc_relaxation, use_nuopc_swaclim, & + use_nuopc_chloro, use_nuopc_dust, use_nuopc_oalk, & + use_nuopc_rivin, use_nuopc_ndep use mod_swabs, only: swamth, jwtype, chlopt, ccfile use mod_diffusion, only: readnml_diffusion use mod_eddtra, only: mlrmth, ce, cl, tau_mlr, tau_growing_hbl, & @@ -147,8 +147,8 @@ subroutine rdlim() cnsvdi, & csdiag, & rstfrq,rstfmt,rstcmp,iotype,& - use_stream_relaxation, use_stream_swa, use_stream_chloro, & - use_stream_dust, use_stream_oalk, use_stream_rivin, use_stream_ndep + use_nuopc_relaxation, use_nuopc_swaclim, use_nuopc_chloro, & + use_nuopc_dust, use_nuopc_oalk, use_nuopc_rivin, use_nuopc_ndep ! read limits namelist @@ -252,13 +252,13 @@ subroutine rdlim() write (lp,*) 'RSTFMT',RSTFMT write (lp,*) 'RSTCMP',RSTCMP write (lp,*) 'IOTYPE',IOTYPE - write (lp,*) 'USE_STREAM_RELAXATION',use_stream_relaxation - write (lp,*) 'USE_STREAM_CHLORO',use_stream_chloro - write (lp,*) 'USE_STREAM_DUST',use_stream_dust - write (lp,*) 'USE_STREAM_OALK',use_stream_oalk - write (lp,*) 'USE_STREAM_RIVIN',use_stream_rivin - write (lp,*) 'USE_STREAM_NDEP',use_stream_ndep - write (lp,*) 'USE_STREAM_SWA',use_stream_swa + write (lp,*) 'USE_NUOPC_RELAXATION',use_nuopc_relaxation + write (lp,*) 'USE_NUOPC_CHLORO',use_nuopc_chloro + write (lp,*) 'USE_NUOPC_DUST',use_nuopc_dust + write (lp,*) 'USE_NUOPC_OALK',use_nuopc_oalk + write (lp,*) 'USE_NUOPC_RIVIN',use_nuopc_rivin + write (lp,*) 'USE_NUOPC_NDEP',use_nuopc_ndep + write (lp,*) 'USE_NUOPC_SWA',use_nuopc_swaclim write (lp,*) end if @@ -341,13 +341,13 @@ subroutine rdlim() call xcbcst(rstfmt) call xcbcst(rstcmp) call xcbcst(iotype) - call xcbcst(use_stream_relaxation) - call xcbcst(use_stream_chloro) - call xcbcst(use_stream_swa) - call xcbcst(use_stream_dust) - call xcbcst(use_stream_oalk) - call xcbcst(use_stream_rivin) - call xcbcst(use_stream_ndep) + call xcbcst(use_nuopc_relaxation) + call xcbcst(use_nuopc_chloro) + call xcbcst(use_nuopc_swaclim) + call xcbcst(use_nuopc_dust) + call xcbcst(use_nuopc_oalk) + call xcbcst(use_nuopc_rivin) + call xcbcst(use_nuopc_ndep) ! resolve options select case (trim(wavsrc)) From 6cba730924e0a780923bdd0c4bce78dabcba7eca Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Wed, 25 Sep 2024 10:36:22 +0200 Subject: [PATCH 14/16] more udpates for streams --- cime_config/buildnml | 3 +- cime_config/namelist_definition_blom.xml | 50 ++++++++-------- drivers/nuopc/ocn_comp_nuopc.F90 | 76 +++++++++++++++--------- 3 files changed, 74 insertions(+), 55 deletions(-) diff --git a/cime_config/buildnml b/cime_config/buildnml index c9bcde5e..0dcf9fe7 100755 --- a/cime_config/buildnml +++ b/cime_config/buildnml @@ -257,8 +257,7 @@ def buildnml(case, caseroot, compname): # Create BLOM namelist groups=['limits','diffusion','merdia','secdia','diaphy', - 'stream_sss','stream_sst','stream_swa','stream_dust', - 'stream_oalk', 'stream_rivin'] + 'stream_sss','stream_sst','stream_swaclim','stream_dust','stream_oalk','stream_rivin'] groups.append('cwmod') diff --git a/cime_config/namelist_definition_blom.xml b/cime_config/namelist_definition_blom.xml index 255c3b93..8002fa60 100644 --- a/cime_config/namelist_definition_blom.xml +++ b/cime_config/namelist_definition_blom.xml @@ -8694,7 +8694,7 @@ limits .false. - .true. + .false. if .true., use NUOPC stream capability to obtain chlorophyll concentration @@ -8743,7 +8743,7 @@ if .true., use NUOPC stream ocean alkalinity capability - + logical limits limits @@ -8899,30 +8899,30 @@ - + char - stream_swa - stream_swa + stream_swaclim + stream_swaclim stream mesh file $DIN_LOC_ROOT/share/meshes/tnx1v4_20170601_cdf5_ESMFmesh.nc - + char(10) - stream_swa - stream_swa + stream_swaclim + stream_swaclim - file name(s) containing swa climatology + file name(s) containing swaclim climatology $DIN_LOC_ROOT/ocn/blom/bndcon/Annual_clim_swa_tnx1v4_20210415.nc - + char - stream_swa - stream_swa + stream_swaclim + stream_swaclim variable name on stream file @@ -8930,10 +8930,10 @@ swa - + integer - stream_swa - stream_swa + stream_swaclim + stream_swaclim First year in stream to use @@ -8941,10 +8941,10 @@ 1 - + integer - stream_swa - stream_swa + stream_swaclim + stream_swaclim Last year in stream to use @@ -8952,10 +8952,10 @@ 1 - + integer - stream_swa - stream_swa + stream_swaclim + stream_swaclim Align stream_year_first with this model year @@ -9103,7 +9103,7 @@ - + @@ -9113,7 +9113,8 @@ stream mesh file - $DIN_LOC_ROOT/share/meshes/tnx1v4_20170601_cdf5_ESMFmesh.nc + + $DIN_LOC_ROOT/share/meshes/r05_nomask_c110308_ESMFmesh.nc @@ -9125,7 +9126,8 @@ - $DIN_LOC_ROOT//ocn/blom/bndcon/river_nutrients_GNEWS2000_tnx1v4_20170820.nc + + $DIN_LOC_ROOT/ocn/blom/bndcon/river_nutrients_GNEWS2000c70_r05_20240921.nc diff --git a/drivers/nuopc/ocn_comp_nuopc.F90 b/drivers/nuopc/ocn_comp_nuopc.F90 index f3360c6c..4e2ff8e9 100644 --- a/drivers/nuopc/ocn_comp_nuopc.F90 +++ b/drivers/nuopc/ocn_comp_nuopc.F90 @@ -50,7 +50,8 @@ module ocn_comp_nuopc use mod_cesm, only: runid_cesm, runtyp_cesm, ocn_cpl_dt_cesm use mod_config, only: inst_index, inst_name, inst_suffix use mod_time, only: blom_time - use mod_forcing, only: srxday, trxday + use mod_forcing, only: srxday, trxday, use_nuopc_chloro, use_nuopc_swaclim + use mod_forcing, only: use_nuopc_dust, use_nuopc_rivin use mod_swabs, only: swamth, chlopt use mod_constants, only: epsilt use mod_blom_init, only: blom_init @@ -234,17 +235,20 @@ subroutine ocn_import(importState, rc) ! Get data pointers for the fields to be imported. do n = 1, fldsToOcn_num if (fldsToOcn(n)%stdname == trim(flds_scalar_name)) cycle - call ESMF_StateGet(importState, trim(fldsToOcn(n)%stdname), & - itemType, rc=rc) + call ESMF_StateGet(importState, trim(fldsToOcn(n)%stdname), itemType, rc=rc) if (ChkErr(rc, __LINE__, u_FILE_u)) return if (itemType == ESMF_STATEITEM_NOTFOUND) then fldsToOcn(n)%dataptr => null() else - call ESMF_StateGet(importState, trim(fldsToOcn(n)%stdname), & - field=field, rc=rc) - if (ChkErr(rc, __LINE__, u_FILE_u)) return - call ESMF_FieldGet(field, farrayPtr=fldsToOcn(n)%dataptr, rc=rc) + call ESMF_StateGet(importState, trim(fldsToOcn(n)%stdname), field=field, rc=rc) if (ChkErr(rc, __LINE__, u_FILE_u)) return + if (fldsToOcn(n)%ungridded_lbound > 0 .and. fldsToOcn(n)%ungridded_ubound > 0) then + call ESMF_FieldGet(field, farrayPtr=fldsToOcn(n)%dataptr2d, rc=rc) + if (ChkErr(rc, __LINE__, u_FILE_u)) return + else + call ESMF_FieldGet(field, farrayPtr=fldsToOcn(n)%dataptr, rc=rc) + if (ChkErr(rc, __LINE__, u_FILE_u)) return + end if endif enddo @@ -743,31 +747,39 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) end if ! Initialize sdat for chlorophyll concentration if appropriate - if (swamth == 'chlorophyll') then - if (chlopt == 'climatology') then - call ocn_stream_chloro_init(Emesh, clock, rc) - if (ChkErr(rc, __LINE__, u_FILE_u)) return - else - if (mnproc == 1) then - write (lp,'(3a)') ' chlopt = ',trim(chlopt),' is unsupported!' + if (use_nuopc_chloro) then + if (swamth == 'chlorophyll') then + if (chlopt == 'climatology') then + call ocn_stream_chloro_init(Emesh, clock, rc) + if (ChkErr(rc, __LINE__, u_FILE_u)) return + else + if (mnproc == 1) then + write (lp,'(3a)') ' chlopt = ',trim(chlopt),' is unsupported!' + end if + call xcstop('(iniswa)') + stop '(iniswa)' end if - call xcstop('(iniswa)') - stop '(iniswa)' end if end if #ifdef HAMOCC ! Initialize sdat for swa climatology if appropriate - call ocn_stream_swaclim_init(Emesh, clock, rc) - if (ChkErr(rc, __LINE__, u_FILE_u)) return + if (use_nuopc_swaclim) then + call ocn_stream_swaclim_init(Emesh, clock, rc) + if (ChkErr(rc, __LINE__, u_FILE_u)) return + end if ! Initialize sdat for dust deposition climatology if appropriate - call ocn_stream_dust_init(Emesh, clock, rc) - if (ChkErr(rc, __LINE__, u_FILE_u)) return + if (use_nuopc_dust) then + call ocn_stream_dust_init(Emesh, clock, rc) + if (ChkErr(rc, __LINE__, u_FILE_u)) return + end if ! Initialize time independent riverine nutrient input - call ocn_stream_rivin_init(Emesh, rc) - if (ChkErr(rc, __LINE__, u_FILE_u)) return + if (use_nuopc_rivin) then + call ocn_stream_rivin_init(Emesh, rc) + if (ChkErr(rc, __LINE__, u_FILE_u)) return + end if #endif if (dbug > 5) call ESMF_LogWrite(subname//': done', ESMF_LOGMSG_INFO) @@ -933,19 +945,25 @@ subroutine ModelAdvance(gcomp, rc) end if ! Advance chlorophyll stream input if appropriate - if (swamth == 'chlorophyll' .and. chlopt == 'climatology') then - call ocn_stream_chloro_interp(clock, rc) - if (ChkErr(rc, __LINE__, u_FILE_u)) return + if (use_nuopc_chloro) then + if (swamth == 'chlorophyll' .and. chlopt == 'climatology') then + call ocn_stream_chloro_interp(clock, rc) + if (ChkErr(rc, __LINE__, u_FILE_u)) return + end if end if #ifdef HAMOCC ! Advance swa stream input if appropriate - call ocn_stream_swaclim_interp(clock, rc) - if (ChkErr(rc, __LINE__, u_FILE_u)) return + if (use_nuopc_swaclim) then + call ocn_stream_swaclim_interp(clock, rc) + if (ChkErr(rc, __LINE__, u_FILE_u)) return + end if ! Advance dust stream input if appropriate - call ocn_stream_dust_interp(clock, rc) - if (ChkErr(rc, __LINE__, u_FILE_u)) return + if (use_nuopc_dust) then + call ocn_stream_dust_interp(clock, rc) + if (ChkErr(rc, __LINE__, u_FILE_u)) return + end if #endif ! Advance the model a time step. From d6a2169aa83aea2eb2d0275b3fee06ace82f14c2 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Wed, 25 Sep 2024 15:55:37 +0200 Subject: [PATCH 15/16] addressed comments in PR --- hamocc/mo_hamocc_step.F90 | 2 +- hamocc/mo_read_ndep.F90 | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/hamocc/mo_hamocc_step.F90 b/hamocc/mo_hamocc_step.F90 index afe532af..5beae6e4 100644 --- a/hamocc/mo_hamocc_step.F90 +++ b/hamocc/mo_hamocc_step.F90 @@ -80,7 +80,7 @@ subroutine hamocc_step(m,n,mm,nn,k1m,k1n) if (.not. allocated(ndep_forcing)) then allocate(ndep_forcing(1-nbdy:idm+nbdy, 1-nbdy:jdm+nbdy, nndep)) end if - call get_ndep(date%year, date%month, omask, ndep_forcing, atmnhxdep, atmnoydep) + call get_ndep(idm,jdm,nbdy,date%year,date%month,omask,ndep,atmnhxdep,atmnoydep) end if if (.not. use_nuopc_oalk) then diff --git a/hamocc/mo_read_ndep.F90 b/hamocc/mo_read_ndep.F90 index bd8c5672..0a04b40e 100644 --- a/hamocc/mo_read_ndep.F90 +++ b/hamocc/mo_read_ndep.F90 @@ -172,7 +172,7 @@ subroutine ini_read_ndep(kpie,kpje) end subroutine ini_read_ndep - subroutine get_ndep(kplyear, kplmon, omask, ndep, patmnhxdep, patmnoydep) + subroutine get_ndep(idm, jdm, kplyear, kplmon, omask, ndep, patmnhxdep, patmnoydep) !*********************************************************************************************** ! Read and return CMIP6 n-deposition data for a given month or use atmosphere input @@ -180,7 +180,7 @@ subroutine get_ndep(kplyear, kplmon, omask, ndep, patmnhxdep, patmnoydep) ! S. Gao *Gfi, Bergen* 19.08.2017 !*********************************************************************************************** - use mod_xc, only: idm, jdm, nbdy, mnproc + use mod_xc, only: nbdy, mnproc use netcdf, only: nf90_open,nf90_close,nf90_nowrite use mo_control_bgc, only: io_stdo_bgc,do_ndep,use_extNcycle, do_ndep_coupled use mo_netcdf_bgcrw, only: read_netcdf_var @@ -188,12 +188,15 @@ subroutine get_ndep(kplyear, kplmon, omask, ndep, patmnhxdep, patmnoydep) use mo_chemcon, only: mw_nitrogen ! Arguments - integer, intent(in) :: kplyear ! current year. - integer, intent(in) :: kplmon ! current month. - real, intent(in) :: omask(idm,jdm) ! land/ocean mask (1=ocean) - real, intent(out) :: ndep(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy,nndep) ! N-deposition field for current year and month - real, intent(in) :: patmnhxdep(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy) ! Atmospheric NHx deposition [kgN m-2 s-1] - real, intent(in) :: patmnoydep(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy) ! Atmospheric NOy deposition [kgN m-2 s-1] + integer, intent(in) :: kpie ! 1st dimension of model grid. + integer, intent(in) :: kpje ! 2nd dimension of model grid. + integer, intent(in) :: kbnd ! + integer, intent(in) :: kplyear ! current year. + integer, intent(in) :: kplmon ! current month. + real, intent(in) :: omask(kpie,kpje) ! land/ocean mask (1=ocean) + real, intent(out) :: ndep(kpie,kpje,nndep) ! N-deposition field for current year and month + real, intent(in) :: patmnhxdep(1-kbnd:kpie+kbnd,1-kbnd:kpje+kbnd) ! Atmospheric NHx deposition [kgN m-2 s-1] + real, intent(in) :: patmnoydep(1-kbnd:kpie+kbnd,1-kbnd:kpje+kbnd) ! Atmospheric NOy deposition [kgN m-2 s-1] ! local variables integer :: month_in_file, ncstat, ncid, i, j From 635595dd76b764a91f0e6688c2ef900e5b31487f Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Thu, 26 Sep 2024 19:51:54 +0200 Subject: [PATCH 16/16] fixes for compilation problems --- hamocc/mo_hamocc_step.F90 | 2 +- hamocc/mo_read_ndep.F90 | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hamocc/mo_hamocc_step.F90 b/hamocc/mo_hamocc_step.F90 index 5beae6e4..319efd09 100644 --- a/hamocc/mo_hamocc_step.F90 +++ b/hamocc/mo_hamocc_step.F90 @@ -80,7 +80,7 @@ subroutine hamocc_step(m,n,mm,nn,k1m,k1n) if (.not. allocated(ndep_forcing)) then allocate(ndep_forcing(1-nbdy:idm+nbdy, 1-nbdy:jdm+nbdy, nndep)) end if - call get_ndep(idm,jdm,nbdy,date%year,date%month,omask,ndep,atmnhxdep,atmnoydep) + call get_ndep(idm,jdm,nbdy,date%year,date%month,omask,ndep_forcing,atmnhxdep,atmnoydep) end if if (.not. use_nuopc_oalk) then diff --git a/hamocc/mo_read_ndep.F90 b/hamocc/mo_read_ndep.F90 index 0a04b40e..e41b3f8c 100644 --- a/hamocc/mo_read_ndep.F90 +++ b/hamocc/mo_read_ndep.F90 @@ -172,7 +172,7 @@ subroutine ini_read_ndep(kpie,kpje) end subroutine ini_read_ndep - subroutine get_ndep(idm, jdm, kplyear, kplmon, omask, ndep, patmnhxdep, patmnoydep) + subroutine get_ndep(kpie, kpje, kbnd, kplyear, kplmon, omask, ndep, patmnhxdep, patmnoydep) !*********************************************************************************************** ! Read and return CMIP6 n-deposition data for a given month or use atmosphere input @@ -215,8 +215,8 @@ subroutine get_ndep(idm, jdm, kplyear, kplmon, omask, ndep, patmnhxdep, patmnoyd ndep(:,:,:) = 0. !$omp parallel do private(i) - do j=1,jdm - do i=1,idm + do j=1,kpje + do i=1,kpie ! convert from kgN/m2/s to climatological input file units: kmolN/m2/yr if (patmnoydep(i,j) > 0.) then ndep(i,j,idepnoy) = patmnoydep(i,j)*fatmndep @@ -252,8 +252,8 @@ subroutine get_ndep(idm, jdm, kplyear, kplmon, omask, ndep, patmnhxdep, patmnoyd !$omp parallel do private(i) ! 1 = NO3; 2 = NH4 - do j=1,jdm - do i=1,idm + do j=1,kpje + do i=1,kpie if (use_extNcycle) then ndep(i,j,idepnoy) = noydepread(i,j) ndep(i,j,idepnhx) = nhxdepread(i,j)