diff --git a/docn/CMakeLists.txt b/docn/CMakeLists.txt
index 256dc304..46e51007 100644
--- a/docn/CMakeLists.txt
+++ b/docn/CMakeLists.txt
@@ -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})
diff --git a/docn/cime_config/config_component.xml b/docn/cime_config/config_component.xml
index ab88c6fe..c5461d90 100644
--- a/docn/cime_config/config_component.xml
+++ b/docn/cime_config/config_component.xml
@@ -13,7 +13,7 @@
This file may have ocn desc entries.
-->
- DOCN
+ DOCN
prescribed ocean mode
slab ocean mode
aquaplanet slab ocean mode
@@ -33,6 +33,7 @@
globally constant SST for idealized experiments, such as RCE
mediator history output for ocean fields imported to mediator
input stream files have multi level data
+ input stream files have multi level data and prescribed ocean SST
@@ -46,7 +47,7 @@
char
- 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
+ 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
prescribed
prescribed
@@ -67,6 +68,7 @@
sst_aquap_constant
cplhist
multilev
+ multilev_dom
run_component_docn
env_run.xml
diff --git a/docn/cime_config/namelist_definition_docn.xml b/docn/cime_config/namelist_definition_docn.xml
index b2f78811..3e6d1255 100644
--- a/docn/cime_config/namelist_definition_docn.xml
+++ b/docn/cime_config/namelist_definition_docn.xml
@@ -32,6 +32,7 @@
''
''
''
+ sst_salinity_depth_blom,prescribed
sst_salinity_depth_blom
@@ -40,7 +41,7 @@
char
docn
docn_nml
- 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
+ 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
General method that operates on the data for a given docn_mode.
==> dataMode = "sstdata"
@@ -108,6 +109,7 @@
sst_aquap_file
sst_aquap_constant
cplhist
+ multilev_dom
multilev
diff --git a/docn/docn_datamode_multilev_dom_mod.F90 b/docn/docn_datamode_multilev_dom_mod.F90
new file mode 100644
index 00000000..7cd7fd9e
--- /dev/null
+++ b/docn/docn_datamode_multilev_dom_mod.F90
@@ -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
diff --git a/docn/ocn_comp_nuopc.F90 b/docn/ocn_comp_nuopc.F90
index ced8cb86..f15ed9ec 100644
--- a/docn/ocn_comp_nuopc.F90
+++ b/docn/ocn_comp_nuopc.F90
@@ -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
@@ -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))
@@ -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
@@ -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
@@ -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)
diff --git a/drof/cime_config/testdefs/testlist_drof.xml b/drof/cime_config/testdefs/testlist_drof.xml
index e45c72a3..6e423fab 100644
--- a/drof/cime_config/testdefs/testlist_drof.xml
+++ b/drof/cime_config/testdefs/testlist_drof.xml
@@ -3,7 +3,7 @@
-
+