From a9eafe12291997cb594d9387fc0e545266ad343d Mon Sep 17 00:00:00 2001 From: Denise Worthen Date: Sun, 29 Jun 2025 09:54:40 -0400 Subject: [PATCH 1/9] initial files for mom6+cdeps work --- config_src/drivers/nuopc_cap/mom_cap.F90 | 15 ++- config_src/drivers/nuopc_cap/mom_inline.F90 | 118 ++++++++++++++++++++ 2 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 config_src/drivers/nuopc_cap/mom_inline.F90 diff --git a/config_src/drivers/nuopc_cap/mom_cap.F90 b/config_src/drivers/nuopc_cap/mom_cap.F90 index e0e618c76e..9a5f1b64f1 100644 --- a/config_src/drivers/nuopc_cap/mom_cap.F90 +++ b/config_src/drivers/nuopc_cap/mom_cap.F90 @@ -94,6 +94,7 @@ module MOM_cap_mod #ifndef CESMCOUPLED use shr_is_restart_fh_mod, only : init_is_restart_fh, is_restart_fh, is_restart_fh_type #endif + use mom_inline_mod, only : mom_inline_init, mom_inline_run implicit none; private @@ -141,6 +142,7 @@ module MOM_cap_mod logical :: use_coldstart = .true. logical :: use_mommesh = .true. logical :: restart_eor = .false. +character(len=128) :: streamconfigfile = '' character(len=128) :: scalar_field_name = '' integer :: scalar_field_count = 0 integer :: scalar_field_idx_grid_nx = 0 @@ -386,6 +388,8 @@ subroutine InitializeP0(gcomp, importState, exportState, clock, rc) geomtype = ESMF_GEOMTYPE_GRID endif + ! + streamconfigfile = 'mom6.stream.config' ! Read end of run restart config option call NUOPC_CompAttributeGet(gcomp, name="write_restart_at_endofrun", value=value, & isPresent=isPresent, isSet=isSet, rc=rc) @@ -1573,6 +1577,11 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) !--------------------------------- call mom_set_geomtype(geomtype) + if (len_trim(streamconfigfile) > 0) then + call mom_inline_init(gcomp, clock, eMesh, stdout, streamconfigfile, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end if + !--------------------------------- ! write out diagnostics !--------------------------------- @@ -1847,6 +1856,10 @@ subroutine ModelAdvance(gcomp, rc) call mom_import(ocean_public, ocean_grid, importState, ice_ocean_boundary, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return + !some logical + call mom_inline_run(clock, stdout, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + !--------------- ! Update MOM6 !--------------- @@ -1923,7 +1936,7 @@ subroutine ModelAdvance(gcomp, rc) call ESMF_VMGet(vm, localPet=localPet, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - write(timestamp,'(".",i4.4,"-",i2.2,"-",i2.2,"-",i5.5)'),year,month,day,hour*3600+minute*60+seconds + write(timestamp,'(".",i4.4,"-",i2.2,"-",i2.2,"-",i5.5)')year,month,day,hour*3600+minute*60+seconds rpointer_filename = 'rpointer.ocn'//trim(inst_suffix) if (pointer_date) then diff --git a/config_src/drivers/nuopc_cap/mom_inline.F90 b/config_src/drivers/nuopc_cap/mom_inline.F90 new file mode 100644 index 0000000000..bbf92661bd --- /dev/null +++ b/config_src/drivers/nuopc_cap/mom_inline.F90 @@ -0,0 +1,118 @@ +module mom_inline_mod + + use ESMF , only: ESMF_GridComp, ESMF_Mesh + use ESMF , only: ESMF_Clock, ESMF_Time, ESMF_TimeGet, ESMF_ClockGet + use ESMF , only: ESMF_KIND_R8, ESMF_SUCCESS, ESMF_LogFoundError + use ESMF , only: ESMF_LOGERR_PASSTHRU, ESMF_LOGMSG_INFO, ESMF_LOGWRITE + use dshr_mod , only: dshr_pio_init + use dshr_strdata_mod , only: shr_strdata_type + use dshr_strdata_mod , only: shr_strdata_init_from_inline + use dshr_strdata_mod , only: shr_strdata_advance + use dshr_methods_mod , only: dshr_fldbun_getfldptr + use dshr_stream_mod , only: shr_stream_init_from_esmfconfig + use MOM_cap_methods , only: ChkErr + + implicit none + private + + public mom_inline_init + public mom_inline_run + + type(shr_strdata_type) :: sdat ! stream dat + ! need array to hold dust input + + character(len=*), parameter :: u_FILE_u = __FILE__ +contains + + subroutine mom_inline_init(gcomp, clock, mesh, logunit, streamconfigfile, rc) + + ! input/output parameters + type(ESMF_GridComp) , intent(in) :: gcomp + type(ESMF_Clock) , intent(in) :: clock + type(ESMF_Mesh) , intent(in) :: mesh + integer , intent(in) :: logunit + character(len=*) , intent(in) :: streamconfigfile + integer , intent(out) :: rc + + ! CMEPS Init PIO + call dshr_pio_init(gcomp, sdat, logunit, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Read stream configuration file + ! TODO: At this point it only suports ESMF config format (XML?) + !streamfilename = 'stream.config' + call shr_stream_init_from_esmfconfig(streamconfigfile, sdat%stream, logunit, & + sdat%pio_subsystem, sdat%io_type, sdat%io_format, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! ! 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_varnames = ',trim(stream_dust_varnames) + ! 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 + + ! ! allocate field to hold dust fields + ! allocate(dust_stream(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy,ndust), stat=errstat) + ! if (errstat /= 0) then + ! stop 'not enough memory for dust_stream' + ! end if + ! dust_stream(:,:,:) = 0.0 + + end subroutine mom_inline_init + + subroutine mom_inline_run(clock, logunit, rc) + + ! input/output variables + type(ESMF_Clock), intent(in) :: clock + integer , intent(in) :: logunit + integer , intent(out) :: rc + + ! local variables + type(ESMF_Time) :: date + integer :: i,j,n,nfld + 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(ESMF_KIND_R8), pointer :: dataptr1(:) + real(ESMF_KIND_R8), parameter :: mval = -1.e12_ESMF_KIND_R8 + real(ESMF_KIND_R8), parameter :: fval = -1.e13_ESMF_KIND_R8 + !----------------------------------------------------------------------- + + ! Advance sdat stream + call ESMF_ClockGet( clock, currTime=date, rc=rc ) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_TimeGet(date, yy=year, mm=mon, dd=day, s=sec, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + mcdate = year*10000 + mon*100 + day + + call shr_strdata_advance(sdat, ymd=mcdate, tod=sec, logunit=logunit, istr='dust', rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! ! Set to unreasonable value to catch errors + ! dust_stream(:,:,:) = 1.e30 + ! do nfld = 1, size(stream_varnames) + + ! ! 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_varnames(nfld), fldptr1=dataptr1, rc=rc) + ! if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! ! fill internal MOM variable w/ fldptr + ! end do + + end subroutine mom_inline_run + +end module mom_inline_mod From 0cd6d821fce165ee2ea4bbed3cde153a04cde190 Mon Sep 17 00:00:00 2001 From: Denise Worthen Date: Wed, 2 Jul 2025 12:43:30 -0400 Subject: [PATCH 2/9] initial working version...using dust for runoff ! --- config_src/drivers/nuopc_cap/mom_cap.F90 | 6 +- config_src/drivers/nuopc_cap/mom_inline.F90 | 118 ------------- .../drivers/nuopc_cap/mom_inline_mod.F90 | 165 ++++++++++++++++++ 3 files changed, 169 insertions(+), 120 deletions(-) delete mode 100644 config_src/drivers/nuopc_cap/mom_inline.F90 create mode 100644 config_src/drivers/nuopc_cap/mom_inline_mod.F90 diff --git a/config_src/drivers/nuopc_cap/mom_cap.F90 b/config_src/drivers/nuopc_cap/mom_cap.F90 index 9a5f1b64f1..7604d65781 100644 --- a/config_src/drivers/nuopc_cap/mom_cap.F90 +++ b/config_src/drivers/nuopc_cap/mom_cap.F90 @@ -1578,7 +1578,7 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) call mom_set_geomtype(geomtype) if (len_trim(streamconfigfile) > 0) then - call mom_inline_init(gcomp, clock, eMesh, stdout, streamconfigfile, rc=rc) + call mom_inline_init(gcomp, clock, eMesh, localPet, stdout, streamconfigfile, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return end if @@ -1742,6 +1742,7 @@ subroutine ModelAdvance(gcomp, rc) real(8) :: MPI_Wtime, timers logical :: write_restart, write_restartfh logical :: write_restart_eor + integer :: isc, iec, jsc, jec rc = ESMF_SUCCESS if(profile_memory) call ESMF_VMLogMemInfo("Entering MOM Model_ADVANCE: ") @@ -1857,7 +1858,8 @@ subroutine ModelAdvance(gcomp, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return !some logical - call mom_inline_run(clock, stdout, rc=rc) + call get_domain_extent(ocean_public%domain, isc, iec, jsc, jec) + call mom_inline_run(clock, isc, iec, jsc, jec, ice_ocean_boundary%lrunoff, stdout, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return !--------------- diff --git a/config_src/drivers/nuopc_cap/mom_inline.F90 b/config_src/drivers/nuopc_cap/mom_inline.F90 deleted file mode 100644 index bbf92661bd..0000000000 --- a/config_src/drivers/nuopc_cap/mom_inline.F90 +++ /dev/null @@ -1,118 +0,0 @@ -module mom_inline_mod - - use ESMF , only: ESMF_GridComp, ESMF_Mesh - use ESMF , only: ESMF_Clock, ESMF_Time, ESMF_TimeGet, ESMF_ClockGet - use ESMF , only: ESMF_KIND_R8, ESMF_SUCCESS, ESMF_LogFoundError - use ESMF , only: ESMF_LOGERR_PASSTHRU, ESMF_LOGMSG_INFO, ESMF_LOGWRITE - use dshr_mod , only: dshr_pio_init - use dshr_strdata_mod , only: shr_strdata_type - use dshr_strdata_mod , only: shr_strdata_init_from_inline - use dshr_strdata_mod , only: shr_strdata_advance - use dshr_methods_mod , only: dshr_fldbun_getfldptr - use dshr_stream_mod , only: shr_stream_init_from_esmfconfig - use MOM_cap_methods , only: ChkErr - - implicit none - private - - public mom_inline_init - public mom_inline_run - - type(shr_strdata_type) :: sdat ! stream dat - ! need array to hold dust input - - character(len=*), parameter :: u_FILE_u = __FILE__ -contains - - subroutine mom_inline_init(gcomp, clock, mesh, logunit, streamconfigfile, rc) - - ! input/output parameters - type(ESMF_GridComp) , intent(in) :: gcomp - type(ESMF_Clock) , intent(in) :: clock - type(ESMF_Mesh) , intent(in) :: mesh - integer , intent(in) :: logunit - character(len=*) , intent(in) :: streamconfigfile - integer , intent(out) :: rc - - ! CMEPS Init PIO - call dshr_pio_init(gcomp, sdat, logunit, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - - ! Read stream configuration file - ! TODO: At this point it only suports ESMF config format (XML?) - !streamfilename = 'stream.config' - call shr_stream_init_from_esmfconfig(streamconfigfile, sdat%stream, logunit, & - sdat%pio_subsystem, sdat%io_type, sdat%io_format, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - - ! ! 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_varnames = ',trim(stream_dust_varnames) - ! 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 - - ! ! allocate field to hold dust fields - ! allocate(dust_stream(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy,ndust), stat=errstat) - ! if (errstat /= 0) then - ! stop 'not enough memory for dust_stream' - ! end if - ! dust_stream(:,:,:) = 0.0 - - end subroutine mom_inline_init - - subroutine mom_inline_run(clock, logunit, rc) - - ! input/output variables - type(ESMF_Clock), intent(in) :: clock - integer , intent(in) :: logunit - integer , intent(out) :: rc - - ! local variables - type(ESMF_Time) :: date - integer :: i,j,n,nfld - 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(ESMF_KIND_R8), pointer :: dataptr1(:) - real(ESMF_KIND_R8), parameter :: mval = -1.e12_ESMF_KIND_R8 - real(ESMF_KIND_R8), parameter :: fval = -1.e13_ESMF_KIND_R8 - !----------------------------------------------------------------------- - - ! Advance sdat stream - call ESMF_ClockGet( clock, currTime=date, rc=rc ) - if (chkerr(rc,__LINE__,u_FILE_u)) return - call ESMF_TimeGet(date, yy=year, mm=mon, dd=day, s=sec, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - mcdate = year*10000 + mon*100 + day - - call shr_strdata_advance(sdat, ymd=mcdate, tod=sec, logunit=logunit, istr='dust', rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - - ! ! Set to unreasonable value to catch errors - ! dust_stream(:,:,:) = 1.e30 - ! do nfld = 1, size(stream_varnames) - - ! ! 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_varnames(nfld), fldptr1=dataptr1, rc=rc) - ! if (chkerr(rc,__LINE__,u_FILE_u)) return - - ! ! fill internal MOM variable w/ fldptr - ! end do - - end subroutine mom_inline_run - -end module mom_inline_mod diff --git a/config_src/drivers/nuopc_cap/mom_inline_mod.F90 b/config_src/drivers/nuopc_cap/mom_inline_mod.F90 new file mode 100644 index 0000000000..80c4900f96 --- /dev/null +++ b/config_src/drivers/nuopc_cap/mom_inline_mod.F90 @@ -0,0 +1,165 @@ +module mom_inline_mod + + use ESMF , only: ESMF_GridComp, ESMF_Mesh + use ESMF , only: ESMF_Clock, ESMF_Time, ESMF_TimeGet, ESMF_ClockGet + use ESMF , only: ESMF_KIND_R8, ESMF_SUCCESS, ESMF_LogFoundError + use ESMF , only: ESMF_LOGERR_PASSTHRU, ESMF_LOGMSG_INFO, ESMF_LOGWRITE + use ESMF , only: ESMF_MAXSTR + use dshr_mod , only: dshr_pio_init + use dshr_strdata_mod , only: shr_strdata_type, shr_strdata_print + use dshr_strdata_mod , only: shr_strdata_init_from_inline + use dshr_strdata_mod , only: shr_strdata_advance + use dshr_methods_mod , only: dshr_fldbun_getfldptr + use dshr_stream_mod , only: shr_stream_init_from_esmfconfig + use MOM_cap_methods , only: ChkErr + + implicit none + private + + public mom_inline_init + public mom_inline_run + + type(shr_strdata_type) :: sdat ! input data stream + + character(len=*), parameter :: u_FILE_u = __FILE__ +contains + + subroutine mom_inline_init(gcomp, model_clock, model_mesh, mytask, logunit, streamconfigfile, rc) + + ! input/output parameters + type(ESMF_GridComp) , intent(in) :: gcomp + type(ESMF_Clock) , intent(in) :: model_clock + type(ESMF_Mesh) , intent(in) :: model_mesh + integer , intent(in) :: logunit + integer , intent(in) :: mytask + character(len=*) , intent(in) :: streamconfigfile + integer , intent(out) :: rc + + integer :: ns, nf, nv + integer :: nstreams, nfiles, nvars + + character(len=ESMF_MAXSTR), allocatable :: streamfilelist(:) + character(len=ESMF_MAXSTR), allocatable :: streamfilevars(:,:) + character(len=*), parameter :: subname='(mom_inline_init)' + + ! CMEPS Init PIO + call dshr_pio_init(gcomp, sdat, logunit, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + call shr_stream_init_from_esmfconfig(streamconfigfile, sdat%stream, logunit, & + sdat%pio_subsystem, sdat%io_type, sdat%io_format, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + nstreams = size(sdat%stream) ! should always be only 1 for inline? + nfiles = sdat%stream(1)%nfiles + nvars = sdat%stream(1)%nvars + + allocate(streamfilelist(1:nfiles)) + allocate(streamfilevars(1:nvars,2)) + + ! build the file and variable lists + do ns = 1,nstreams + do nf = 1,nfiles + streamfilelist(nf) = trim(sdat%stream(1)%file(nf)%name) + if (mytask == 0) print *,'XX1 ',nf,trim(streamfilelist(nf)) + end do + do nv = 1,nvars + streamfilevars(nv,1) = trim(sdat%stream(1)%varlist(nv)%nameinfile) + streamfilevars(nv,2) = trim(sdat%stream(1)%varlist(nv)%nameinmodel) + if (mytask == 0) print *,'XX1 ',nv,trim(streamfilevars(nv,1)),' ',trim(streamfilevars(nv,2)) + end do + end do + + if (mytask == 0) then + write(logunit,'(a)') ' stream settings: ' + write(logunit,'(a)' ) ' stream_mesh_filename = '//trim(sdat%stream(1)%meshfile) + do nf = 1,nfiles + write(logunit,'(a)' ) ' stream_filenames = '//trim(streamfilelist(nf)) + end do + do nv = 1,nvars + write(logunit,'(a)' ) ' stream_fldlist file,model = '//trim(streamfilevars(nv,1))//' '//trim(streamfilevars(nv,2)) + end do + write(logunit,'(a,i8)') ' stream_year_first = ',sdat%stream(1)%yearFirst + write(logunit,'(a,i8)') ' stream_year_last = ',sdat%stream(1)%yearLast + write(logunit,'(a,i8)') ' stream_year_align = ',sdat%stream(1)%yearAlign + write(logunit,'(a)' ) ' ' + endif + + ! initialize sdat + call shr_strdata_init_from_inline(sdat, & + my_task = mytask, & + logunit = logunit, & + compname = 'OCN', & + model_clock = model_clock, & + model_mesh = model_mesh, & + stream_meshfile = trim(sdat%stream(1)%meshfile), & + stream_lev_dimname = 'null', & + stream_mapalgo = trim(sdat%stream(1)%mapalgo), & + stream_filenames = streamfilelist, & + stream_fldlistFile = streamfilevars(:,1), & + stream_fldListModel = streamfilevars(:,2), & + stream_yearFirst = sdat%stream(1)%yearFirst, & + stream_yearLast = sdat%stream(1)%yearLast, & + stream_yearAlign = sdat%stream(1)%yearAlign , & + stream_offset = 0, & + stream_taxmode = trim(sdat%stream(1)%taxmode), & + stream_dtlimit = sdat%stream(1)%dtlimit, & + stream_tintalgo = trim(sdat%stream(1)%tinterpalgo), & + rc = rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + end subroutine mom_inline_init + + subroutine mom_inline_run(clock, isc, iec, jsc, jec, output, logunit, rc) + + ! input/output variables + type(ESMF_Clock) , intent(in) :: clock + integer , intent(in) :: isc !< The start i-index of cell centers within + !! the computational domain + integer , intent(in) :: iec !< The end i-index of cell centers within the + !! computational domain + integer , intent(in) :: jsc !< The start j-index of cell centers within + !! the computational domain + integer , intent(in) :: jec !< The end j-index of cell centers within + !! the computational domain + real (ESMF_KIND_R8) , intent(inout) :: output(isc:iec,jsc:jec) !< Output 2D array + + integer , intent(in) :: logunit + integer , intent(out) :: rc + + ! local variables + type(ESMF_Time) :: date + integer :: i,j,n + 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(ESMF_KIND_R8), pointer :: dataPtr1d(:) + !----------------------------------------------------------------------- + + ! Advance sdat stream + call ESMF_ClockGet( clock, currTime=date, rc=rc ) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_TimeGet(date, yy=year, mm=mon, dd=day, s=sec, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + mcdate = year*10000 + mon*100 + day + + call shr_strdata_advance(sdat, ymd=mcdate, tod=sec, logunit=logunit, istr='merra2_runoff', rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Get pointer for stream data that is time and spatially interpolated to model time and grid + call dshr_fldbun_getFldPtr(sdat%pstrm(1)%fldbun_model, 'DUCMASS', dataPtr1d, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + n = 0 + do j = jsc,jec + do i = isc,iec + n = n + 1 + output(i,j) = output(i,j) + dataPtr1d(n) + end do + end do + + end subroutine mom_inline_run + +end module mom_inline_mod From cb6f730c8ce58b6c42219e928151811aee3ec67b Mon Sep 17 00:00:00 2001 From: "denise.worthen" Date: Thu, 3 Jul 2025 17:35:06 -0500 Subject: [PATCH 3/9] add local log unit and fb diagnose; fails if multi input files --- config_src/drivers/nuopc_cap/mom_cap.F90 | 4 +- .../drivers/nuopc_cap/mom_inline_mod.F90 | 53 +++++++++++++------ 2 files changed, 38 insertions(+), 19 deletions(-) diff --git a/config_src/drivers/nuopc_cap/mom_cap.F90 b/config_src/drivers/nuopc_cap/mom_cap.F90 index 7604d65781..7b8aee8632 100644 --- a/config_src/drivers/nuopc_cap/mom_cap.F90 +++ b/config_src/drivers/nuopc_cap/mom_cap.F90 @@ -1578,7 +1578,7 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) call mom_set_geomtype(geomtype) if (len_trim(streamconfigfile) > 0) then - call mom_inline_init(gcomp, clock, eMesh, localPet, stdout, streamconfigfile, rc=rc) + call mom_inline_init(gcomp, clock, eMesh, localPet, streamconfigfile, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return end if @@ -1859,7 +1859,7 @@ subroutine ModelAdvance(gcomp, rc) !some logical call get_domain_extent(ocean_public%domain, isc, iec, jsc, jec) - call mom_inline_run(clock, isc, iec, jsc, jec, ice_ocean_boundary%lrunoff, stdout, rc=rc) + call mom_inline_run(clock, isc, iec, jsc, jec, ice_ocean_boundary%lrunoff, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return !--------------- diff --git a/config_src/drivers/nuopc_cap/mom_inline_mod.F90 b/config_src/drivers/nuopc_cap/mom_inline_mod.F90 index 80c4900f96..6421d3778d 100644 --- a/config_src/drivers/nuopc_cap/mom_inline_mod.F90 +++ b/config_src/drivers/nuopc_cap/mom_inline_mod.F90 @@ -9,7 +9,7 @@ module mom_inline_mod use dshr_strdata_mod , only: shr_strdata_type, shr_strdata_print use dshr_strdata_mod , only: shr_strdata_init_from_inline use dshr_strdata_mod , only: shr_strdata_advance - use dshr_methods_mod , only: dshr_fldbun_getfldptr + use dshr_methods_mod , only: dshr_fldbun_getfldptr, dshr_fldbun_Field_diagnose use dshr_stream_mod , only: shr_stream_init_from_esmfconfig use MOM_cap_methods , only: ChkErr @@ -19,28 +19,38 @@ module mom_inline_mod public mom_inline_init public mom_inline_run + integer :: logunit ! the logunit on mytask = 0 + + character(len=ESMF_MAXSTR), allocatable :: streamfilelist(:) + character(len=ESMF_MAXSTR), allocatable :: streamfilevars(:,:) + type(shr_strdata_type) :: sdat ! input data stream character(len=*), parameter :: u_FILE_u = __FILE__ contains - - subroutine mom_inline_init(gcomp, model_clock, model_mesh, mytask, logunit, streamconfigfile, rc) + !=============================================================================== + subroutine mom_inline_init(gcomp, model_clock, model_mesh, mytask, streamconfigfile, rc) ! input/output parameters type(ESMF_GridComp) , intent(in) :: gcomp type(ESMF_Clock) , intent(in) :: model_clock type(ESMF_Mesh) , intent(in) :: model_mesh - integer , intent(in) :: logunit integer , intent(in) :: mytask character(len=*) , intent(in) :: streamconfigfile integer , intent(out) :: rc integer :: ns, nf, nv integer :: nstreams, nfiles, nvars - - character(len=ESMF_MAXSTR), allocatable :: streamfilelist(:) - character(len=ESMF_MAXSTR), allocatable :: streamfilevars(:,:) character(len=*), parameter :: subname='(mom_inline_init)' + !---------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + if (mytask == 0) then + open (newunit=logunit, file='log.mom6.cdeps') + else + logunit = 6 + end if ! CMEPS Init PIO call dshr_pio_init(gcomp, sdat, logunit, rc=rc) @@ -109,8 +119,9 @@ subroutine mom_inline_init(gcomp, model_clock, model_mesh, mytask, logunit, stre if (ChkErr(rc,__LINE__,u_FILE_u)) return end subroutine mom_inline_init +!=============================================================================== - subroutine mom_inline_run(clock, isc, iec, jsc, jec, output, logunit, rc) + subroutine mom_inline_run(clock, isc, iec, jsc, jec, output, rc) ! input/output variables type(ESMF_Clock) , intent(in) :: clock @@ -124,20 +135,22 @@ subroutine mom_inline_run(clock, isc, iec, jsc, jec, output, logunit, rc) !! the computational domain real (ESMF_KIND_R8) , intent(inout) :: output(isc:iec,jsc:jec) !< Output 2D array - integer , intent(in) :: logunit integer , intent(out) :: rc ! local variables - type(ESMF_Time) :: date - integer :: i,j,n - 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(ESMF_KIND_R8), pointer :: dataPtr1d(:) + type(ESMF_Time) :: date + integer :: i,j,n + character(len=ESMF_MAXSTR) :: fldname + 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(ESMF_KIND_R8), pointer :: dataPtr1d(:) !----------------------------------------------------------------------- + rc = ESMF_SUCCESS + ! Advance sdat stream call ESMF_ClockGet( clock, currTime=date, rc=rc ) if (chkerr(rc,__LINE__,u_FILE_u)) return @@ -145,6 +158,9 @@ subroutine mom_inline_run(clock, isc, iec, jsc, jec, output, logunit, rc) if (chkerr(rc,__LINE__,u_FILE_u)) return mcdate = year*10000 + mon*100 + day + ! field name in file + fldname = streamfilevars(1,1) + call shr_strdata_advance(sdat, ymd=mcdate, tod=sec, logunit=logunit, istr='merra2_runoff', rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return @@ -152,6 +168,9 @@ subroutine mom_inline_run(clock, isc, iec, jsc, jec, output, logunit, rc) call dshr_fldbun_getFldPtr(sdat%pstrm(1)%fldbun_model, 'DUCMASS', dataPtr1d, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return + call dshr_fldbun_Field_diagnose(sdat%pstrm(1)%fldbun_model, trim(fldname), rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + n = 0 do j = jsc,jec do i = isc,iec From 8b7e47ef7f5dbbae769cff0f7e80f1073816cb6d Mon Sep 17 00:00:00 2001 From: "denise.worthen" Date: Mon, 7 Jul 2025 14:23:14 -0500 Subject: [PATCH 4/9] initialize single streams from multiple configured streams --- config_src/drivers/nuopc_cap/mom_cap.F90 | 6 +- .../drivers/nuopc_cap/mom_inline_mod.F90 | 213 ++++++++++++------ 2 files changed, 145 insertions(+), 74 deletions(-) diff --git a/config_src/drivers/nuopc_cap/mom_cap.F90 b/config_src/drivers/nuopc_cap/mom_cap.F90 index 7b8aee8632..97408b414c 100644 --- a/config_src/drivers/nuopc_cap/mom_cap.F90 +++ b/config_src/drivers/nuopc_cap/mom_cap.F90 @@ -1857,9 +1857,11 @@ subroutine ModelAdvance(gcomp, rc) call mom_import(ocean_public, ocean_grid, importState, ice_ocean_boundary, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - !some logical + !...some logical... call get_domain_extent(ocean_public%domain, isc, iec, jsc, jec) - call mom_inline_run(clock, isc, iec, jsc, jec, ice_ocean_boundary%lrunoff, rc=rc) + call mom_inline_run(clock, isc, iec, jsc, jec, 'lrunoff', ice_ocean_boundary%lrunoff, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call mom_inline_run(clock, isc, iec, jsc, jec, 'frunoff', ice_ocean_boundary%frunoff, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return !--------------- diff --git a/config_src/drivers/nuopc_cap/mom_inline_mod.F90 b/config_src/drivers/nuopc_cap/mom_inline_mod.F90 index 6421d3778d..8cecb24d62 100644 --- a/config_src/drivers/nuopc_cap/mom_inline_mod.F90 +++ b/config_src/drivers/nuopc_cap/mom_inline_mod.F90 @@ -19,12 +19,10 @@ module mom_inline_mod public mom_inline_init public mom_inline_run - integer :: logunit ! the logunit on mytask = 0 - - character(len=ESMF_MAXSTR), allocatable :: streamfilelist(:) - character(len=ESMF_MAXSTR), allocatable :: streamfilevars(:,:) - - type(shr_strdata_type) :: sdat ! input data stream + integer :: logunit ! the logunit on the root task + ! available streams + type(shr_strdata_type) :: sdat_lrunoff + type(shr_strdata_type) :: sdat_frunoff character(len=*), parameter :: u_FILE_u = __FILE__ contains @@ -39,8 +37,15 @@ subroutine mom_inline_init(gcomp, model_clock, model_mesh, mytask, streamconfigf character(len=*) , intent(in) :: streamconfigfile integer , intent(out) :: rc - integer :: ns, nf, nv - integer :: nstreams, nfiles, nvars + ! stream data from config (xml or esmf), one or more streams + type(shr_strdata_type) :: sdat + + integer :: id_lrunoff=0 + integer :: id_frunoff=0 + + integer :: ns, nv + integer :: nstreams, nvars + character(len=*), parameter :: subname='(mom_inline_init)' !---------------------------------------------------------------------- @@ -52,76 +57,47 @@ subroutine mom_inline_init(gcomp, model_clock, model_mesh, mytask, streamconfigf logunit = 6 end if +#ifndef CESMCOUPLED ! CMEPS Init PIO call dshr_pio_init(gcomp, sdat, logunit, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return + ! read the available stream definitions, each data stream is one or more data_files + ! which have the same spatial and temporal coordinates + ! returns sdat%stream, of type shr_stream_streamType call shr_stream_init_from_esmfconfig(streamconfigfile, sdat%stream, logunit, & sdat%pio_subsystem, sdat%io_type, sdat%io_format, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - - nstreams = size(sdat%stream) ! should always be only 1 for inline? - nfiles = sdat%stream(1)%nfiles - nvars = sdat%stream(1)%nvars - - allocate(streamfilelist(1:nfiles)) - allocate(streamfilevars(1:nvars,2)) - - ! build the file and variable lists +#else + !do cesm stuff...point to shr, use xml +#endif + ! set the model clock and mesh + sdat%model_clock = model_clock + sdat%model_mesh = model_mesh + + nstreams = size(sdat%stream) + ! locate the individual stream data do ns = 1,nstreams - do nf = 1,nfiles - streamfilelist(nf) = trim(sdat%stream(1)%file(nf)%name) - if (mytask == 0) print *,'XX1 ',nf,trim(streamfilelist(nf)) - end do + nvars = sdat%stream(ns)%nvars do nv = 1,nvars - streamfilevars(nv,1) = trim(sdat%stream(1)%varlist(nv)%nameinfile) - streamfilevars(nv,2) = trim(sdat%stream(1)%varlist(nv)%nameinmodel) - if (mytask == 0) print *,'XX1 ',nv,trim(streamfilevars(nv,1)),' ',trim(streamfilevars(nv,2)) + if (trim(sdat%stream(ns)%varlist(nv)%nameinmodel) == 'lrunoff') id_lrunoff = ns + if (trim(sdat%stream(ns)%varlist(nv)%nameinmodel) == 'frunoff') id_frunoff = ns end do end do - if (mytask == 0) then - write(logunit,'(a)') ' stream settings: ' - write(logunit,'(a)' ) ' stream_mesh_filename = '//trim(sdat%stream(1)%meshfile) - do nf = 1,nfiles - write(logunit,'(a)' ) ' stream_filenames = '//trim(streamfilelist(nf)) - end do - do nv = 1,nvars - write(logunit,'(a)' ) ' stream_fldlist file,model = '//trim(streamfilevars(nv,1))//' '//trim(streamfilevars(nv,2)) - end do - write(logunit,'(a,i8)') ' stream_year_first = ',sdat%stream(1)%yearFirst - write(logunit,'(a,i8)') ' stream_year_last = ',sdat%stream(1)%yearLast - write(logunit,'(a,i8)') ' stream_year_align = ',sdat%stream(1)%yearAlign - write(logunit,'(a)' ) ' ' - endif - - ! initialize sdat - call shr_strdata_init_from_inline(sdat, & - my_task = mytask, & - logunit = logunit, & - compname = 'OCN', & - model_clock = model_clock, & - model_mesh = model_mesh, & - stream_meshfile = trim(sdat%stream(1)%meshfile), & - stream_lev_dimname = 'null', & - stream_mapalgo = trim(sdat%stream(1)%mapalgo), & - stream_filenames = streamfilelist, & - stream_fldlistFile = streamfilevars(:,1), & - stream_fldListModel = streamfilevars(:,2), & - stream_yearFirst = sdat%stream(1)%yearFirst, & - stream_yearLast = sdat%stream(1)%yearLast, & - stream_yearAlign = sdat%stream(1)%yearAlign , & - stream_offset = 0, & - stream_taxmode = trim(sdat%stream(1)%taxmode), & - stream_dtlimit = sdat%stream(1)%dtlimit, & - stream_tintalgo = trim(sdat%stream(1)%tinterpalgo), & - rc = rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (id_lrunoff /= 0) then + call initialize_single_stream(sdat, sdat_lrunoff, id_lrunoff, 'lrunoff', 'OCN', mytask, logunit, rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + end if + if (id_frunoff /= 0) then + call initialize_single_stream(sdat, sdat_frunoff, id_frunoff, 'frunoff', 'OCN', mytask, logunit, rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + end if end subroutine mom_inline_init !=============================================================================== - subroutine mom_inline_run(clock, isc, iec, jsc, jec, output, rc) + subroutine mom_inline_run(clock, isc, iec, jsc, jec, fldname, output, rc) ! input/output variables type(ESMF_Clock) , intent(in) :: clock @@ -133,6 +109,7 @@ subroutine mom_inline_run(clock, isc, iec, jsc, jec, output, rc) !! the computational domain integer , intent(in) :: jec !< The end j-index of cell centers within !! the computational domain + character(len=*) , intent(in) :: fldname !! the stream name real (ESMF_KIND_R8) , intent(inout) :: output(isc:iec,jsc:jec) !< Output 2D array integer , intent(out) :: rc @@ -140,7 +117,6 @@ subroutine mom_inline_run(clock, isc, iec, jsc, jec, output, rc) ! local variables type(ESMF_Time) :: date integer :: i,j,n - character(len=ESMF_MAXSTR) :: fldname 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 @@ -158,18 +134,28 @@ subroutine mom_inline_run(clock, isc, iec, jsc, jec, output, rc) if (chkerr(rc,__LINE__,u_FILE_u)) return mcdate = year*10000 + mon*100 + day - ! field name in file - fldname = streamfilevars(1,1) + if (trim(fldname) == 'lrunoff') then + call shr_strdata_advance(sdat_lrunoff, ymd=mcdate, tod=sec, logunit=logunit, istr='lrunoff stream',rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return - call shr_strdata_advance(sdat, ymd=mcdate, tod=sec, logunit=logunit, istr='merra2_runoff', rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return + ! Get pointer for stream data that is time and spatially interpolated to model time and grid + call dshr_fldbun_getFldPtr(sdat_lrunoff%pstrm(1)%fldbun_model, trim(fldname), dataPtr1d, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return - ! Get pointer for stream data that is time and spatially interpolated to model time and grid - call dshr_fldbun_getFldPtr(sdat%pstrm(1)%fldbun_model, 'DUCMASS', dataPtr1d, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return + call dshr_fldbun_Field_diagnose(sdat_lrunoff%pstrm(1)%fldbun_model, trim(fldname), rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + end if + if (trim(fldname) == 'frunoff') then + call shr_strdata_advance(sdat_frunoff, ymd=mcdate, tod=sec, logunit=logunit, istr='frunoff stream', rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return - call dshr_fldbun_Field_diagnose(sdat%pstrm(1)%fldbun_model, trim(fldname), rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return + ! Get pointer for stream data that is time and spatially interpolated to model time and grid + call dshr_fldbun_getFldPtr(sdat_frunoff%pstrm(1)%fldbun_model, trim(fldname), dataPtr1d, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + call dshr_fldbun_Field_diagnose(sdat_frunoff%pstrm(1)%fldbun_model, trim(fldname), rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + end if n = 0 do j = jsc,jec @@ -180,5 +166,88 @@ subroutine mom_inline_run(clock, isc, iec, jsc, jec, output, rc) end do end subroutine mom_inline_run + !=============================================================================== + + subroutine initialize_single_stream(sdatm, sdats, sid, sdatname, compname, mytask, logunit, rc) + + type(shr_strdata_type), intent(inout) :: sdatm + type(shr_strdata_type), intent(inout) :: sdats + integer, intent(in) :: sid + character(len=*), intent(in) :: sdatname + character(len=*), intent(in) :: compname + integer, intent(in) :: mytask + integer, intent(in) :: logunit + integer , intent(out) :: rc + + ! local + integer :: nfiles, nvars, nf, nv + character(len=ESMF_MAXSTR), allocatable :: filelist(:) + character(len=ESMF_MAXSTR), allocatable :: filevars(:,:) + + !----------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + nfiles = sdatm%stream(sid)%nfiles + nvars = sdatm%stream(sid)%nvars + + allocate(filelist(1:nfiles)) + allocate(filevars(1:nvars,2)) + + do nf = 1,nfiles + filelist(nf) = trim(sdatm%stream(sid)%file(nf)%name) + end do + do nv = 1,nvars + filevars(nv,1) = trim(sdatm%stream(sid)%varlist(nv)%nameinfile) + filevars(nv,2) = trim(sdatm%stream(sid)%varlist(nv)%nameinmodel) + end do + + ! Write out info + if (mytask == 0) then + write(logunit,'(a)' ) ' ' + write(logunit,'(a,i8)') 'stream settings:',sid + do nf = 1,nfiles + write(logunit,'(a)' ) ' stream file list = '//trim(filelist(nf)) + end do + do nv = 1,nvars + write(logunit,'(a)' ) ' stream variable in file= '//trim(filevars(nv,1))//' ; variable in model '//trim(filevars(nv,2)) + write(logunit,'(a)' ) ' ' + end do + endif + + ! Set PIO related variables + sdats%pio_subsystem => sdatm%pio_subsystem + sdats%io_type = sdatm%io_type + sdats%io_format = sdatm%io_format + + call shr_strdata_init_from_inline(sdats, & + my_task = mytask, & + logunit = logunit, & + compname = trim(compname), & + model_clock = sdatm%model_clock, & + model_mesh = sdatm%model_mesh, & + stream_name = trim(sdatname), & + stream_meshfile = trim(sdatm%stream(sid)%meshFile), & + stream_filenames = filelist, & + stream_yearFirst = sdatm%stream(sid)%yearFirst, & + stream_yearLast = sdatm%stream(sid)%yearLast, & + stream_yearAlign = sdatm%stream(sid)%yearAlign, & + stream_fldlistFile = filevars(:,1), & + stream_fldListModel = filevars(:,2), & + stream_lev_dimname = trim(sdatm%stream(sid)%lev_dimname), & + stream_mapalgo = trim(sdatm%stream(sid)%mapAlgo), & + stream_offset = sdatm%stream(sid)%offset, & + stream_taxmode = trim(sdatm%stream(sid)%taxmode), & + stream_dtlimit = sdatm%stream(sid)%dtlimit, & + stream_tintalgo = trim(sdatm%stream(sid)%tInterpAlgo), & + stream_src_mask = sdatm%stream(sid)%src_mask_val, & + stream_dst_mask = sdatm%stream(sid)%dst_mask_val, & + rc = rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + deallocate(filelist) + deallocate(filevars) + + end subroutine initialize_single_stream end module mom_inline_mod From 51a031d54a61f6c1d8a5757a9d6f09c55e153b65 Mon Sep 17 00:00:00 2001 From: "denise.worthen" Date: Tue, 8 Jul 2025 08:01:03 -0500 Subject: [PATCH 5/9] fix summation in inline_run --- config_src/drivers/nuopc_cap/mom_inline_mod.F90 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/config_src/drivers/nuopc_cap/mom_inline_mod.F90 b/config_src/drivers/nuopc_cap/mom_inline_mod.F90 index 8cecb24d62..ff8bda3625 100644 --- a/config_src/drivers/nuopc_cap/mom_inline_mod.F90 +++ b/config_src/drivers/nuopc_cap/mom_inline_mod.F90 @@ -97,6 +97,7 @@ subroutine mom_inline_init(gcomp, model_clock, model_mesh, mytask, streamconfigf end subroutine mom_inline_init !=============================================================================== + !call mom_inline_run(clock, isc, iec, jsc, jec, 'lrunoff', ice_ocean_boundary%lrunoff, rc=rc) subroutine mom_inline_run(clock, isc, iec, jsc, jec, fldname, output, rc) ! input/output variables @@ -161,7 +162,7 @@ subroutine mom_inline_run(clock, isc, iec, jsc, jec, fldname, output, rc) do j = jsc,jec do i = isc,iec n = n + 1 - output(i,j) = output(i,j) + dataPtr1d(n) + output(i,j) = dataPtr1d(n) end do end do @@ -210,7 +211,7 @@ subroutine initialize_single_stream(sdatm, sdats, sid, sdatname, compname, mytas write(logunit,'(a)' ) ' stream file list = '//trim(filelist(nf)) end do do nv = 1,nvars - write(logunit,'(a)' ) ' stream variable in file= '//trim(filevars(nv,1))//' ; variable in model '//trim(filevars(nv,2)) + write(logunit,'(a)' ) ' stream variable in file= '//trim(filevars(nv,1))//' ; variable in model= '//trim(filevars(nv,2)) write(logunit,'(a)' ) ' ' end do endif From cdc17ef967fa47c836f4ff8025ddd29afb8626a0 Mon Sep 17 00:00:00 2001 From: "denise.worthen" Date: Tue, 8 Jul 2025 12:17:56 -0500 Subject: [PATCH 6/9] currently working with merra2 dust standing in for lrunoff mom6.stream.config stream_info: lrunoff01 taxmode01: limit mapalgo01: bilinear tInterpAlgo01: linear readMode01: single dtlimit01: 10.0 stream_offset01: 0.0 yearFirst01: 2011 yearLast01: 2011 yearAlign01: 2011 stream_vectors01: null stream_mesh_file01: INPUT/mesh.merra2.576x361.nc stream_lev_dimname01: null stream_data_files01: INPUT/merra2.ducmass.20111001_10.nc stream_data_variables01: "DUCMASS lrunoff" stream_dst_mask01: 0 --- config_src/drivers/nuopc_cap/mom_cap.F90 | 4 ++-- config_src/drivers/nuopc_cap/mom_inline_mod.F90 | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/config_src/drivers/nuopc_cap/mom_cap.F90 b/config_src/drivers/nuopc_cap/mom_cap.F90 index 97408b414c..595a4ea524 100644 --- a/config_src/drivers/nuopc_cap/mom_cap.F90 +++ b/config_src/drivers/nuopc_cap/mom_cap.F90 @@ -1861,8 +1861,8 @@ subroutine ModelAdvance(gcomp, rc) call get_domain_extent(ocean_public%domain, isc, iec, jsc, jec) call mom_inline_run(clock, isc, iec, jsc, jec, 'lrunoff', ice_ocean_boundary%lrunoff, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - call mom_inline_run(clock, isc, iec, jsc, jec, 'frunoff', ice_ocean_boundary%frunoff, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return + !call mom_inline_run(clock, isc, iec, jsc, jec, 'frunoff', ice_ocean_boundary%frunoff, rc=rc) + !if (ChkErr(rc,__LINE__,u_FILE_u)) return !--------------- ! Update MOM6 diff --git a/config_src/drivers/nuopc_cap/mom_inline_mod.F90 b/config_src/drivers/nuopc_cap/mom_inline_mod.F90 index ff8bda3625..5fc3d3d45f 100644 --- a/config_src/drivers/nuopc_cap/mom_inline_mod.F90 +++ b/config_src/drivers/nuopc_cap/mom_inline_mod.F90 @@ -135,6 +135,7 @@ subroutine mom_inline_run(clock, isc, iec, jsc, jec, fldname, output, rc) if (chkerr(rc,__LINE__,u_FILE_u)) return mcdate = year*10000 + mon*100 + day + ! TODO: need to allow for multiple variables/stream if (trim(fldname) == 'lrunoff') then call shr_strdata_advance(sdat_lrunoff, ymd=mcdate, tod=sec, logunit=logunit, istr='lrunoff stream',rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return From 16f87941ec7dfaef822a927c7f09fc8517017493 Mon Sep 17 00:00:00 2001 From: "denise.worthen" Date: Tue, 8 Jul 2025 13:01:21 -0500 Subject: [PATCH 7/9] to run w/ daitren data need to be permuted ncpdq -a time,j,i runoff.daitren.clim.1440x1080.v20180328.nc permuted.runoff.daitren.clim.1440x1080.v20180328.nc stream_info: lrunoff01 taxmode01: cycle mapalgo01: redist tInterpAlgo01: linear readMode01: single dtlimit01: 1.0 stream_offset01: 0.0 yearFirst01: 1 yearLast01: 1 yearAlign01: 1 stream_vectors01: null stream_mesh_file01: mesh.mx025.nc stream_lev_dimname01: null stream_data_files01: INPUT/permuted.runoff.daitren.clim.1440x1080.v20180328.nc stream_data_variables01: "runoff lrunoff" stream_dst_mask01: 1 From 45a117539610fafca19895a147174c2b170c034d Mon Sep 17 00:00:00 2001 From: Denise Worthen Date: Thu, 7 Aug 2025 14:59:46 -0400 Subject: [PATCH 8/9] generalize streams and run for multiple fields/streams --- config_src/drivers/nuopc_cap/mom_cap.F90 | 20 +- .../drivers/nuopc_cap/mom_inline_mod.F90 | 287 +++++++----------- 2 files changed, 127 insertions(+), 180 deletions(-) diff --git a/config_src/drivers/nuopc_cap/mom_cap.F90 b/config_src/drivers/nuopc_cap/mom_cap.F90 index 595a4ea524..3da33d2283 100644 --- a/config_src/drivers/nuopc_cap/mom_cap.F90 +++ b/config_src/drivers/nuopc_cap/mom_cap.F90 @@ -142,7 +142,7 @@ module MOM_cap_mod logical :: use_coldstart = .true. logical :: use_mommesh = .true. logical :: restart_eor = .false. -character(len=128) :: streamconfigfile = '' +character(len=128) :: streamconfig = '' character(len=128) :: scalar_field_name = '' integer :: scalar_field_count = 0 integer :: scalar_field_idx_grid_nx = 0 @@ -388,8 +388,12 @@ subroutine InitializeP0(gcomp, importState, exportState, clock, rc) geomtype = ESMF_GEOMTYPE_GRID endif - ! - streamconfigfile = 'mom6.stream.config' + call NUOPC_CompAttributeGet(gcomp, name="streamconfig", value=value, isPresent=isPresent, isSet=isSet, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (isPresent .and. isSet) then + streamconfig = trim(value) + endif + ! Read end of run restart config option call NUOPC_CompAttributeGet(gcomp, name="write_restart_at_endofrun", value=value, & isPresent=isPresent, isSet=isSet, rc=rc) @@ -1577,8 +1581,8 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) !--------------------------------- call mom_set_geomtype(geomtype) - if (len_trim(streamconfigfile) > 0) then - call mom_inline_init(gcomp, clock, eMesh, localPet, streamconfigfile, rc=rc) + if (len_trim(streamconfig) > 0) then + call mom_inline_init(gcomp, clock, eMesh, localPet, streamconfig, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return end if @@ -1742,7 +1746,6 @@ subroutine ModelAdvance(gcomp, rc) real(8) :: MPI_Wtime, timers logical :: write_restart, write_restartfh logical :: write_restart_eor - integer :: isc, iec, jsc, jec rc = ESMF_SUCCESS if(profile_memory) call ESMF_VMLogMemInfo("Entering MOM Model_ADVANCE: ") @@ -1858,11 +1861,8 @@ subroutine ModelAdvance(gcomp, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return !...some logical... - call get_domain_extent(ocean_public%domain, isc, iec, jsc, jec) - call mom_inline_run(clock, isc, iec, jsc, jec, 'lrunoff', ice_ocean_boundary%lrunoff, rc=rc) + call mom_inline_run(clock, ocean_public, ocean_grid, ice_ocean_boundary, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - !call mom_inline_run(clock, isc, iec, jsc, jec, 'frunoff', ice_ocean_boundary%frunoff, rc=rc) - !if (ChkErr(rc,__LINE__,u_FILE_u)) return !--------------- ! Update MOM6 diff --git a/config_src/drivers/nuopc_cap/mom_inline_mod.F90 b/config_src/drivers/nuopc_cap/mom_inline_mod.F90 index 5fc3d3d45f..09eaa40fa7 100644 --- a/config_src/drivers/nuopc_cap/mom_inline_mod.F90 +++ b/config_src/drivers/nuopc_cap/mom_inline_mod.F90 @@ -19,237 +19,184 @@ module mom_inline_mod public mom_inline_init public mom_inline_run - integer :: logunit ! the logunit on the root task - ! available streams - type(shr_strdata_type) :: sdat_lrunoff - type(shr_strdata_type) :: sdat_frunoff + type(shr_strdata_type), allocatable :: sdat(:) + + integer :: logunit ! the logunit on the root task + character(len=ESMF_MAXSTR) :: stream_name ! generic identifier character(len=*), parameter :: u_FILE_u = __FILE__ contains !=============================================================================== - subroutine mom_inline_init(gcomp, model_clock, model_mesh, mytask, streamconfigfile, rc) + subroutine mom_inline_init(gcomp, model_clock, model_mesh, mytask, configfile, rc) ! input/output parameters type(ESMF_GridComp) , intent(in) :: gcomp type(ESMF_Clock) , intent(in) :: model_clock type(ESMF_Mesh) , intent(in) :: model_mesh integer , intent(in) :: mytask - character(len=*) , intent(in) :: streamconfigfile + character(len=*) , intent(in) :: configfile integer , intent(out) :: rc ! stream data from config (xml or esmf), one or more streams - type(shr_strdata_type) :: sdat - - integer :: id_lrunoff=0 - integer :: id_frunoff=0 + type(shr_strdata_type) :: sdatconfig - integer :: ns, nv + integer :: ns, l integer :: nstreams, nvars + character(len=ESMF_MAXSTR), allocatable :: filelist(:) + character(len=ESMF_MAXSTR), allocatable :: filevars(:,:) + character(len=*), parameter :: subname='(mom_inline_init)' !---------------------------------------------------------------------- rc = ESMF_SUCCESS if (mytask == 0) then - open (newunit=logunit, file='log.mom6.cdeps') + open (newunit=logunit, file='log.mom6.cdeps') else - logunit = 6 + logunit = 6 end if #ifndef CESMCOUPLED ! CMEPS Init PIO - call dshr_pio_init(gcomp, sdat, logunit, rc=rc) + call dshr_pio_init(gcomp, sdatconfig, logunit, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return ! read the available stream definitions, each data stream is one or more data_files ! which have the same spatial and temporal coordinates - ! returns sdat%stream, of type shr_stream_streamType - call shr_stream_init_from_esmfconfig(streamconfigfile, sdat%stream, logunit, & - sdat%pio_subsystem, sdat%io_type, sdat%io_format, rc=rc) + call shr_stream_init_from_esmfconfig(configfile, sdatconfig%stream, logunit, & + sdatconfig%pio_subsystem, sdatconfig%io_type, sdatconfig%io_format, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return #else - !do cesm stuff...point to shr, use xml + !TODO: cesm configuration via xml etc #endif - ! set the model clock and mesh - sdat%model_clock = model_clock - sdat%model_mesh = model_mesh - nstreams = size(sdat%stream) - ! locate the individual stream data - do ns = 1,nstreams - nvars = sdat%stream(ns)%nvars - do nv = 1,nvars - if (trim(sdat%stream(ns)%varlist(nv)%nameinmodel) == 'lrunoff') id_lrunoff = ns - if (trim(sdat%stream(ns)%varlist(nv)%nameinmodel) == 'frunoff') id_frunoff = ns - end do - end do + nstreams = size(sdatconfig%stream) + ! allocate stream data type + if (.not. allocated(sdat)) allocate(sdat(nstreams)) - if (id_lrunoff /= 0) then - call initialize_single_stream(sdat, sdat_lrunoff, id_lrunoff, 'lrunoff', 'OCN', mytask, logunit, rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - end if - if (id_frunoff /= 0) then - call initialize_single_stream(sdat, sdat_frunoff, id_frunoff, 'frunoff', 'OCN', mytask, logunit, rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - end if + ! set the model clock and mesh + sdat(:)%model_clock = model_clock + sdat(:)%model_mesh = model_mesh + + ! loop over streams and initialize + do ns = 1, nstreams + sdat(ns)%pio_subsystem => sdatconfig%pio_subsystem + sdat(ns)%io_type = sdatconfig%io_type + sdat(ns)%io_format = sdatconfig%io_format + + allocate(filelist(sdatconfig%stream(ns)%nfiles)) + allocate(filevars(sdatconfig%stream(ns)%nvars,2)) + + ! fill stream info + do l = 1, sdatconfig%stream(ns)%nfiles + filelist(l) = trim(sdatconfig%stream(ns)%file(l)%name) + end do + do l = 1, sdatconfig%stream(ns)%nvars + filevars(l,1) = trim(sdatconfig%stream(ns)%varlist(l)%nameinfile) + filevars(l,2) = trim(sdatconfig%stream(ns)%varlist(l)%nameinmodel) + end do + + write(stream_name,fmt='(a,i2.2)') 'stream_', ns + call shr_strdata_init_from_inline(sdat(ns), & + my_task = mytask, & + logunit = logunit, & + compname = 'OCN', & + model_clock = sdat(ns)%model_clock, & + model_mesh = sdat(ns)%model_mesh, & + stream_name = trim(stream_name), & + stream_meshfile = trim(sdatconfig%stream(ns)%meshfile), & + stream_filenames = filelist, & + stream_yearFirst = sdatconfig%stream(ns)%yearFirst, & + stream_yearLast = sdatconfig%stream(ns)%yearLast, & + stream_yearAlign = sdatconfig%stream(ns)%yearAlign, & + stream_fldlistFile = filevars(:,1), & + stream_fldListModel = filevars(:,2), & + stream_lev_dimname = trim(sdatconfig%stream(ns)%lev_dimname), & + stream_mapalgo = trim(sdatconfig%stream(ns)%mapalgo), & + stream_offset = sdatconfig%stream(ns)%offset, & + stream_taxmode = trim(sdatconfig%stream(ns)%taxmode), & + stream_dtlimit = sdatconfig%stream(ns)%dtlimit, & + stream_tintalgo = trim(sdatconfig%stream(ns)%tInterpAlgo), & + stream_src_mask = sdatconfig%stream(ns)%src_mask_val, & + stream_dst_mask = sdatconfig%stream(ns)%dst_mask_val, & + rc = rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + deallocate(filelist) + deallocate(filevars) + end do end subroutine mom_inline_init -!=============================================================================== + !=============================================================================== + subroutine mom_inline_run(clock, ocean_public, ocean_grid, ice_ocean_boundary, rc) - !call mom_inline_run(clock, isc, iec, jsc, jec, 'lrunoff', ice_ocean_boundary%lrunoff, rc=rc) - subroutine mom_inline_run(clock, isc, iec, jsc, jec, fldname, output, rc) + use MOM_ocean_model_nuopc, only: ocean_public_type + use MOM_surface_forcing_nuopc, only: ice_ocean_boundary_type + use MOM_grid, only: ocean_grid_type + use mpp_domains_mod, only: mpp_get_compute_domain ! input/output variables - type(ESMF_Clock) , intent(in) :: clock - integer , intent(in) :: isc !< The start i-index of cell centers within - !! the computational domain - integer , intent(in) :: iec !< The end i-index of cell centers within the - !! computational domain - integer , intent(in) :: jsc !< The start j-index of cell centers within - !! the computational domain - integer , intent(in) :: jec !< The end j-index of cell centers within - !! the computational domain - character(len=*) , intent(in) :: fldname !! the stream name - real (ESMF_KIND_R8) , intent(inout) :: output(isc:iec,jsc:jec) !< Output 2D array - - integer , intent(out) :: rc + type(ESMF_Clock) , intent(in) :: clock !< Model clock + type(ocean_public_type) , intent(in) :: ocean_public !< Ocean surface state + type(ocean_grid_type) , intent(in) :: ocean_grid !< Ocean model grid + type(ice_ocean_boundary_type) , intent(inout) :: ice_ocean_boundary !< Ocean boundary forcing + integer , intent(out) :: rc ! local variables type(ESMF_Time) :: date - integer :: i,j,n + integer :: nstreams, nflds + integer :: ns,nf,n,i,j + integer :: isc, iec, jsc, jec 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) + character(len=ESMF_MAXSTR) :: fldname real(ESMF_KIND_R8), pointer :: dataPtr1d(:) + character(len=*), parameter :: subname='(mom_inline_run)' !----------------------------------------------------------------------- rc = ESMF_SUCCESS - ! Advance sdat stream + ! The following are global indices without halos + call mpp_get_compute_domain(ocean_public%domain, isc, iec, jsc, jec) + + ! Current model date call ESMF_ClockGet( clock, currTime=date, rc=rc ) if (chkerr(rc,__LINE__,u_FILE_u)) return call ESMF_TimeGet(date, yy=year, mm=mon, dd=day, s=sec, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return mcdate = year*10000 + mon*100 + day - ! TODO: need to allow for multiple variables/stream - if (trim(fldname) == 'lrunoff') then - call shr_strdata_advance(sdat_lrunoff, ymd=mcdate, tod=sec, logunit=logunit, istr='lrunoff stream',rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - - ! Get pointer for stream data that is time and spatially interpolated to model time and grid - call dshr_fldbun_getFldPtr(sdat_lrunoff%pstrm(1)%fldbun_model, trim(fldname), dataPtr1d, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - - call dshr_fldbun_Field_diagnose(sdat_lrunoff%pstrm(1)%fldbun_model, trim(fldname), rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - end if - if (trim(fldname) == 'frunoff') then - call shr_strdata_advance(sdat_frunoff, ymd=mcdate, tod=sec, logunit=logunit, istr='frunoff stream', rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - - ! Get pointer for stream data that is time and spatially interpolated to model time and grid - call dshr_fldbun_getFldPtr(sdat_frunoff%pstrm(1)%fldbun_model, trim(fldname), dataPtr1d, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - - call dshr_fldbun_Field_diagnose(sdat_frunoff%pstrm(1)%fldbun_model, trim(fldname), rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - end if - - n = 0 - do j = jsc,jec - do i = isc,iec - n = n + 1 - output(i,j) = dataPtr1d(n) - end do + nstreams = size(sdat) + ! Advance the streams + do ns = 1,nstreams + write(stream_name,fmt='(a,i2.2)') 'stream_', ns + call shr_strdata_advance(sdat(ns), ymd=mcdate, tod=sec, logunit=logunit, istr=trim(stream_name),rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + nflds = size(sdat(ns)%pstrm(1)%fldlist_model) + do nf = 1,nflds + fldname = trim(sdat(ns)%pstrm(1)%fldlist_model(nf)) + + if (fldname == 'lrunoff') then + ! Get pointer for stream data that is time and spatially interpolated to model time and grid + call dshr_fldbun_getFldPtr(sdat(ns)%pstrm(1)%fldbun_model, trim(fldname), dataPtr1d, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + n = 0 + do j = jsc,jec + do i = isc,iec + n = n + 1 + ice_ocean_boundary%lrunoff(i,j) = dataPtr1d(n) + end do + end do + end if + + end do end do end subroutine mom_inline_run - !=============================================================================== - - subroutine initialize_single_stream(sdatm, sdats, sid, sdatname, compname, mytask, logunit, rc) - - type(shr_strdata_type), intent(inout) :: sdatm - type(shr_strdata_type), intent(inout) :: sdats - integer, intent(in) :: sid - character(len=*), intent(in) :: sdatname - character(len=*), intent(in) :: compname - integer, intent(in) :: mytask - integer, intent(in) :: logunit - integer , intent(out) :: rc - - ! local - integer :: nfiles, nvars, nf, nv - character(len=ESMF_MAXSTR), allocatable :: filelist(:) - character(len=ESMF_MAXSTR), allocatable :: filevars(:,:) - - !----------------------------------------------------------------------- - - rc = ESMF_SUCCESS - - nfiles = sdatm%stream(sid)%nfiles - nvars = sdatm%stream(sid)%nvars - - allocate(filelist(1:nfiles)) - allocate(filevars(1:nvars,2)) - - do nf = 1,nfiles - filelist(nf) = trim(sdatm%stream(sid)%file(nf)%name) - end do - do nv = 1,nvars - filevars(nv,1) = trim(sdatm%stream(sid)%varlist(nv)%nameinfile) - filevars(nv,2) = trim(sdatm%stream(sid)%varlist(nv)%nameinmodel) - end do - - ! Write out info - if (mytask == 0) then - write(logunit,'(a)' ) ' ' - write(logunit,'(a,i8)') 'stream settings:',sid - do nf = 1,nfiles - write(logunit,'(a)' ) ' stream file list = '//trim(filelist(nf)) - end do - do nv = 1,nvars - write(logunit,'(a)' ) ' stream variable in file= '//trim(filevars(nv,1))//' ; variable in model= '//trim(filevars(nv,2)) - write(logunit,'(a)' ) ' ' - end do - endif - - ! Set PIO related variables - sdats%pio_subsystem => sdatm%pio_subsystem - sdats%io_type = sdatm%io_type - sdats%io_format = sdatm%io_format - - call shr_strdata_init_from_inline(sdats, & - my_task = mytask, & - logunit = logunit, & - compname = trim(compname), & - model_clock = sdatm%model_clock, & - model_mesh = sdatm%model_mesh, & - stream_name = trim(sdatname), & - stream_meshfile = trim(sdatm%stream(sid)%meshFile), & - stream_filenames = filelist, & - stream_yearFirst = sdatm%stream(sid)%yearFirst, & - stream_yearLast = sdatm%stream(sid)%yearLast, & - stream_yearAlign = sdatm%stream(sid)%yearAlign, & - stream_fldlistFile = filevars(:,1), & - stream_fldListModel = filevars(:,2), & - stream_lev_dimname = trim(sdatm%stream(sid)%lev_dimname), & - stream_mapalgo = trim(sdatm%stream(sid)%mapAlgo), & - stream_offset = sdatm%stream(sid)%offset, & - stream_taxmode = trim(sdatm%stream(sid)%taxmode), & - stream_dtlimit = sdatm%stream(sid)%dtlimit, & - stream_tintalgo = trim(sdatm%stream(sid)%tInterpAlgo), & - stream_src_mask = sdatm%stream(sid)%src_mask_val, & - stream_dst_mask = sdatm%stream(sid)%dst_mask_val, & - rc = rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - - deallocate(filelist) - deallocate(filevars) - - end subroutine initialize_single_stream - end module mom_inline_mod From 251c62891c22e187dc72d7942b185e5fe3890a11 Mon Sep 17 00:00:00 2001 From: "denise.worthen" Date: Fri, 15 Aug 2025 15:33:51 -0500 Subject: [PATCH 9/9] modify control and config of the inline * add a logical to enable/disable the feature --- config_src/drivers/nuopc_cap/mom_cap.F90 | 25 +++++---- .../drivers/nuopc_cap/mom_inline_mod.F90 | 51 +++++++++++++------ 2 files changed, 49 insertions(+), 27 deletions(-) diff --git a/config_src/drivers/nuopc_cap/mom_cap.F90 b/config_src/drivers/nuopc_cap/mom_cap.F90 index 947c22fe94..a6bca3837c 100644 --- a/config_src/drivers/nuopc_cap/mom_cap.F90 +++ b/config_src/drivers/nuopc_cap/mom_cap.F90 @@ -91,10 +91,10 @@ module MOM_cap_mod use NUOPC_Model, only: model_label_Finalize => label_Finalize use NUOPC_Model, only: SetVM +use mom_inline_mod, only : mom_inline_init, mom_inline_run #ifndef CESMCOUPLED use shr_is_restart_fh_mod, only : init_is_restart_fh, is_restart_fh, is_restart_fh_type #endif - use mom_inline_mod, only : mom_inline_init, mom_inline_run implicit none; private @@ -143,7 +143,7 @@ module MOM_cap_mod logical :: use_mommesh = .true. logical :: set_missing_stks_to_zero = .false. logical :: restart_eor = .false. -character(len=128) :: streamconfig = '' +logical :: use_cdeps_inline = .false. character(len=128) :: scalar_field_name = '' integer :: scalar_field_count = 0 integer :: scalar_field_idx_grid_nx = 0 @@ -397,11 +397,13 @@ subroutine InitializeP0(gcomp, importState, exportState, clock, rc) geomtype = ESMF_GEOMTYPE_GRID endif - call NUOPC_CompAttributeGet(gcomp, name="streamconfig", value=value, isPresent=isPresent, isSet=isSet, rc=rc) + use_cdeps_inline = .false. + call NUOPC_CompAttributeGet(gcomp, name="use_cdeps_inline", value=value, & + isPresent=isPresent, isSet=isSet, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - if (isPresent .and. isSet) then - streamconfig = trim(value) - endif + if (isPresent .and. isSet) use_cdeps_inline=(trim(value)=="true") + write(logmsg,*) use_cdeps_inline + call ESMF_LogWrite('MOM_cap:use_cdeps_inline = '//trim(logmsg), ESMF_LOGMSG_INFO) ! Read end of run restart config option call NUOPC_CompAttributeGet(gcomp, name="write_restart_at_endofrun", value=value, & @@ -1590,8 +1592,8 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) !--------------------------------- call mom_set_geomtype(geomtype) - if (len_trim(streamconfig) > 0) then - call mom_inline_init(gcomp, clock, eMesh, localPet, streamconfig, rc=rc) + if (use_cdeps_inline) then + call mom_inline_init(gcomp, clock, eMesh, localPet, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return end if @@ -1870,9 +1872,10 @@ subroutine ModelAdvance(gcomp, rc) set_missing_stks_to_zero, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - !...some logical... - call mom_inline_run(clock, ocean_public, ocean_grid, ice_ocean_boundary, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (use_cdeps_inline) then + call mom_inline_run(clock, ocean_public, ocean_grid, ice_ocean_boundary, dbug, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end if !--------------- ! Update MOM6 diff --git a/config_src/drivers/nuopc_cap/mom_inline_mod.F90 b/config_src/drivers/nuopc_cap/mom_inline_mod.F90 index 09eaa40fa7..f279614e7b 100644 --- a/config_src/drivers/nuopc_cap/mom_inline_mod.F90 +++ b/config_src/drivers/nuopc_cap/mom_inline_mod.F90 @@ -1,10 +1,11 @@ module mom_inline_mod + use NUOPC , only: NUOPC_CompAttributeGet use ESMF , only: ESMF_GridComp, ESMF_Mesh use ESMF , only: ESMF_Clock, ESMF_Time, ESMF_TimeGet, ESMF_ClockGet use ESMF , only: ESMF_KIND_R8, ESMF_SUCCESS, ESMF_LogFoundError use ESMF , only: ESMF_LOGERR_PASSTHRU, ESMF_LOGMSG_INFO, ESMF_LOGWRITE - use ESMF , only: ESMF_MAXSTR + use ESMF , only: ESMF_END_ABORT, ESMF_Finalize, ESMF_MAXSTR use dshr_mod , only: dshr_pio_init use dshr_strdata_mod , only: shr_strdata_type, shr_strdata_print use dshr_strdata_mod , only: shr_strdata_init_from_inline @@ -27,22 +28,24 @@ module mom_inline_mod character(len=*), parameter :: u_FILE_u = __FILE__ contains !=============================================================================== - subroutine mom_inline_init(gcomp, model_clock, model_mesh, mytask, configfile, rc) + subroutine mom_inline_init(gcomp, model_clock, model_mesh, mytask, rc) ! input/output parameters - type(ESMF_GridComp) , intent(in) :: gcomp - type(ESMF_Clock) , intent(in) :: model_clock - type(ESMF_Mesh) , intent(in) :: model_mesh - integer , intent(in) :: mytask - character(len=*) , intent(in) :: configfile - integer , intent(out) :: rc + type(ESMF_GridComp) , intent(in) :: gcomp !< ESMF_GridComp object + type(ESMF_Clock) , intent(in) :: model_clock !< ESMF_Clock object + type(ESMF_Mesh) , intent(in) :: model_mesh !< ESMF mesh + integer , intent(in) :: mytask !< the current task + integer , intent(out) :: rc !< Return code ! stream data from config (xml or esmf), one or more streams type(shr_strdata_type) :: sdatconfig + ! local variables + logical :: isPresent, isSet integer :: ns, l integer :: nstreams, nvars + character(len=ESMF_MAXSTR) :: value, streamfilename character(len=ESMF_MAXSTR), allocatable :: filelist(:) character(len=ESMF_MAXSTR), allocatable :: filevars(:,:) @@ -51,24 +54,35 @@ subroutine mom_inline_init(gcomp, model_clock, model_mesh, mytask, configfile, r rc = ESMF_SUCCESS + call NUOPC_CompAttributeGet(gcomp, name="streamfilename", value=value, isPresent=isPresent, isSet=isSet, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (isPresent .and. isSet) then + streamfilename = value + else + call ESMF_LogWrite(trim(subname)//': streamfilename must be provided', ESMF_LOGMSG_INFO) + call ESMF_Finalize(endflag=ESMF_END_ABORT) + return + end if + +#ifndef CESMCOUPLED if (mytask == 0) then open (newunit=logunit, file='log.mom6.cdeps') else logunit = 6 end if -#ifndef CESMCOUPLED ! CMEPS Init PIO call dshr_pio_init(gcomp, sdatconfig, logunit, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return ! read the available stream definitions, each data stream is one or more data_files ! which have the same spatial and temporal coordinates - call shr_stream_init_from_esmfconfig(configfile, sdatconfig%stream, logunit, & + call shr_stream_init_from_esmfconfig(trim(streamfilename), sdatconfig%stream, logunit, & sdatconfig%pio_subsystem, sdatconfig%io_type, sdatconfig%io_format, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return #else - !TODO: cesm configuration via xml etc + !TODO: CESM logunit, configuration via xml etc + !call shr_stream_init_from_xml(trim(streamfilename) .... #endif nstreams = size(sdatconfig%stream) @@ -129,7 +143,7 @@ subroutine mom_inline_init(gcomp, model_clock, model_mesh, mytask, configfile, r end subroutine mom_inline_init !=============================================================================== - subroutine mom_inline_run(clock, ocean_public, ocean_grid, ice_ocean_boundary, rc) + subroutine mom_inline_run(clock, ocean_public, ocean_grid, ice_ocean_boundary, dbug, rc) use MOM_ocean_model_nuopc, only: ocean_public_type use MOM_surface_forcing_nuopc, only: ice_ocean_boundary_type @@ -137,11 +151,12 @@ subroutine mom_inline_run(clock, ocean_public, ocean_grid, ice_ocean_boundary, r use mpp_domains_mod, only: mpp_get_compute_domain ! input/output variables - type(ESMF_Clock) , intent(in) :: clock !< Model clock + type(ESMF_Clock) , intent(in) :: clock !< ESMF_Clock object type(ocean_public_type) , intent(in) :: ocean_public !< Ocean surface state type(ocean_grid_type) , intent(in) :: ocean_grid !< Ocean model grid type(ice_ocean_boundary_type) , intent(inout) :: ice_ocean_boundary !< Ocean boundary forcing - integer , intent(out) :: rc + integer , intent(in) :: dbug !< Integer debug flag + integer , intent(out) :: rc !< Return code ! local variables type(ESMF_Time) :: date @@ -195,8 +210,12 @@ subroutine mom_inline_run(clock, ocean_public, ocean_grid, ice_ocean_boundary, r end do end if - end do - end do + if (dbug > 1) then + call dshr_fldbun_Field_diagnose(sdat(ns)%pstrm(1)%fldbun_model, trim(fldname), 'inline_run ', rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + end if + end do !nf + end do !ns end subroutine mom_inline_run end module mom_inline_mod