Skip to content

Commit

Permalink
Merge pull request #94 from mvertens/feature/cism2mosart
Browse files Browse the repository at this point in the history
cism runoff will be now routed to ocn via mosart
  • Loading branch information
slevis-lmwg authored Jun 21, 2024
2 parents 5acf6b2 + 19966c3 commit e2ffe00
Show file tree
Hide file tree
Showing 14 changed files with 451 additions and 268 deletions.
2 changes: 1 addition & 1 deletion cime_config/namelist_definition_mosart.xml
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@
<value>-24</value>
</values>
<desc>
Frequency to perform budget check. Similar to nhtfrq,
Frequency to perform budget check. Similar to nhtfrq,
positive means in time steps, 0=monthly, negative means hours
(i.e. 24 means every 24 time-steps and -24 means every day
</desc>
Expand Down
9 changes: 9 additions & 0 deletions cime_config/testdefs/testlist_mosart.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@
<option name="comment" >Restart test without DEBUG</option>
</options>
</test>
<test name="ERS_Ld5" grid="f10_f10_mg37" compset="I1850Clm50BgcCropG" testmods="mosart/default">
<machines>
<machine name="derecho" compiler="intel" category="mosart"></machine>
</machines>
<options>
<option name="wallclock">00:20:00</option>
<option name="comment" >Restart test without DEBUG with CISM</option>
</options>
</test>
<test name="ERS_Ld5" grid="f10_f10_mg37" compset="I2000Clm50BgcCru" testmods="mosart/iceOff">
<machines>
<machine name="derecho" compiler="intel" category="mosart"></machine>
Expand Down
23 changes: 23 additions & 0 deletions docs/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,26 @@
===============================================================
Tag name: mosart1_1_02
Originator(s): mvertens
Date: Jun 21, 2024
One-line Summary: cism runoff will be now routed to ocn via mosart

Enables CISM runoff to be routed to the ocean via mosart.

All runoff from CISM will be routed directly to the outlet points
New fields will be advertised in the mosart cap
call fldlist_add(fldsFrRof_num, fldsFrRof, 'Forr_rofl_glc')
call fldlist_add(fldsFrRof_num, fldsFrRof, 'Forr_rofi_glc')

Issues addressed:
Fixes #92
Fixes #102

Testing: standard testing
izumi -- OK
cheyenne -- OK

See https://github.com/ESCOMP/MOSART/pull/94 for more details

===============================================================
Tag name: mosart1_1_01
Originator(s): mvertens
Expand Down
8 changes: 4 additions & 4 deletions src/cpl/nuopc/rof_comp_nuopc.F90
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ module rof_comp_nuopc
model_label_DataInitialize => label_DataInitialize, &
model_label_SetRunClock => label_SetRunClock, &
model_label_Finalize => label_Finalize, &
SetVM, NUOPC_ModelGet
NUOPC_ModelGet
use shr_kind_mod , only : R8=>SHR_KIND_R8, CL=>SHR_KIND_CL, CS=>SHR_KIND_CS
use shr_sys_mod , only : shr_sys_abort
use shr_log_mod , only : shr_log_getlogunit, shr_log_setlogunit
use shr_cal_mod , only : shr_cal_noleap, shr_cal_gregorian, shr_cal_ymd2date
use mosart_vars , only : nsrStartup, nsrContinue, nsrBranch, &
inst_index, inst_suffix, inst_name, &
mainproc, mpicom_rof, iam, npes, iulog, &
mainproc, mpicom_rof, iam, npes, iulog, vm, &
nsrest, caseid, ctitle, version, hostname, username
use mosart_data , only : ctl
use mosart_driver , only : mosart_read_namelist, mosart_init1, mosart_init2, mosart_run
Expand All @@ -49,7 +49,6 @@ module rof_comp_nuopc

! Module routines
public :: SetServices
public :: SetVM
private :: InitializeP0
private :: InitializeAdvertise
private :: InitializeRealize
Expand Down Expand Up @@ -159,7 +158,6 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc)
type(ESMF_Time) :: refTime ! Ref time
type(ESMF_TimeInterval) :: timeStep ! Model timestep
type(ESMF_CalKind_Flag) :: esmf_caltype ! esmf calendar type
type(ESMF_VM) :: vm ! esmf virtual machine
integer :: ref_ymd ! reference date (YYYYMMDD)
integer :: ref_tod ! reference time of day (sec)
integer :: yy,mm,dd ! Temporaries for time query
Expand Down Expand Up @@ -187,6 +185,8 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc)
! generate local mpi comm
!----------------------------------------------------------------------------

! Note vm is in mosart_vars.F90 and can be shared among components

