Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cism runoff will be now routed to ocn via mosart #94

Merged
merged 20 commits into from
Jun 21, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion cime_config/namelist_definition_mosart.xml
Original file line number Diff line number Diff line change
Expand Up @@ -288,10 +288,24 @@
<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>
</entry>

<entry id="separate_glc2ocn_fluxes">
<type>logical</type>
<category>mosart</category>
<group>mosart_inparm</group>
<values>
<value>.true.</value>
</values>
<desc>
Default: .true.
If .true., glc2ocn fluxes that are passed through mosart will be sent
as a separate fields to the mediator.
ekluzek marked this conversation as resolved.
Show resolved Hide resolved
</desc>
</entry>

</entry_id>
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
117 changes: 86 additions & 31 deletions src/cpl/nuopc/rof_import_export.F90
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ module rof_import_export
use NUOPC_Model , only : NUOPC_ModelGet
use shr_kind_mod , only : r8 => shr_kind_r8
use shr_sys_mod , only : shr_sys_abort
use mosart_vars , only : iulog, mainproc, mpicom_rof, ice_runoff
use mosart_vars , only : iulog, mainproc, mpicom_rof, ice_runoff, separate_glc2ocn_fluxes
use mosart_data , only : ctl, TRunoff, TUnit
use mosart_timemanager , only : get_nstep
use nuopc_shr_methods , only : chkerr
Expand All @@ -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,14 @@ 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')
if (separate_glc2ocn_fluxes) then
call fldlist_add(fldsFrRof_num, fldsFrRof, 'Forr_rofl_glc')
ekluzek marked this conversation as resolved.
Show resolved Hide resolved
call fldlist_add(fldsFrRof_num, fldsFrRof, 'Forr_rofi_glc')
end if
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 +115,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 +230,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
ekluzek marked this conversation as resolved.
Show resolved Hide resolved
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 +256,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 +267,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
mvertens marked this conversation as resolved.
Show resolved Hide resolved
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 +285,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 +325,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 +347,8 @@ subroutine export_fields (gcomp, begr, endr, rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return

! Set tracers
nliq = 0
ekluzek marked this conversation as resolved.
Show resolved Hide resolved
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 +365,36 @@ 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

if (separate_glc2ocn_fluxes) then
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
else
do n = begr,endr
rofl(n) = rofl(n) + ctl%direct_glc(n,nliq) / (ctl%area(n)*0.001_r8)
rofi(n) = rofi(n) + ctl%direct_glc(n,nice) / (ctl%area(n)*0.001_r8)
end do
end if

! 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 +417,14 @@ 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

if (separate_glc2ocn_fluxes) then
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
end if

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 +688,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