Skip to content

Commit

Permalink
Add capability to send both prescribed SST and multi-level ocean SST/…
Browse files Browse the repository at this point in the history
…SALN to mediator (#289)

* new data ocn mode to send both multi-level ocn and sst to mediator
* moved cheyenne to derecho in testlist
* added new mode code
Co-authored-by: Mariana Vertenstein <[email protected]>
  • Loading branch information
mvertens authored Jul 12, 2024
1 parent 453a9d1 commit b7a6088
Show file tree
Hide file tree
Showing 6 changed files with 290 additions and 6 deletions.
1 change: 1 addition & 0 deletions docn/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ set(SRCFILES ocn_comp_nuopc.F90
docn_datamode_iaf_mod.F90
docn_datamode_cplhist_mod.F90
docn_datamode_multilev_mod.F90
docn_datamode_multilev_dom_mod.F90
docn_import_data_mod.F90)

foreach(FILE ${SRCFILES})
Expand Down
6 changes: 4 additions & 2 deletions docn/cime_config/config_component.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
This file may have ocn desc entries.
-->
<description modifier_mode="1">
<desc ocn="DOCN[%DOM][%SOM][%SOMAQP][%IAF][%SST_AQUAP][%AQP1][%AQP2][%AQP3][%AQP4][%AQP5][%AQP6][%AQP7][%AQP8][%AQP9][%AQP10][%AQPFILE][%AQPCONST][%CPLHIST][%MULTILEV]">DOCN </desc>
<desc ocn="DOCN[%DOM][%SOM][%SOMAQP][%IAF][%SST_AQUAP][%AQP1][%AQP2][%AQP3][%AQP4][%AQP5][%AQP6][%AQP7][%AQP8][%AQP9][%AQP10][%AQPFILE][%AQPCONST][%CPLHIST][%MULTILEV][%MULTILEV-DOM]">DOCN </desc>
<desc option="DOM"> prescribed ocean mode</desc>
<desc option="SOM"> slab ocean mode</desc>
<desc option="SOMAQP"> aquaplanet slab ocean mode</desc>
Expand All @@ -33,6 +33,7 @@
<desc option="AQPCONST"> globally constant SST for idealized experiments, such as RCE </desc>
<desc option="CPLHIST"> mediator history output for ocean fields imported to mediator </desc>
<desc option="MULTILEV"> input stream files have multi level data</desc>
<desc option="MULTILEV-DOM"> input stream files have multi level data and prescribed ocean SST</desc>
</description>

<entry id="COMP_OCN">
Expand All @@ -46,7 +47,7 @@

<entry id="DOCN_MODE">
<type>char</type>
<valid_values>prescribed,sst_aquap1,sst_aquap2,sst_aquap3,sst_aquap4,sst_aquap5,sst_aquap6,sst_aquap7,sst_aquap8,sst_aquap9,sst_aquap10,sst_aquapfile,som,som_aquap,sst_aquap_constant,interannual,cplhist,multilev</valid_values>
<valid_values>prescribed,sst_aquap1,sst_aquap2,sst_aquap3,sst_aquap4,sst_aquap5,sst_aquap6,sst_aquap7,sst_aquap8,sst_aquap9,sst_aquap10,sst_aquapfile,som,som_aquap,sst_aquap_constant,interannual,cplhist,multilev,multilev_dom</valid_values>
<default_value>prescribed</default_value>
<values match="last">
<value compset="_DOCN%DOM_" >prescribed</value>
Expand All @@ -67,6 +68,7 @@
<value compset="_DOCN%AQPCONST_">sst_aquap_constant</value>
<value compset="_DOCN%CPLHIST">cplhist</value>
<value compset="_DOCN%MULTILEV">multilev</value>
<value compset="_DOCN%MULTILEV-DOM">multilev_dom</value>
</values>
<group>run_component_docn</group>
<file>env_run.xml</file>
Expand Down
4 changes: 3 additions & 1 deletion docn/cime_config/namelist_definition_docn.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
<value docn_mode="sst_aquap8">''</value>
<value docn_mode="sst_aquap9">''</value>
<value docn_mode="sst_aquap10">''</value>
<value docn_mode="multilev_dom">sst_salinity_depth_blom,prescribed</value>
<value docn_mode="multilev">sst_salinity_depth_blom</value>
</values>
</entry>
Expand All @@ -40,7 +41,7 @@
<type>char</type>
<category>docn</category>
<group>docn_nml</group>
<valid_values>sstdata,sst_aquap1,sst_aquap2,sst_aquap3,sst_aquap4,sst_aquap5,sst_aquap6,sst_aquap7,sst_aquap8,sst_aquap9,sst_aquap10,sst_aquapfile,sst_aquap_constant,som,som_aquap,iaf,cplhist,multilev</valid_values>
<valid_values>sstdata,sst_aquap1,sst_aquap2,sst_aquap3,sst_aquap4,sst_aquap5,sst_aquap6,sst_aquap7,sst_aquap8,sst_aquap9,sst_aquap10,sst_aquapfile,sst_aquap_constant,som,som_aquap,iaf,cplhist,multilev,multilev_dom</valid_values>
<desc>
General method that operates on the data for a given docn_mode.
==> dataMode = "sstdata"
Expand Down Expand Up @@ -108,6 +109,7 @@
<value docn_mode="sst_aquapfile$">sst_aquap_file</value>
<value docn_mode="sst_aquap_constant$">sst_aquap_constant</value>
<value docn_mode="cplhist">cplhist</value>
<value docn_mode="multilev_dom">multilev_dom</value>
<value docn_mode="multilev">multilev</value>
</values>
</entry>
Expand Down
264 changes: 264 additions & 0 deletions docn/docn_datamode_multilev_dom_mod.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
module docn_datamode_multilev_dom_mod

use ESMF , only : ESMF_State, ESMF_LOGMSG_INFO, ESMF_LogWrite, ESMF_SUCCESS
use NUOPC , only : NUOPC_Advertise
use shr_kind_mod , only : r8=>shr_kind_r8, i8=>shr_kind_i8, cl=>shr_kind_cl, cs=>shr_kind_cs
use shr_const_mod , only : shr_const_TkFrz, shr_const_pi, shr_const_ocn_ref_sal, shr_const_spval
use shr_sys_mod , only : shr_sys_abort
use dshr_methods_mod , only : dshr_state_getfldptr, dshr_fldbun_getfldptr, chkerr
use dshr_fldlist_mod , only : fldlist_type, dshr_fldlist_add
use dshr_mod , only : dshr_restart_read, dshr_restart_write
use dshr_strdata_mod , only : shr_strdata_get_stream_pointer, shr_strdata_type, shr_strdata_get_stream_count

implicit none
private ! except

public :: docn_datamode_multilev_dom_advertise
public :: docn_datamode_multilev_dom_init_pointers
public :: docn_datamode_multilev_dom_advance
public :: docn_datamode_multilev_dom_restart_read
public :: docn_datamode_multilev_dom_restart_write

! pointers to export fields
real(r8), pointer :: So_omask(:) => null() ! real ocean fraction sent to mediator
real(r8), pointer :: So_t_depth(:,:) => null()
real(r8), pointer :: So_s_depth(:,:) => null()
real(r8), pointer :: So_t(:) => null()
real(r8), pointer :: So_u(:) => null()
real(r8), pointer :: So_v(:) => null()
real(r8), pointer :: So_s(:) => null()

! pointers to stream fields
real(r8), pointer :: stream_So_t_depth(:,:) => null()
real(r8), pointer :: stream_So_s_depth(:,:) => null()

integer, parameter :: nlev_export = 30
real(r8) :: vertical_levels(nlev_export) = (/ &
30., 90., 150., 210., 270., 330., 390., 450., 510., 570., &
630., 690., 750., 810., 870., 930., 990., 1050., 1110., 1170., &
1230., 1290., 1350., 1410., 1470., 1530., 1590., 1650., 1710., 1770. /)

real(r8) , parameter :: tkfrz = shr_const_tkfrz ! freezing point, fresh water (kelvin)
real(r8) , parameter :: ocnsalt = shr_const_ocn_ref_sal ! ocean reference salinity

! constants
character(*) , parameter :: nullstr = 'null'
character(*) , parameter :: rpfile = 'rpointer.ocn'
character(*) , parameter :: u_FILE_u = &
__FILE__

!===============================================================================
contains
!===============================================================================

subroutine docn_datamode_multilev_dom_advertise(exportState, fldsexport, flds_scalar_name, rc)

! input/output variables
type(esmf_State) , intent(inout) :: exportState
type(fldlist_type) , pointer :: fldsexport
character(len=*) , intent(in) :: flds_scalar_name
integer , intent(out) :: rc

! local variables
type(fldlist_type), pointer :: fldList
!-------------------------------------------------------------------------------

rc = ESMF_SUCCESS

! Advertise export fields
call dshr_fldList_add(fldsExport, trim(flds_scalar_name))
call dshr_fldList_add(fldsExport, 'So_omask')
call dshr_fldList_add(fldsExport, 'So_t_depth', ungridded_lbound=1, ungridded_ubound=nlev_export)
call dshr_fldList_add(fldsExport, 'So_s_depth', ungridded_lbound=1, ungridded_ubound=nlev_export)
call dshr_fldList_add(fldsExport, 'So_t' )
call dshr_fldList_add(fldsExport, 'So_s' )
call dshr_fldList_add(fldsExport, 'So_u' )
call dshr_fldList_add(fldsExport, 'So_v' )

fldlist => fldsExport ! the head of the linked list
do while (associated(fldlist))
call NUOPC_Advertise(exportState, standardName=fldlist%stdname, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
call ESMF_LogWrite('(docn_comp_advertise): Fr_ocn'//trim(fldList%stdname), ESMF_LOGMSG_INFO)
fldList => fldList%next
enddo

end subroutine docn_datamode_multilev_dom_advertise

!===============================================================================
subroutine docn_datamode_multilev_dom_init_pointers(exportState, sdat, ocn_fraction, rc)

! input/output variables
type(ESMF_State) , intent(inout) :: exportState
type(shr_strdata_type) , intent(in) :: sdat
real(r8) , intent(in) :: ocn_fraction(:)
integer , intent(out) :: rc

! local variables
character(len=*), parameter :: subname='(docn_init_pointers): '
!-------------------------------------------------------------------------------

rc = ESMF_SUCCESS

! initialize pointers to stream fields
! this has the full set of leveles in the stream data
call shr_strdata_get_stream_pointer( sdat, 'So_t_depth', stream_So_t_depth, rc=rc)
if (chkerr(rc,__LINE__,u_FILE_u)) return
call shr_strdata_get_stream_pointer( sdat, 'So_s_depth', stream_So_s_depth, rc=rc)
if (chkerr(rc,__LINE__,u_FILE_u)) return

call dshr_state_getfldptr(exportState, 'So_t', fldptr1=So_t, rc=rc)
if (chkerr(rc,__LINE__,u_FILE_u)) return
call dshr_state_getfldptr(exportState, 'So_s', fldptr1=So_s, rc=rc)
if (chkerr(rc,__LINE__,u_FILE_u)) return
call dshr_state_getfldptr(exportState, 'So_u', fldptr1=So_u, rc=rc)
if (chkerr(rc,__LINE__,u_FILE_u)) return
call dshr_state_getfldptr(exportState, 'So_v', fldptr1=So_v, rc=rc)
if (chkerr(rc,__LINE__,u_FILE_u)) return

! initialize pointers to export fields
! the export state has only nlev_export levels
call dshr_state_getfldptr(exportState, 'So_omask' , fldptr1=So_omask , rc=rc)
if (chkerr(rc,__LINE__,u_FILE_u)) return
call dshr_state_getfldptr(exportState, 'So_t_depth' , fldptr2=So_t_depth , rc=rc)
if (chkerr(rc,__LINE__,u_FILE_u)) return
call dshr_state_getfldptr(exportState, 'So_s_depth' , fldptr2=So_s_depth , rc=rc)
if (chkerr(rc,__LINE__,u_FILE_u)) return

! Initialize export state pointers to non-zero
So_t_depth(:,:) = shr_const_TkFrz
So_s_depth(:,:) = shr_const_ocn_ref_sal

So_u(:) = 0.0_r8
So_v(:) = 0.0_r8
So_s(:) = ocnsalt
So_t(:) = TkFrz

! Set export state ocean fraction (So_omask)
So_omask(:) = ocn_fraction(:)

end subroutine docn_datamode_multilev_dom_init_pointers

!===============================================================================
subroutine docn_datamode_multilev_dom_advance(sdat, logunit, mainproc, rc)

! input/output variables
type(shr_strdata_type) , intent(in) :: sdat
integer , intent(in) :: logunit
logical , intent(in) :: mainproc
integer , intent(out) :: rc

! local variables
integer :: i,ki,ko
integer :: nstreams
integer :: nlev_stream
integer :: stream_index
logical :: level_found
real(r8) :: factor
real(r8), allocatable :: stream_vlevs(:)
logical :: first_time = .true.
character(len=*), parameter :: subname='(docn_datamode_multilev_dom): '
!-------------------------------------------------------------------------------

rc = ESMF_SUCCESS

So_t(:) = So_t(:) + TkFrz

! Determine number of vertical levels for multi level stream
nstreams = shr_strdata_get_stream_count(sdat)
nlev_stream = 0
do stream_index = 1,nstreams
nlev_stream = sdat%pstrm(stream_index)%stream_nlev
if (nlev_stream > 1) exit
end do
if (nlev_stream == 0) then
call shr_sys_abort(trim(subname)//" could not find vertical levels greater than 0")
end if
allocate(stream_vlevs(nlev_stream))
stream_vlevs(:) = sdat%pstrm(stream_index)%stream_vlevs(:)

do ko = 1,nlev_export
level_found = .false.
do ki = 1,nlev_stream-1
if (vertical_levels(ko) > stream_vlevs(ki) .and. vertical_levels(ko) <= stream_vlevs(ki+1)) then
if (mainproc .and. first_time) then
write(logunit,'(a,3(i5,2x),3(f13.5,2x))') &
'vertical interpolation: ki,ko,ki+1,lev(ki),lev(ko),lev(ki+1) = ',&
ki,ko,ki+1,stream_vlevs(ki), vertical_levels(ko), stream_vlevs(ki+1)
end if
level_found = .true.
do i = 1,size(So_omask)
if (So_omask(i) == 0.) then
So_t_depth(ko,i) = shr_const_spval
So_s_depth(ko,i) = shr_const_spval
else
! Assume input T forcing is in degrees C
if (stream_So_t_depth(ki+1,i) > 1.e10) then
if (stream_So_t_depth(ki,i) > 1.e10) then
So_t_depth(ko,i) = shr_const_spval
So_s_depth(ko,i) = shr_const_spval
else
So_t_depth(ko,i) = stream_So_t_depth(ki,i) + shr_const_tkfrz
So_s_depth(ko,i) = stream_So_s_depth(ki,i)
end if
else
factor = (stream_So_t_depth(ki+1,i)-stream_So_t_depth(ki,i))/(stream_vlevs(ki+1)-stream_vlevs(ki))
So_t_depth(ko,i) = stream_So_t_depth(ki,i) + (vertical_levels(ko)-stream_vlevs(ki))*factor
So_t_depth(ko,i) = So_t_depth(ko,i) + shr_const_tkfrz

factor = (stream_So_s_depth(ki+1,i)-stream_So_s_depth(ki,i))/(stream_vlevs(ki+1)-stream_vlevs(ki))
So_s_depth(ko,i) = stream_So_s_depth(ki,i) + (vertical_levels(ko)-stream_vlevs(ki))*factor
end if
end if
end do
end if
end do
if (.not. level_found) then
call shr_sys_abort(trim(subname)//" could not find level bounds for vertical interpolation")
end if
end do

first_time = .false.

end subroutine docn_datamode_multilev_dom_advance

!===============================================================================
subroutine docn_datamode_multilev_dom_restart_write(case_name, inst_suffix, ymd, tod, &
logunit, my_task, sdat)

! write restart file

! input/output variables
character(len=*) , intent(in) :: case_name
character(len=*) , intent(in) :: inst_suffix
integer , intent(in) :: ymd ! model date
integer , intent(in) :: tod ! model sec into model date
integer , intent(in) :: logunit
integer , intent(in) :: my_task
type(shr_strdata_type) , intent(inout) :: sdat
!-------------------------------------------------------------------------------

call dshr_restart_write(rpfile, case_name, 'docn', inst_suffix, ymd, tod, &
logunit, my_task, sdat)

end subroutine docn_datamode_multilev_dom_restart_write

!===============================================================================
subroutine docn_datamode_multilev_dom_restart_read(rest_filem, inst_suffix, logunit, my_task, mpicom, sdat)

! read restart file

! input/output arguments
character(len=*) , intent(inout) :: rest_filem
character(len=*) , intent(in) :: inst_suffix
integer , intent(in) :: logunit
integer , intent(in) :: my_task
integer , intent(in) :: mpicom
type(shr_strdata_type) , intent(inout) :: sdat
!-------------------------------------------------------------------------------

call dshr_restart_read(rest_filem, rpfile, inst_suffix, nullstr, logunit, my_task, mpicom, sdat)

end subroutine docn_datamode_multilev_dom_restart_read

end module docn_datamode_multilev_dom_mod
19 changes: 17 additions & 2 deletions docn/ocn_comp_nuopc.F90
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,12 @@ module cdeps_docn_comp
use docn_datamode_multilev_mod , only : docn_datamode_multilev_advance
use docn_datamode_multilev_mod , only : docn_datamode_multilev_restart_read
use docn_datamode_multilev_mod , only : docn_datamode_multilev_restart_write
use docn_import_data_mod , only : docn_import_data_advertise
use docn_datamode_multilev_dom_mod, only : docn_datamode_multilev_dom_advertise
use docn_datamode_multilev_dom_mod, only : docn_datamode_multilev_dom_init_pointers
use docn_datamode_multilev_dom_mod, only : docn_datamode_multilev_dom_advance
use docn_datamode_multilev_dom_mod, only : docn_datamode_multilev_dom_restart_read
use docn_datamode_multilev_dom_mod, only : docn_datamode_multilev_dom_restart_write
use docn_import_data_mod , only : docn_import_data_advertise

implicit none
private ! except
Expand Down Expand Up @@ -307,7 +312,8 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc)
trim(datamode) == 'cplhist' .or. & ! read stream, needs import data
trim(datamode) == 'sst_aquap_analytic' .or. & ! analytic, no streams, import or export data
trim(datamode) == 'sst_aquap_constant' .or. & ! analytic, no streams, import or export data
trim(datamode) == 'multilev') then ! multilevel ocean input
trim(datamode) == 'multilev' .or. & ! multilevel ocean input
trim(datamode) == 'multilev_dom') then ! multilevel ocean input and sst export
! success do nothing
else
call shr_sys_abort(' ERROR illegal docn datamode = '//trim(datamode))
Expand All @@ -333,6 +339,9 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc)
else if (trim(datamode) == 'multilev') then
call docn_datamode_multilev_advertise(exportState, fldsExport, flds_scalar_name, rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
else if (trim(datamode) == 'multilev_dom') then
call docn_datamode_multilev_dom_advertise(exportState, fldsExport, flds_scalar_name, rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
end if

if (trim(import_data_fields) /= 'none') then
Expand Down Expand Up @@ -563,6 +572,9 @@ subroutine docn_comp_run(importState, exportState, clock, target_ymd, target_tod
case('multilev')
call docn_datamode_multilev_init_pointers(exportState, sdat, model_frac, rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
case('multilev_dom')
call docn_datamode_multilev_dom_init_pointers(exportState, sdat, model_frac, rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
end select

! Read restart if needed
Expand Down Expand Up @@ -623,6 +635,9 @@ subroutine docn_comp_run(importState, exportState, clock, target_ymd, target_tod
case('multilev')
call docn_datamode_multilev_advance(sdat, logunit, mainproc, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
case('multilev_dom')
call docn_datamode_multilev_dom_advance(sdat, logunit, mainproc, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
end select

! Write restarts if needed (no restarts for aquaplanet analytic or aquaplanet input file)
Expand Down
2 changes: 1 addition & 1 deletion drof/cime_config/testdefs/testlist_drof.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

<test compset="2000_SATM_SLND_SICE_SOCN_DROF%NYF_SGLC_SWAV" grid="f19_g17_rx1" name="SMS_Ld3">
<machines>
<machine name="cheyenne" compiler="intel" category="aux_cdeps"/>
<machine name="derecho" compiler="intel" category="aux_cdeps"/>
<machine name="betzy" compiler="intel" category="aux_cdeps_noresm"/>
</machines>
<options>
Expand Down

0 comments on commit b7a6088

Please sign in to comment.