call ESMF_GridCompGet(gcomp, vm=vm, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return

Expand Down
104 changes: 74 additions & 30 deletions src/cpl/nuopc/rof_import_export.F90
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ module rof_import_export
private :: state_getimport
private :: state_setexport
private :: check_for_nans
private :: fldchk

type fld_list_type
character(len=128) :: stdname
Expand Down Expand Up @@ -82,9 +83,12 @@ subroutine advertise_fields(gcomp, flds_scalar_name, rc)
isPresent=isPresent, isSet=isSet, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
if (isPresent .and. isSet) read(cvalue,*) flds_r2l_stream_channel_depths

call fldlist_add(fldsFrRof_num, fldsFrRof, trim(flds_scalar_name))
call fldlist_add(fldsFrRof_num, fldsFrRof, 'Forr_rofl')
call fldlist_add(fldsFrRof_num, fldsFrRof, 'Forr_rofi')
call fldlist_add(fldsFrRof_num, fldsFrRof, 'Forr_rofl_glc')
call fldlist_add(fldsFrRof_num, fldsFrRof, 'Forr_rofi_glc')
call fldlist_add(fldsFrRof_num, fldsFrRof, 'Flrr_flood')
call fldlist_add(fldsFrRof_num, fldsFrRof, 'Flrr_volr')
call fldlist_add(fldsFrRof_num, fldsFrRof, 'Flrr_volrmch')
Expand All @@ -109,6 +113,8 @@ subroutine advertise_fields(gcomp, flds_scalar_name, rc)
call fldlist_add(fldsToRof_num, fldsToRof, 'Flrl_rofsub')
call fldlist_add(fldsToRof_num, fldsToRof, 'Flrl_rofi')
call fldlist_add(fldsToRof_num, fldsToRof, 'Flrl_irrig')
call fldlist_add(fldsToRof_num, fldsToRof, 'Fgrg_rofl') ! liq runoff from glc
call fldlist_add(fldsToRof_num, fldsToRof, 'Fgrg_rofi') ! ice runoff from glc

do n = 1,fldsToRof_num
call NUOPC_Advertise(importState, standardName=fldsToRof(n)%stdname, &
Expand Down Expand Up @@ -222,6 +228,15 @@ subroutine realize_fields(gcomp, Emesh, flds_scalar_name, flds_scalar_num, rc)
min_med2mod_areacor_glob, max_med2mod_areacor_glob, 'MOSART'
end if

if (fldchk(importState, 'Fgrg_rofl') .and. fldchk(importState, 'Fgrg_rofl')) then
ctl%rof_from_glc = .true.
else
ctl%rof_from_glc = .false.
end if
if (mainproc) then
write(iulog,'(A,l1)') trim(subname) //' rof from glc is ',ctl%rof_from_glc
end if

end subroutine realize_fields

!===============================================================================
Expand All @@ -239,7 +254,7 @@ subroutine import_fields( gcomp, begr, endr, rc )
! Local variables
type(ESMF_State) :: importState
integer :: n,nt
integer :: nliq, nfrz
integer :: nliq, nice
character(len=*), parameter :: subname='(rof_import_export:import_fields)'
!---------------------------------------------------------------------------

Expand All @@ -250,17 +265,8 @@ subroutine import_fields( gcomp, begr, endr, rc )
call NUOPC_ModelGet(gcomp, importState=importState, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return

! Set tracers
nliq = 0
nfrz = 0
do nt = 1,ctl%ntracers
if (trim(ctl%tracer_names(nt)) == 'LIQ') nliq = nt
if (trim(ctl%tracer_names(nt)) == 'ICE') nfrz = nt
enddo
if (nliq == 0 .or. nfrz == 0) then
write(iulog,*) trim(subname),': ERROR in tracers LIQ ICE ',nliq,nfrz,ctl%tracer_names(:)
call shr_sys_abort()
endif
nliq = ctl%nt_liq
nice = ctl%nt_ice

! determine output array and scale by unit convertsion
! NOTE: the call to state_getimport will convert from input kg/m2s to m3/s
Expand All @@ -277,16 +283,28 @@ subroutine import_fields( gcomp, begr, endr, rc )
do_area_correction=.true., rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return

call state_getimport(importState, 'Flrl_rofi', begr, endr, ctl%area, output=ctl%qsur(:,nfrz), &
call state_getimport(importState, 'Flrl_rofi', begr, endr, ctl%area, output=ctl%qsur(:,nice), &
do_area_correction=.true., rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return

call state_getimport(importState, 'Flrl_irrig', begr, endr, ctl%area, output=ctl%qirrig(:), &
do_area_correction=.true., rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return

ctl%qsub(begr:endr, nfrz) = 0.0_r8
ctl%qgwl(begr:endr, nfrz) = 0.0_r8
ctl%qsub(begr:endr, nice) = 0.0_r8
ctl%qgwl(begr:endr, nice) = 0.0_r8

if (ctl%rof_from_glc) then
call state_getimport(importState, 'Fgrg_rofl', begr, endr, ctl%area, output=ctl%qglc_liq(:), &
do_area_correction=.true., rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
call state_getimport(importState, 'Fgrg_rofi', begr, endr, ctl%area, output=ctl%qglc_ice(:), &
do_area_correction=.true., rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
else
ctl%qglc_liq(:) = 0._r8
ctl%qglc_ice(:) = 0._r8
end if

end subroutine import_fields

Expand All @@ -305,9 +323,11 @@ subroutine export_fields (gcomp, begr, endr, rc)
! Local variables
type(ESMF_State) :: exportState
integer :: n,nt
integer :: nliq, nfrz
integer :: nliq, nice
real(r8) :: rofl(begr:endr)
real(r8) :: rofi(begr:endr)
real(r8) :: rofl_glc(begr:endr)
real(r8) :: rofi_glc(begr:endr)
real(r8) :: flood(begr:endr)
real(r8) :: volr(begr:endr)
real(r8) :: volrmch(begr:endr)
Expand All @@ -325,16 +345,8 @@ subroutine export_fields (gcomp, begr, endr, rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return

! Set tracers
nliq = 0
nfrz = 0
do nt = 1,ctl%ntracers
if (trim(ctl%tracer_names(nt)) == 'LIQ') nliq = nt
if (trim(ctl%tracer_names(nt)) == 'ICE') nfrz = nt
enddo
if (nliq == 0 .or. nfrz == 0) then
write(iulog,*) trim(subname),': ERROR in tracers LIQ ICE ',nliq,nfrz,ctl%tracer_names(:)
call shr_sys_abort()
endif
nliq = ctl%nt_liq
nice = ctl%nt_ice

if (first_time) then
if (mainproc) then
Expand All @@ -351,24 +363,29 @@ subroutine export_fields (gcomp, begr, endr, rc)
! separate liquid and ice runoff
do n = begr,endr
rofl(n) = ctl%direct(n,nliq) / (ctl%area(n)*0.001_r8)
rofi(n) = ctl%direct(n,nfrz) / (ctl%area(n)*0.001_r8)
rofi(n) = ctl%direct(n,nice) / (ctl%area(n)*0.001_r8)
if (ctl%mask(n) >= 2) then
! liquid and ice runoff are treated separately - this is what goes to the ocean
rofl(n) = rofl(n) + ctl%runoff(n,nliq) / (ctl%area(n)*0.001_r8)
rofi(n) = rofi(n) + ctl%runoff(n,nfrz) / (ctl%area(n)*0.001_r8)
rofi(n) = rofi(n) + ctl%runoff(n,nice) / (ctl%area(n)*0.001_r8)
end if
end do
else
! liquid and ice runoff added to liquid runoff, ice runoff is zero
do n = begr,endr
rofl(n) = (ctl%direct(n,nfrz) + ctl%direct(n,nliq)) / (ctl%area(n)*0.001_r8)
rofl(n) = (ctl%direct(n,nice) + ctl%direct(n,nliq)) / (ctl%area(n)*0.001_r8)
if (ctl%mask(n) >= 2) then
rofl(n) = rofl(n) + (ctl%runoff(n,nfrz) + ctl%runoff(n,nliq)) / (ctl%area(n)*0.001_r8)
rofl(n) = rofl(n) + (ctl%runoff(n,nice) + ctl%runoff(n,nliq)) / (ctl%area(n)*0.001_r8)
endif
rofi(n) = 0._r8
end do
end if

do n = begr,endr
rofl_glc(n) = ctl%direct_glc(n,nliq) / (ctl%area(n)*0.001_r8)
rofi_glc(n) = ctl%direct_glc(n,nice) / (ctl%area(n)*0.001_r8)
end do

! Flooding back to land, sign convention is positive in land->rof direction
! so if water is sent from rof to land, the flux must be negative.
! scs: is there a reason for the wr+wt rather than volr (wr+wt+wh)?
Expand All @@ -391,6 +408,12 @@ subroutine export_fields (gcomp, begr, endr, rc)
call state_setexport(exportState, 'Forr_rofi', begr, endr, input=rofi, do_area_correction=.true., rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return

call state_setexport(exportState, 'Forr_rofl_glc', begr, endr, input=rofl_glc, do_area_correction=.true., rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return

call state_setexport(exportState, 'Forr_rofi_glc', begr, endr, input=rofi_glc, do_area_correction=.true., rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return

call state_setexport(exportState, 'Flrr_flood', begr, endr, input=flood, do_area_correction=.true., rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return

Expand Down Expand Up @@ -654,4 +677,25 @@ subroutine check_for_nans(array, fname, begg)
end if
end subroutine check_for_nans

!===============================================================================
logical function fldchk(state, fldname)
! ----------------------------------------------
! Determine if field with fldname is in the input state
! ----------------------------------------------

! input/output variables
type(ESMF_State), intent(in) :: state
character(len=*), intent(in) :: fldname

! local variables
type(ESMF_StateItem_Flag) :: itemFlag
! ----------------------------------------------
call ESMF_StateGet(state, trim(fldname), itemFlag)
if (itemflag /= ESMF_STATEITEM_NOTFOUND) then
fldchk = .true.
else
fldchk = .false.
endif
end function fldchk

end module rof_import_export
Loading

0 comments on commit e2ffe00

Please sign in to comment.