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

Add capability to send both prescribed SST and multi-level ocean SST/SALN to mediator #289

Merged
merged 4 commits into from
Jul 12, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
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
Loading