Repository: NorESMhub/CDEPS
Pull request #10: Enable DLND to read mediator auxiliary file for glc forcing and add DOCN%MULTILEV-CPLHIST mode
Author: login: mvertens
Labels: name: enhancement
description: New feature or request
Created: 2024-11-24T14:20:55Z | Merged: 2025-04-14T08:46:26Z

### Description of changes
- Changes to dlnd to enable dlnd to work with mediator auxiliary file output for glc forcing 
- Addition of DOCN%MULTILEV-CPLHIST mode to allow reading of So_s_depth[1-10] and So_t_depth[1-10] from mediator history files

### Specific notes
The current implementation of dlnd only works with mct coupler output. 

With this PR, DLND still maintains this functionality but also is now able read in data that was generated in a fully coupled run using the `cmeps nuopc.runconfig` setting ` histaux_l2x1yrg = .true.`

In order to do this - a new mode has been introduced for dlnd in `config_component.xml`
```
    <desc lnd="DLND[%SCPL][%GCPL]">Data land model (DLND) </desc>
    <desc option="SCPL">snow coupling mode to drive glc with data from cpl7 run) </desc>
    <desc option="GCPL">snow coupling mode to drive glc with data from cmeps run) </desc> <=== new
```
Similarly in` stream_definition_dlnd.xml` a new stream was introduced for the new mode - 
`  <stream_entry name="glc_forcing">`
and the original stream name 
`<stream_entry name="sno.cplhist"> ` has been changed to `<stream_entry name="glc_forcing_mct">` for clarity.

Introduced two new tests for both docn and dlnd - that now test this capability using new data in /cluster/shared/noresm/inputdata/cplhist/noresm3_0/test-dlnd2glc-docn2glc/ generated by @mpetrini-norce

SMS_Ly4.f09_tn14.1850_SATM_SLND_SICE_DOCN%MULTILEV-CPLHIST_SROF_SGLC_SWAV.betzy_intel.docn-multilev_cplhist
SMS_Ly4.f09_f09_mtn14.1850_SATM_DLND%GCPL_SICE_SOCN_SROF_SGLC_SWAV.betzy_intel.dlnd-glc_forcing

NOTE: there are no out of the box datasets that will be used for the new mode - so xml changes have to be carried out explicitly.

Contributors other than yourself, if any: None

CDEPS Issues Fixed: None

Are there dependencies on other component PRs (if so list): None

Are changes expected to change answers: bfb - this is new functionality

Any User Interface Changes:
- New DLND%GCPL mode
- Old DLND%LCPL MCT no-snow mode removed (not used)

Testing performed: 
**Backwards compatibility:**
- ERS_Ly5.f09_g17_ais8.T1850Ga.betzy_intel passes
SMS_Ld3.f09_f09_mg17.1850_SATM_DLND%SCPL_SICE_SOCN_SROF_SGLC_SWAV.betzy_intel passes
In the following two tests - verified that the coupler history output matched the forcing data in /cluster/shared/noresm/inputdata/cplhist/noresm3_0/test-dlnd2glc-docn2glc
- SMS_Ly4.f09_tn14.1850_SATM_SLND_SICE_DOCN%MULTILEV-CPLHIST_SROF_SGLC_SWAV.betzy_intel.docn-multilev_cplhist passes
- SMS_Ly4.f09_f09_mtn14.1850_SATM_DLND%GCPL_SICE_SOCN_SROF_SGLC_SWAV.betzy_intel.dlnd-glc_forcing passes

**New functionality:**
./create_newcase --case TG1850_f09_tn14_gl4ais8_coldstart_241120 --compset 1850_SATM_DLND%GCPL_SICE_SOCN_SROF_CISM2%AIS-EVOLVE%GRIS-EVOLVE_SWAV --res a%null_l%0.9x1.25_oi%null_r%null_g%ais8:gris4_w%null_z%null_m%tnx1v4 --run-unsupported

2. You need to do an xml change of the following variables (I'll list what I used for  data from @mpetrini-norce)
./xmlchange DLND_CPLHIST_DIR=/cluster/projects/nn11022k/mpet/dataset/cplhist/l0.9x1.25/test_1deg_CAM_CLM_CICE_BLOM_GRISAIS_6
./xmlchange DLND_CPLHIST_CASE=test_1deg_CAM_CLM_CICE_BLOM_GRISAIS_6
./xmlchange DLND_CPLHIST_YR_ALIGN=1
./xmlchange DLND_CPLHIST_YR_START=2
./xmlchange DLND_CPLHIST_YR_END=3

Hashes used for testing: noresm3_0_alpha02



Diff:
diff --git a/cime_config/stream_cdeps.py b/cime_config/stream_cdeps.py
index 3d653745a..ce8c4aec7 100644
--- a/cime_config/stream_cdeps.py
+++ b/cime_config/stream_cdeps.py
@@ -660,7 +660,10 @@ def _sub_paths(
                                 adjusted_year, adjusted_month, adjusted_day
                             )
                             new_line = line.replace(match.group(0), date_string)
-                            new_lines.append(new_line)
+                            if os.path.exists(new_line):
+                                new_lines.append(new_line)
+                            else:
+                                print(f"   WARNING:not adding missing file {new_line}")
                 elif match.group("month"):
                     for month in range(1, 13):
                         date_string = (year_format + "-{:02d}").format(year, month)
diff --git a/dlnd/cime_config/config_component.xml b/dlnd/cime_config/config_component.xml
index ab40fa583..20745449f 100644
--- a/dlnd/cime_config/config_component.xml
+++ b/dlnd/cime_config/config_component.xml
@@ -12,9 +12,9 @@
        This file may have lnd desc entries.
   -->
   <description modifier_mode="1">
-    <desc lnd="DLND[%SCPL][%LCPL]">Data land model (DLND) </desc>
-    <desc option="SCPL">snow coupling mode </desc>
-    <desc option="LCPL">non-snow coupling </desc>
+    <desc lnd="DLND[%SCPL][%GCPL]">Data land model (DLND) </desc>
+    <desc option="SCPL">snow coupling mode to drive glc with data from cpl7 run) </desc>
+    <desc option="GCPL">snow coupling mode to drive glc with data from cmeps run) </desc>
   </description>
 
   <entry id="COMP_LND">
@@ -28,19 +28,17 @@
 
   <entry id="DLND_MODE">
     <type>char</type>
-    <valid_values>SCPL,LCPL</valid_values>
-    <default_value>SCPL</default_value>
+    <valid_values>SCPL,GCPL</valid_values>
+    <default_value>GCPL</default_value>
     <values match="last">
       <value compset="DLND%SCPL">SCPL</value>
-      <value compset="DLND%LCPL">LCPL</value>
+      <value compset="DLND%GCPL">GCPL</value>
     </values>
     <group>run_component_dlnd</group>
     <file>env_run.xml</file>
     <desc>
       model mode.
-      In SCPL, glc coupling data (produced by CISM) from a previous
-      model run is read in from a coupler history file.
-      In LCPL, land forcing data (produced by CLM) from a previous
+      In SCPL or GCPL model glc coupling data produced by lnd from a previous
       model run is read in from a coupler history file.
     </desc>
   </entry>
@@ -77,7 +75,7 @@
     <file>env_run.xml</file>
     <desc>
       Simulation year corresponding to DLND_CPLHIST_YR_START (only used
-      when DLND_MODE is CPLHIST or GLC_CPLHIST). A common usage is to
+      when DLND_MODE is SCPL or GCPL). A common usage is to
       set this to RUN_STARTDATE. With this setting, the forcing in the
       first year of the run will be the forcing of year
       DLND_CPLHIST_YR_START. Another use case is to align the calendar
@@ -90,6 +88,7 @@
     </desc>
   </entry>
 
+
   <entry id="DLND_CPLHIST_YR_START">
     <type>integer</type>
     <default_value>-999</default_value>
diff --git a/dlnd/cime_config/namelist_definition_dlnd.xml b/dlnd/cime_config/namelist_definition_dlnd.xml
index b10350b74..b85b0419d 100644
--- a/dlnd/cime_config/namelist_definition_dlnd.xml
+++ b/dlnd/cime_config/namelist_definition_dlnd.xml
@@ -17,8 +17,8 @@
     <group>streams_file</group>
     <desc>List of streams used for each supported dlnd_mode</desc>
     <values>
-      <value dlnd_mode="LCPL">lnd.cplhist</value>
-      <value dlnd_mode="SCPL">sno.cplhist</value>
+      <value dlnd_mode="SCPL">glc_forcing_mct</value>
+      <value dlnd_mode="GCPL">glc_forcing</value>
     </values>
   </entry>
 
@@ -26,13 +26,14 @@
     <type>char</type>
     <category>dlnd</category>
     <group>dlnd_nml</group>
-    <valid_values>copyall</valid_values>
+    <valid_values>glc_forcing_mct,glc_forcing</valid_values>
     <desc>
       Copies all fields directly from the input data streams Any required
       fields not found on an input stream will be set to zero.
     </desc>
     <values>
-      <value>copyall</value>
+      <value dlnd_mode="SCPL">glc_forcing_mct</value>
+      <value dlnd_mode="GCPL">glc_forcing</value>
     </values>
   </entry>
 
diff --git a/dlnd/cime_config/stream_definition_dlnd.xml b/dlnd/cime_config/stream_definition_dlnd.xml
index 292d8834d..4c8103475 100644
--- a/dlnd/cime_config/stream_definition_dlnd.xml
+++ b/dlnd/cime_config/stream_definition_dlnd.xml
@@ -14,7 +14,7 @@
 
 <stream_data version="2.0" xmlns:xi="http://www.w3.org/2001/XInclude">
 
-  <stream_entry name="sno.cplhist">
+  <stream_entry name="glc_forcing_mct">
     <stream_meshfile>
       <meshfile>$LND_DOMAIN_MESH</meshfile>
     </stream_meshfile>
@@ -49,4 +49,69 @@
     <stream_readmode>single</stream_readmode>
   </stream_entry>
 
+  <stream_entry name="glc_forcing">
+    <stream_meshfile>
+      <meshfile>$LND_DOMAIN_MESH</meshfile>
+    </stream_meshfile>
+    <stream_datafiles>
+      <!-- Specify first year = 0, last year = 99999 in order to apply
+           this pattern to all possible years that might be included. -->
+      <file first_year="0" last_year="99999">$DLND_CPLHIST_DIR/$DLND_CPLHIST_CASE.cpl.hx.lnd2glc.%y-01-01-00000.nc</file>
+    </stream_datafiles>
+   <stream_datavars>
+      <var>lndImp_Sl_topo_elev1    Sl_topo_elev1</var>
+      <var>lndImp_Sl_topo_elev2    Sl_topo_elev2</var>
+      <var>lndImp_Sl_topo_elev3    Sl_topo_elev3</var>
+      <var>lndImp_Sl_topo_elev4    Sl_topo_elev4</var>
+      <var>lndImp_Sl_topo_elev5    Sl_topo_elev5</var>
+      <var>lndImp_Sl_topo_elev6    Sl_topo_elev6</var>
+      <var>lndImp_Sl_topo_elev7    Sl_topo_elev7</var>
+      <var>lndImp_Sl_topo_elev8    Sl_topo_elev8</var>
+      <var>lndImp_Sl_topo_elev9    Sl_topo_elev9</var>
+      <var>lndImp_Sl_topo_elev10   Sl_topo_elev10</var>
+      <var>lndImp_Sl_topo_elev11   Sl_topo_elev11</var>
+      <var>lndImp_Sl_tsrf_elev1    Sl_tsrf_elev1</var>
+      <var>lndImp_Sl_tsrf_elev2    Sl_tsrf_elev2</var>
+      <var>lndImp_Sl_tsrf_elev3    Sl_tsrf_elev3</var>
+      <var>lndImp_Sl_tsrf_elev4    Sl_tsrf_elev4</var>
+      <var>lndImp_Sl_tsrf_elev5    Sl_tsrf_elev5</var>
+      <var>lndImp_Sl_tsrf_elev6    Sl_tsrf_elev6</var>
+      <var>lndImp_Sl_tsrf_elev7    Sl_tsrf_elev7</var>
+      <var>lndImp_Sl_tsrf_elev8    Sl_tsrf_elev8</var>
+      <var>lndImp_Sl_tsrf_elev9    Sl_tsrf_elev9</var>
+      <var>lndImp_Sl_tsrf_elev10   Sl_tsrf_elev10</var>
+      <var>lndImp_Sl_tsrf_elev11   Sl_tsrf_elev11</var>
+      <var>lndImp_Flgl_qice_elev1  Flgl_qice_elev1</var>
+      <var>lndImp_Flgl_qice_elev2  Flgl_qice_elev2</var>
+      <var>lndImp_Flgl_qice_elev3  Flgl_qice_elev3</var>
+      <var>lndImp_Flgl_qice_elev4  Flgl_qice_elev4</var>
+      <var>lndImp_Flgl_qice_elev5  Flgl_qice_elev5</var>
+      <var>lndImp_Flgl_qice_elev6  Flgl_qice_elev6</var>
+      <var>lndImp_Flgl_qice_elev7  Flgl_qice_elev7</var>
+      <var>lndImp_Flgl_qice_elev8  Flgl_qice_elev8</var>
+      <var>lndImp_Flgl_qice_elev9  Flgl_qice_elev9</var>
+      <var>lndImp_Flgl_qice_elev10 Flgl_qice_elev10</var>
+      <var>lndImp_Flgl_qice_elev11 Flgl_qice_elev11</var>
+    </stream_datavars>
+    <stream_lev_dimname>null</stream_lev_dimname>
+    <stream_mapalgo>
+      <mapalgo>bilinear</mapalgo>
+    </stream_mapalgo>
+    <stream_vectors>null</stream_vectors>
+    <stream_year_align>$DLND_CPLHIST_YR_ALIGN</stream_year_align>
+    <stream_year_first>$DLND_CPLHIST_YR_START</stream_year_first>
+    <stream_year_last>$DLND_CPLHIST_YR_END</stream_year_last>
+    <stream_offset>0</stream_offset>
+    <stream_tintalgo>
+      <tintalgo>lower</tintalgo>
+    </stream_tintalgo>
+    <stream_taxmode>
+      <taxmode>cycle</taxmode>
+    </stream_taxmode>
+    <stream_dtlimit>
+      <dtlimit>1.5</dtlimit>
+    </stream_dtlimit>
+    <stream_readmode>single</stream_readmode>
+  </stream_entry>
+
 </stream_data>
diff --git a/dlnd/cime_config/testdefs/testlist_dlnd.xml b/dlnd/cime_config/testdefs/testlist_dlnd.xml
index 59026878c..0e4d5b00f 100644
--- a/dlnd/cime_config/testdefs/testlist_dlnd.xml
+++ b/dlnd/cime_config/testdefs/testlist_dlnd.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <testlist version="2.0">
 
-  <test compset="1850_SATM_DLND%SCPL_SICE_SOCN_SROF_SGLC_SWAV" grid="f09_f09_mg17" name="SMS_Ld3">
+  <test name="SMS_Ld3" compset="1850_SATM_DLND%SCPL_SICE_SOCN_SROF_SGLC_SWAV" grid="f09_f09_mg17">
     <machines>
       <machine name="derecho" compiler="intel" category="aux_cdeps"/>
       <machine name="betzy" compiler="intel" category="aux_cdeps_noresm"/>
@@ -11,4 +11,13 @@
     </options>
   </test>
 
+  <test name="SMS_Ly4" compset="1850_SATM_DLND%GCPL_SICE_SOCN_SROF_SGLC_SWAV" grid="f09_f09_mg17" testmods="dlnd/glc_forcing">
+    <machines>
+      <machine name="betzy" compiler="intel" category="aux_cdeps_noresm"/>
+    </machines>
+    <options>
+      <option name="wallclock"> 00:10:00 </option>
+    </options>
+  </test>
+
 </testlist>
diff --git a/dlnd/cime_config/testdefs/testmods_dirs/dlnd/glc_forcing/shell_commands b/dlnd/cime_config/testdefs/testmods_dirs/dlnd/glc_forcing/shell_commands
new file mode 100644
index 000000000..f2c10621d
--- /dev/null
+++ b/dlnd/cime_config/testdefs/testmods_dirs/dlnd/glc_forcing/shell_commands
@@ -0,0 +1,9 @@
+./xmlchange DLND_CPLHIST_CASE=B2G1850_f09_tn14_gl4ais8_coldstart_20250122
+./xmlchange DLND_CPLHIST_DIR='$DIN_LOC_ROOT/cplhist/noresm3_0/test-dlnd2glc-docn2glc'
+./xmlchange DLND_CPLHIST_YR_ALIGN=2
+./xmlchange DLND_CPLHIST_YR_END=6
+./xmlchange DLND_CPLHIST_YR_START=2
+./xmlchange RUN_STARTDATE=0002-01-01
+./xmlchange ATM_NCPL=1
+./xmlchange ROF_NCPL=1
+./xmlchange NCPL_BASE_PERIOD=year
diff --git a/dlnd/lnd_comp_nuopc.F90 b/dlnd/lnd_comp_nuopc.F90
index 3ad783862..7450b4c95 100644
--- a/dlnd/lnd_comp_nuopc.F90
+++ b/dlnd/lnd_comp_nuopc.F90
@@ -35,7 +35,7 @@ module cdeps_dlnd_comp
   use dshr_fldlist_mod  , only : fldlist_type, dshr_fldlist_add, dshr_fldlist_realize
   use glc_elevclass_mod , only : glc_elevclass_as_string, glc_elevclass_init
   use nuopc_shr_methods , only : shr_get_rpointer_name
-  
+
   implicit none
   private ! except
 
@@ -61,7 +61,7 @@ module cdeps_dlnd_comp
   integer                  :: flds_scalar_index_ny = 0
   integer                  :: mpicom                              ! mpi communicator
   integer                  :: my_task                             ! my task in mpi communicator mpicom
-  logical                  :: mainproc                          ! true of my_task == main_task
+  logical                  :: mainproc                            ! true of my_task == main_task
   integer                  :: inst_index                          ! number of current instance (ie. 1)
   character(len=16)        :: inst_suffix = ""                    ! char string associated with instance (ie. "_0001" or "")
   integer                  :: logunit                             ! logging unit number
@@ -245,7 +245,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc)
     endif
 
     ! Validate sdat datamode
-    if (trim(datamode) == 'copyall') then
+    if (trim(datamode) == 'glc_forcing_mct' .or. trim(datamode) == 'glc_forcing' ) then
        if (my_task == main_task) write(logunit,*) 'dlnd datamode = ',trim(datamode)
     else
        call shr_log_error(' ERROR illegal dlnd datamode = '//trim(datamode), rc=rc)
@@ -467,14 +467,6 @@ subroutine dlnd_comp_advertise(importState, exportState, rc)
        fldList => fldList%next
     enddo
 
-    ! TODO: Non snow fields that nead to be added if dlnd is in cplhist mode
-    ! "Sl_t        " "Sl_tref     " "Sl_qref     " "Sl_avsdr    "
-    ! "Sl_anidr    " "Sl_avsdf    " "Sl_anidf    " "Sl_snowh    "
-    ! "Fall_taux   " "Fall_tauy   " "Fall_lat    " "Fall_sen    "
-    ! "Fall_lwup   " "Fall_evap   " "Fall_swnet  " "Sl_landfrac "
-    ! "Sl_fv       " "Sl_ram1     "
-    ! "Fall_flxdst1" "Fall_flxdst2" "Fall_flxdst3" "Fall_flxdst4"
-
   end subroutine dlnd_comp_advertise
 
   !===============================================================================
@@ -518,10 +510,13 @@ subroutine dlnd_comp_run(importState, exportState, target_ymd, target_tod, rc)
     integer          , intent(out)   :: rc
 
     ! local variables
-    logical                    :: first_time = .true.
     integer                    :: n
     character(len=2)           :: nec_str
-    character(CS), allocatable :: strm_flds(:)
+    character(CS), allocatable :: strm_flds_topo(:)
+    character(CS), allocatable :: strm_flds_tsrf(:)
+    character(CS), allocatable :: strm_flds_qice(:)
+    real(r8), pointer          :: fldptr2(:,:)
+    logical                    :: first_time = .true.
     !-------------------------------------------------------------------------------
 
     rc = ESMF_SUCCESS
@@ -542,31 +537,46 @@ subroutine dlnd_comp_run(importState, exportState, target_ymd, target_tod, rc)
        ! Create stream-> export state mapping
        ! Note that strm_flds is the model name for the stream field
        ! Note that state_fld is the model name for the export field
-       allocate(strm_flds(0:glc_nec))
-       do n = 0,glc_nec
-          nec_str = glc_elevclass_as_string(n)
-          strm_flds(n) = 'Sl_tsrf_elev' // trim(nec_str)
-       end do
-       call dshr_dfield_add(dfields, sdat, state_fld='Sl_tsrf_elev', strm_flds=strm_flds, state=exportState, &
+
+       if (trim(datamode) == 'glc_forcing_mct') then
+          allocate(strm_flds_tsrf(0:glc_nec))
+          allocate(strm_flds_topo(0:glc_nec))
+          allocate(strm_flds_qice(0:glc_nec))
+          do n = 0,glc_nec
+             write(nec_str, '(i2.2)') n
+             strm_flds_tsrf(n) = 'Sl_tsrf_elev'   // trim(nec_str)
+             strm_flds_topo(n) = 'Sl_topo_elev'   // trim(nec_str)
+             strm_flds_qice(n) = 'Flgl_qice_elev' // trim(nec_str)
+          end do
+
+       else if (trim(datamode) == 'glc_forcing' ) then
+          allocate(strm_flds_tsrf(1:glc_nec+1))
+          allocate(strm_flds_topo(1:glc_nec+1))
+          allocate(strm_flds_qice(1:glc_nec+1))
+          do n = 1,glc_nec+1
+             write(nec_str, '(i0)') n
+             strm_flds_tsrf(n) = 'Sl_tsrf_elev'   // trim(nec_str)
+             strm_flds_topo(n) = 'Sl_topo_elev'   // trim(nec_str)
+             strm_flds_qice(n) = 'Flgl_qice_elev' // trim(nec_str)
+          end do
+
+       end if
+
+       ! The following maps stream input fields to export fields that have an ungridded dimension
+       call dshr_dfield_add(dfields, sdat, state_fld='Sl_tsrf_elev', strm_flds=strm_flds_tsrf, state=exportState, &
             logunit=logunit, mainproc=mainproc, rc=rc)
        if (ChkErr(rc,__LINE__,u_FILE_u)) return
-
-       do n = 0,glc_nec
-          nec_str = glc_elevclass_as_string(n)
-          strm_flds(n) = 'Sl_topo_elev' // trim(nec_str)
-       end do
-       call dshr_dfield_add(dfields, sdat, state_fld='Sl_topo_elev', strm_flds=strm_flds, state=exportState, &
+       call dshr_dfield_add(dfields, sdat, state_fld='Sl_topo_elev', strm_flds=strm_flds_topo, state=exportState, &
             logunit=logunit, mainproc=mainproc, rc=rc)
        if (ChkErr(rc,__LINE__,u_FILE_u)) return
-
-       do n = 0,glc_nec
-          nec_str = glc_elevclass_as_string(n)
-          strm_flds(n) = 'Flgl_qice_elev' // trim(nec_str)
-       end do
-       call dshr_dfield_add(dfields, sdat, state_fld='Flgl_qice_elev', strm_flds=strm_flds, state=exportState, &
+       call dshr_dfield_add(dfields, sdat, state_fld='Flgl_qice_elev', strm_flds=strm_flds_qice, state=exportState, &
             logunit=logunit, mainproc=mainproc, rc=rc)
        if (ChkErr(rc,__LINE__,u_FILE_u)) return
 
+       deallocate(strm_flds_tsrf)
+       deallocate(strm_flds_topo)
+       deallocate(strm_flds_qice)
+
        first_time = .false.
     end if
 
@@ -594,6 +604,27 @@ subroutine dlnd_comp_run(importState, exportState, target_ymd, target_tod, rc)
        ! do nothing extra
     end select
 
+    ! Set special value over masked points
+    if (trim(datamode) == 'glc_forcing_mct' .or. trim(datamode) == 'glc_forcing' ) then
+       call dshr_state_getfldptr(exportState, 'Sl_tsrf_elev', fldptr2=fldptr2, rc=rc)
+       if (chkerr(rc,__LINE__,u_FILE_u)) return
+       do n = 1,size(fldptr2,dim=2)
+          if (lfrac(n) == 0._r8) fldptr2(:,n) = 1.e30_r8
+       end do
+
+       call dshr_state_getfldptr(exportState, 'Sl_topo_elev', fldptr2=fldptr2, rc=rc)
+       if (chkerr(rc,__LINE__,u_FILE_u)) return
+       do n = 1,size(fldptr2,dim=2)
+          if (lfrac(n) == 0._r8) fldptr2(:,n) = 1.e30_r8
+       end do
+
+       call dshr_state_getfldptr(exportState, 'Flgl_qice_elev', fldptr2=fldptr2, rc=rc)
+       if (chkerr(rc,__LINE__,u_FILE_u)) return
+       do n = 1,size(fldptr2,dim=2)
+          if (lfrac(n) == 0._r8) fldptr2(:,n) = 1.e30_r8
+       end do
+    end if
+
     call ESMF_TraceRegionExit('dlnd_datamode')
     call ESMF_TraceRegionExit('DLND_RUN')
 
diff --git a/docn/CMakeLists.txt b/docn/CMakeLists.txt
index 46e51007f..ab12861cd 100644
--- a/docn/CMakeLists.txt
+++ b/docn/CMakeLists.txt
@@ -7,6 +7,7 @@ set(SRCFILES ocn_comp_nuopc.F90
              docn_datamode_cplhist_mod.F90
              docn_datamode_multilev_mod.F90
              docn_datamode_multilev_dom_mod.F90
+             docn_datamode_multilev_cplhist_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 251dddf66..114eb7f8d 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.
   -->
   <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][%MULTILEV-DOM]">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-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>
@@ -34,6 +34,7 @@
     <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>
+    <desc option="MULTILEV-CPLHIST"> mediator history output for multi-level ocean fields imported to mediator</desc>
   </description>
 
   <entry id="COMP_OCN">
@@ -47,7 +48,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,multilev_dom</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,multilev_cplhist</valid_values>
     <default_value>prescribed</default_value>
     <values match="last">
       <value compset="_DOCN%DOM_" >prescribed</value>
@@ -69,6 +70,7 @@
       <value compset="_DOCN%CPLHIST">cplhist</value>
       <value compset="_DOCN%MULTILEV">multilev</value>
       <value compset="_DOCN%MULTILEV-DOM">multilev_dom</value>
+      <value compset="_DOCN%MULTILEV-CPLHIST">multilev_cplhist</value>
     </values>
     <group>run_component_docn</group>
     <file>env_run.xml</file>
@@ -255,6 +257,22 @@
     This is only used when DOCN_MODE=prescribed.</desc>
   </entry>
 
+  <entry id="DOCN_CPLHIST_DIR">
+    <type>char</type>
+    <default_value>UNSET</default_value>
+    <group>run_component_docn</group>
+    <file>env_run.xml</file>
+    <desc>directory for coupler history data mode (only used for CPLHIST mode)</desc>
+  </entry>
+
+  <entry id="DOCN_CPLHIST_CASE">
+    <type>char</type>
+    <default_value>UNSET</default_value>
+    <group>run_component_docn</group>
+    <file>env_run.xml</file>
+    <desc>case name for coupler history data mode (only used for CPLHIST mode)</desc>
+  </entry>
+
   <entry id="DOCN_CPLHIST_YR_ALIGN">
     <type>integer</type>
     <valid_values></valid_values>
diff --git a/docn/cime_config/namelist_definition_docn.xml b/docn/cime_config/namelist_definition_docn.xml
index 3e6d12558..03b43af9d 100644
--- a/docn/cime_config/namelist_definition_docn.xml
+++ b/docn/cime_config/namelist_definition_docn.xml
@@ -19,7 +19,6 @@
       <value docn_mode="interannual">interannual</value>
       <value docn_mode="som_aquap">som_aquap</value>
       <value docn_mode="som">som</value>
-      <value docn_mode="cplhist">cplhist</value>
       <value docn_mode="sst_aquap_file">aquapfile</value>
       <value docn_mode="sst_aquap_constant">''</value>
       <value docn_mode="sst_aquap1">''</value>
@@ -32,8 +31,10 @@
       <value docn_mode="sst_aquap8">''</value>
       <value docn_mode="sst_aquap9">''</value>
       <value docn_mode="sst_aquap10">''</value>
+      <value docn_mode="multilev_cplhist">multilev_cplhist</value>
       <value docn_mode="multilev_dom">sst_salinity_depth_blom,prescribed</value>
       <value docn_mode="multilev">sst_salinity_depth_blom</value>
+      <value docn_mode="cplhist">cplhist</value>
     </values>
   </entry>
 
@@ -41,7 +42,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,multilev_dom</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,multilev_cplhist</valid_values>
     <desc>
       General method that operates on the data for a given docn_mode.
       ==> dataMode = "sstdata"
@@ -108,9 +109,10 @@
       <value docn_mode="sst_aquap10$">sst_aquap10</value>
       <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_cplhist">multilev_cplhist</value>
       <value docn_mode="multilev_dom">multilev_dom</value>
       <value docn_mode="multilev">multilev</value>
+      <value docn_mode="cplhist">cplhist</value>
     </values>
   </entry>
 
diff --git a/docn/cime_config/stream_definition_docn.xml b/docn/cime_config/stream_definition_docn.xml
index 4e4dd6655..a7081c27c 100644
--- a/docn/cime_config/stream_definition_docn.xml
+++ b/docn/cime_config/stream_definition_docn.xml
@@ -175,6 +175,96 @@
     <stream_readmode>single</stream_readmode>
   </stream_entry>
 
+  <stream_entry name="multilev_cplhist">
+    <stream_meshfile>
+      <meshfile>$OCN_DOMAIN_MESH</meshfile>
+    </stream_meshfile>
+    <stream_datafiles>
+      <file first_year="0" last_year="99999">$DOCN_CPLHIST_DIR/$DOCN_CPLHIST_CASE.cpl.hx.ocn2glc.%y-01-01-00000.nc</file>
+   </stream_datafiles>
+    <stream_datavars>
+      <var>ocnImp_So_s_depth1    So_s_depth1</var>
+      <var>ocnImp_So_s_depth2    So_s_depth2</var>
+      <var>ocnImp_So_s_depth3    So_s_depth3</var>
+      <var>ocnImp_So_s_depth4    So_s_depth4</var>
+      <var>ocnImp_So_s_depth5    So_s_depth5</var>
+      <var>ocnImp_So_s_depth6    So_s_depth6</var>
+      <var>ocnImp_So_s_depth7    So_s_depth7</var>
+      <var>ocnImp_So_s_depth8    So_s_depth8</var>
+      <var>ocnImp_So_s_depth9    So_s_depth9</var>
+      <var>ocnImp_So_s_depth10   So_s_depth10</var>
+      <var>ocnImp_So_s_depth11   So_s_depth11</var>
+      <var>ocnImp_So_s_depth12   So_s_depth12</var>
+      <var>ocnImp_So_s_depth13   So_s_depth13</var>
+      <var>ocnImp_So_s_depth14   So_s_depth14</var>
+      <var>ocnImp_So_s_depth15   So_s_depth15</var>
+      <var>ocnImp_So_s_depth16   So_s_depth16</var>
+      <var>ocnImp_So_s_depth17   So_s_depth17</var>
+      <var>ocnImp_So_s_depth18   So_s_depth18</var>
+      <var>ocnImp_So_s_depth19   So_s_depth19</var>
+      <var>ocnImp_So_s_depth20   So_s_depth20</var>
+      <var>ocnImp_So_s_depth21   So_s_depth21</var>
+      <var>ocnImp_So_s_depth22   So_s_depth22</var>
+      <var>ocnImp_So_s_depth23   So_s_depth23</var>
+      <var>ocnImp_So_s_depth24   So_s_depth24</var>
+      <var>ocnImp_So_s_depth25   So_s_depth25</var>
+      <var>ocnImp_So_s_depth26   So_s_depth26</var>
+      <var>ocnImp_So_s_depth27   So_s_depth27</var>
+      <var>ocnImp_So_s_depth28   So_s_depth28</var>
+      <var>ocnImp_So_s_depth29   So_s_depth29</var>
+      <var>ocnImp_So_s_depth30   So_s_depth30</var>
+      <var>ocnImp_So_t_depth1    So_t_depth1</var>
+      <var>ocnImp_So_t_depth2    So_t_depth2</var>
+      <var>ocnImp_So_t_depth3    So_t_depth3</var>
+      <var>ocnImp_So_t_depth4    So_t_depth4</var>
+      <var>ocnImp_So_t_depth5    So_t_depth5</var>
+      <var>ocnImp_So_t_depth6    So_t_depth6</var>
+      <var>ocnImp_So_t_depth7    So_t_depth7</var>
+      <var>ocnImp_So_t_depth8    So_t_depth8</var>
+      <var>ocnImp_So_t_depth9    So_t_depth9</var>
+      <var>ocnImp_So_t_depth10   So_t_depth10</var>
+      <var>ocnImp_So_t_depth11   So_t_depth11</var>
+      <var>ocnImp_So_t_depth12   So_t_depth12</var>
+      <var>ocnImp_So_t_depth13   So_t_depth13</var>
+      <var>ocnImp_So_t_depth14   So_t_depth14</var>
+      <var>ocnImp_So_t_depth15   So_t_depth15</var>
+      <var>ocnImp_So_t_depth16   So_t_depth16</var>
+      <var>ocnImp_So_t_depth17   So_t_depth17</var>
+      <var>ocnImp_So_t_depth18   So_t_depth18</var>
+      <var>ocnImp_So_t_depth19   So_t_depth19</var>
+      <var>ocnImp_So_t_depth20   So_t_depth20</var>
+      <var>ocnImp_So_t_depth21   So_t_depth21</var>
+      <var>ocnImp_So_t_depth22   So_t_depth22</var>
+      <var>ocnImp_So_t_depth23   So_t_depth23</var>
+      <var>ocnImp_So_t_depth24   So_t_depth24</var>
+      <var>ocnImp_So_t_depth25   So_t_depth25</var>
+      <var>ocnImp_So_t_depth26   So_t_depth26</var>
+      <var>ocnImp_So_t_depth27   So_t_depth27</var>
+      <var>ocnImp_So_t_depth28   So_t_depth28</var>
+      <var>ocnImp_So_t_depth29   So_t_depth29</var>
+      <var>ocnImp_So_t_depth30   So_t_depth30</var>
+    </stream_datavars>
+    <stream_lev_dimname>null</stream_lev_dimname>
+    <stream_mapalgo>
+      <mapalgo>bilinear</mapalgo>
+    </stream_mapalgo>
+    <stream_vectors>null</stream_vectors>
+    <stream_year_align>$DOCN_CPLHIST_YR_ALIGN</stream_year_align>
+    <stream_year_first>$DOCN_CPLHIST_YR_START</stream_year_first>
+    <stream_year_last>$DOCN_CPLHIST_YR_END</stream_year_last>
+    <stream_offset>0</stream_offset>
+    <stream_tintalgo>
+      <tintalgo>nearest</tintalgo>
+    </stream_tintalgo>
+    <stream_taxmode>
+      <taxmode>extend</taxmode>
+    </stream_taxmode>
+    <stream_dtlimit>
+      <dtlimit>1.e30</dtlimit>
+    </stream_dtlimit>
+    <stream_readmode>single</stream_readmode>
+  </stream_entry>
+
   <stream_entry name="cplhist">
     <stream_meshfile>
       <meshfile>$OCN_DOMAIN_MESH</meshfile>
diff --git a/docn/cime_config/testdefs/testlist_docn.xml b/docn/cime_config/testdefs/testlist_docn.xml
index 5c279cabf..ea12a269f 100644
--- a/docn/cime_config/testdefs/testlist_docn.xml
+++ b/docn/cime_config/testdefs/testlist_docn.xml
@@ -28,5 +28,13 @@
       <option name="wallclock"> 00:10:00 </option>
     </options>
   </test>
+  <test compset="1850_SATM_SLND_SICE_DOCN%MULTILEV-CPLHIST_SROF_SGLC_SWAV" grid="f09_tn14" name="SMS_Ly4" testmods="docn/multilev_cplhist">
+    <machines>
+      <machine name="betzy" compiler="intel" category="aux_cdeps_noresm"/>
+    </machines>
+    <options>
+      <option name="wallclock"> 00:10:00 </option>
+    </options>
+  </test>
 
 </testlist>
diff --git a/docn/cime_config/testdefs/testmods_dirs/docn/multilev_cplhist/shell_commands b/docn/cime_config/testdefs/testmods_dirs/docn/multilev_cplhist/shell_commands
new file mode 100644
index 000000000..6c4191f24
--- /dev/null
+++ b/docn/cime_config/testdefs/testmods_dirs/docn/multilev_cplhist/shell_commands
@@ -0,0 +1,9 @@
+./xmlchange DOCN_CPLHIST_CASE=B2G1850_f09_tn14_gl4ais8_coldstart_20250122
+./xmlchange DOCN_CPLHIST_DIR='$DIN_LOC_ROOT/cplhist/noresm3_0/test-dlnd2glc-docn2glc'
+./xmlchange DOCN_CPLHIST_YR_ALIGN=2
+./xmlchange DOCN_CPLHIST_YR_END=6
+./xmlchange DOCN_CPLHIST_YR_START=2
+./xmlchange RUN_STARTDATE=0002-01-01
+./xmlchange ATM_NCPL=1
+./xmlchange ROF_NCPL=1
+./xmlchange NCPL_BASE_PERIOD=year
diff --git a/docn/cime_config/testdefs/testmods_dirs/docn/multilev_cplhist/user_nl_cpl b/docn/cime_config/testdefs/testmods_dirs/docn/multilev_cplhist/user_nl_cpl
new file mode 100644
index 000000000..e31c13784
--- /dev/null
+++ b/docn/cime_config/testdefs/testmods_dirs/docn/multilev_cplhist/user_nl_cpl
@@ -0,0 +1,20 @@
+!------------------------------------------------------------------------
+! Users should ONLY USE user_nl_cpl to change namelists variables
+! for namelist variables in drv_in (except for the ones below) and
+! any keyword/values in seq_maps.rc
+! Users should add ALL user specific namelist and seq_maps.rc changes below
+! using the following syntax
+!   namelist_var = new_namelist_value
+! or
+!   mapname = new_map_name
+! For example to change the default value of ocn2atm_fmapname to 'foo' use
+!   ocn2atm_fmapname =  'foo'
+!
+! Note that some namelist variables MAY NOT be changed in user_nl_cpl -
+! they are defined in a $CASEROOT xml file and must be changed with
+! xmlchange.
+!
+! For example, rather than set username to 'foo' in user_nl_cpl, call
+! ./xmlchange USER=foo
+!------------------------------------------------------------------------
+ocn2glc_coupling = .true.
\ No newline at end of file
diff --git a/docn/docn_datamode_multilev_cplhist_mod.F90 b/docn/docn_datamode_multilev_cplhist_mod.F90
new file mode 100644
index 000000000..663685f10
--- /dev/null
+++ b/docn/docn_datamode_multilev_cplhist_mod.F90
@@ -0,0 +1,166 @@
+module docn_datamode_multilev_cplhist_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_strdata_mod , only : shr_strdata_get_stream_pointer, shr_strdata_type
+  use dshr_dfield_mod  , only : dfield_type, dshr_dfield_add
+
+  implicit none
+  private ! except
+
+  public :: docn_datamode_multilev_cplhist_advertise
+  public :: docn_datamode_multilev_cplhist_init_pointers
+  public :: docn_datamode_multilev_cplhist_advance
+
+  ! 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()
+
+  ! 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._r8 ,  90._r8,  150._r8,  210._r8,  270._r8,  330._r8,  390._r8,  450._r8,  510._r8,  570._r8, &
+        630._r8,  690._r8,  750._r8,  810._r8,  870._r8,  930._r8,  990._r8, 1050._r8, 1110._r8, 1170._r8, &
+       1230._r8, 1290._r8, 1350._r8, 1410._r8, 1470._r8, 1530._r8, 1590._r8, 1650._r8, 1710._r8, 1770._r8 /)
+
+  ! constants
+  character(*) , parameter :: nullstr = 'null'
+  character(*) , parameter :: u_FILE_u = &
+       __FILE__
+
+!===============================================================================
+contains
+!===============================================================================
+
+  subroutine docn_datamode_multilev_cplhist_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)
+
+    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_cplhist_advertise
+
+  !===============================================================================
+  subroutine docn_datamode_multilev_cplhist_init_pointers(dfields, &
+       exportState, sdat, ocn_fraction, logunit, mainproc, rc)
+
+    ! input/output variables
+    type(dfield_type)      , pointer       :: dfields
+    type(ESMF_State)       , intent(inout) :: exportState
+    type(shr_strdata_type) , intent(in)    :: sdat
+    real(r8)               , intent(in)    :: ocn_fraction(:)
+    integer                , intent(in)    :: logunit
+    logical                , intent(in)    :: mainproc
+    integer                , intent(out)   :: rc
+
+    ! local variables
+    integer                     :: n
+    character(len=2)            :: num_str
+    character(CS), allocatable  :: strm_flds_t_depth(:)
+    character(CS), allocatable  :: strm_flds_s_depth(:)
+    character(len=*), parameter :: subname='(docn_init_pointers): '
+    !-------------------------------------------------------------------------------
+
+    rc = ESMF_SUCCESS
+
+    ! Note - docn_datamode_multilev_mod the assumption is that the stream files contain single
+    ! stream fields which contain the full set of levels in the stream data (i.e. 2d)
+    ! Whereas here we are assuming a different stream field for each vertical level
+    ! However, in both cases the export field contains an ungridded dimension for each vertical level
+
+    ! Create stream-> export state mapping
+    ! Note that strm_flds is the model name for the stream field
+    ! Note that state_fld is the model name for the export field
+
+    allocate(strm_flds_t_depth(1:nlev_export))
+    allocate(strm_flds_s_depth(1:nlev_export))
+    do n = 1,nlev_export
+       write(num_str, '(i0)') n
+       strm_flds_t_depth(n) = 'So_t_depth' // trim(num_str)
+       strm_flds_s_depth(n) = 'So_s_depth' // trim(num_str)
+    end do
+
+    ! The following maps stream input multiple fields to export field that has an ungridded dimension
+    call dshr_dfield_add(dfields, sdat, state_fld='So_t_depth', strm_flds=strm_flds_t_depth, state=exportState, &
+         logunit=logunit, mainproc=mainproc, rc=rc)
+    call dshr_dfield_add(dfields, sdat, state_fld='So_s_depth', strm_flds=strm_flds_s_depth, state=exportState, &
+         logunit=logunit, mainproc=mainproc, rc=rc)
+
+    ! Set export state ocean fraction (So_omask)
+    call dshr_state_getfldptr(exportState, 'So_omask', fldptr1=So_omask   , rc=rc)
+    if (chkerr(rc,__LINE__,u_FILE_u)) return
+    So_omask(:) = ocn_fraction(:)
+
+  end subroutine docn_datamode_multilev_cplhist_init_pointers
+
+  !===============================================================================
+  subroutine docn_datamode_multilev_cplhist_advance(exportState, rc)
+
+    use dshr_methods_mod , only : dshr_state_getfldptr
+
+    ! input/output variables
+    type(ESMF_State)       , intent(inout) :: exportState
+    integer                , intent(out)   :: rc
+
+    ! local variables
+    integer           :: idim1,idim2
+    real(r8), pointer :: fldptr2(:,:)
+    character(len=*), parameter :: subname='(docn_datamode_multilev): '
+    !-------------------------------------------------------------------------------
+
+    rc = ESMF_SUCCESS
+
+    call dshr_state_getfldptr(exportState, 'So_t_depth', fldptr2=fldptr2, rc=rc)
+    if (chkerr(rc,__LINE__,u_FILE_u)) return
+    do idim2 = 1,size(fldptr2,dim=2)
+       do idim1 = 1,size(fldptr2,dim=1)
+          if (fldptr2(idim1,idim2) == 0._r8) then
+             fldptr2(idim1,idim2) = 1.e30_r8
+          end if
+       end do
+    end do
+
+    call dshr_state_getfldptr(exportState, 'So_s_depth', fldptr2=fldptr2, rc=rc)
+    if (chkerr(rc,__LINE__,u_FILE_u)) return
+    do idim2 = 1,size(fldptr2,dim=2)
+       do idim1 = 1,size(fldptr2,dim=1)
+          if (fldptr2(idim1,idim2) == 0._r8) then
+             fldptr2(idim1,idim2) = 1.e30_r8
+          end if
+       end do
+    end do
+
+  end subroutine docn_datamode_multilev_cplhist_advance
+
+end module docn_datamode_multilev_cplhist_mod
diff --git a/docn/ocn_comp_nuopc.F90 b/docn/ocn_comp_nuopc.F90
index da612f278..e29c5e8a1 100644
--- a/docn/ocn_comp_nuopc.F90
+++ b/docn/ocn_comp_nuopc.F90
@@ -36,30 +36,33 @@ module cdeps_docn_comp
   use nuopc_shr_methods, only : shr_get_rpointer_name
 
   ! Datamode specialized modules
-  use docn_datamode_copyall_mod    , only : docn_datamode_copyall_advertise
-  use docn_datamode_copyall_mod    , only : docn_datamode_copyall_init_pointers
-  use docn_datamode_copyall_mod    , only : docn_datamode_copyall_advance
-  use docn_datamode_iaf_mod        , only : docn_datamode_iaf_advertise
-  use docn_datamode_iaf_mod        , only : docn_datamode_iaf_init_pointers
-  use docn_datamode_iaf_mod        , only : docn_datamode_iaf_advance
-  use docn_datamode_som_mod        , only : docn_datamode_som_advertise
-  use docn_datamode_som_mod        , only : docn_datamode_som_init_pointers
-  use docn_datamode_som_mod        , only : docn_datamode_som_advance
-  use docn_datamode_som_mod        , only : docn_datamode_som_restart_read
-  use docn_datamode_som_mod        , only : docn_datamode_som_restart_write
-  use docn_datamode_aquaplanet_mod , only : docn_datamode_aquaplanet_advertise
-  use docn_datamode_aquaplanet_mod , only : docn_datamode_aquaplanet_init_pointers
-  use docn_datamode_aquaplanet_mod , only : docn_datamode_aquaplanet_advance
-  use docn_datamode_cplhist_mod    , only : docn_datamode_cplhist_advertise
-  use docn_datamode_cplhist_mod    , only : docn_datamode_cplhist_init_pointers
-  use docn_datamode_cplhist_mod    , only : docn_datamode_cplhist_advance
-  use docn_datamode_multilev_mod   , only : docn_datamode_multilev_advertise
-  use docn_datamode_multilev_mod   , only : docn_datamode_multilev_init_pointers
-  use docn_datamode_multilev_mod   , only : docn_datamode_multilev_advance
-  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_import_data_mod          , only : docn_import_data_advertise
+  use docn_datamode_copyall_mod          , only : docn_datamode_copyall_advertise
+  use docn_datamode_copyall_mod          , only : docn_datamode_copyall_init_pointers
+  use docn_datamode_copyall_mod          , only : docn_datamode_copyall_advance
+  use docn_datamode_iaf_mod              , only : docn_datamode_iaf_advertise
+  use docn_datamode_iaf_mod              , only : docn_datamode_iaf_init_pointers
+  use docn_datamode_iaf_mod              , only : docn_datamode_iaf_advance
+  use docn_datamode_som_mod              , only : docn_datamode_som_advertise
+  use docn_datamode_som_mod              , only : docn_datamode_som_init_pointers
+  use docn_datamode_som_mod              , only : docn_datamode_som_advance
+  use docn_datamode_som_mod              , only : docn_datamode_som_restart_read
+  use docn_datamode_som_mod              , only : docn_datamode_som_restart_write
+  use docn_datamode_aquaplanet_mod       , only : docn_datamode_aquaplanet_advertise
+  use docn_datamode_aquaplanet_mod       , only : docn_datamode_aquaplanet_init_pointers
+  use docn_datamode_aquaplanet_mod       , only : docn_datamode_aquaplanet_advance
+  use docn_datamode_cplhist_mod          , only : docn_datamode_cplhist_advertise
+  use docn_datamode_cplhist_mod          , only : docn_datamode_cplhist_init_pointers
+  use docn_datamode_cplhist_mod          , only : docn_datamode_cplhist_advance
+  use docn_datamode_multilev_cplhist_mod , only : docn_datamode_multilev_cplhist_advertise
+  use docn_datamode_multilev_cplhist_mod , only : docn_datamode_multilev_cplhist_init_pointers
+  use docn_datamode_multilev_cplhist_mod , only : docn_datamode_multilev_cplhist_advance
+  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_mod         , only : docn_datamode_multilev_advertise
+  use docn_datamode_multilev_mod         , only : docn_datamode_multilev_init_pointers
+  use docn_datamode_multilev_mod         , only : docn_datamode_multilev_advance
+  use docn_import_data_mod               , only : docn_import_data_advertise
 
   implicit none
   private ! except
@@ -304,6 +307,7 @@ 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_cplhist'   .or. & ! multilevel ocean input
          trim(datamode) == 'multilev'           .or. & ! multilevel ocean input
          trim(datamode) == 'multilev_dom') then        ! multilevel ocean input and sst export
        ! success do nothing
@@ -332,6 +336,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_cplhist') then
+       call docn_datamode_multilev_cplhist_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
@@ -543,34 +550,50 @@ subroutine docn_comp_run(gcomp, importState, exportState, clock, target_ymd, tar
 
     if (first_time) then
 
-       ! Initialize dfields
-       call docn_init_dfields(importState, exportState, rc=rc)
-       if (ChkErr(rc,__LINE__,u_FILE_u)) return
-
-       ! Initialize datamode module ponters
+       ! Initialize datamode module pointers
        select case (trim(datamode))
        case('sstdata', 'sst_aquap_file')
           call docn_datamode_copyall_init_pointers(exportState, model_frac, rc)
           if (ChkErr(rc,__LINE__,u_FILE_u)) return
+          call docn_init_dfields(importState, exportState, rc=rc)
+          if (ChkErr(rc,__LINE__,u_FILE_u)) return
        case('iaf')
           call docn_datamode_iaf_init_pointers(importState, exportState, model_frac, rc)
           if (ChkErr(rc,__LINE__,u_FILE_u)) return
+          call docn_init_dfields(importState, exportState, rc=rc)
+          if (ChkErr(rc,__LINE__,u_FILE_u)) return
        case('som', 'som_aquap')
           call docn_datamode_som_init_pointers(importState, exportState, sdat, model_frac, rc)
           if (ChkErr(rc,__LINE__,u_FILE_u)) return
+          call docn_init_dfields(importState, exportState, rc=rc)
+          if (ChkErr(rc,__LINE__,u_FILE_u)) return
        case('sst_aquap_analytic', 'sst_aquap_constant')
           skip_restart_read=.true.
           call  docn_datamode_aquaplanet_init_pointers(exportState, model_frac, rc)
           if (ChkErr(rc,__LINE__,u_FILE_u)) return
+          call docn_init_dfields(importState, exportState, rc=rc)
+          if (ChkErr(rc,__LINE__,u_FILE_u)) return
        case('cplhist')
           call docn_datamode_cplhist_init_pointers(exportState, model_frac, rc)
           if (ChkErr(rc,__LINE__,u_FILE_u)) return
+          call docn_init_dfields(importState, exportState, rc=rc)
+          if (ChkErr(rc,__LINE__,u_FILE_u)) return
        case('multilev')
           call docn_datamode_multilev_init_pointers(exportState, sdat,  model_frac, rc)
           if (ChkErr(rc,__LINE__,u_FILE_u)) return
+          call docn_init_dfields(importState, exportState, rc=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
+          call docn_init_dfields(importState, exportState, rc=rc)
+          if (ChkErr(rc,__LINE__,u_FILE_u)) return
+       case('multilev_cplhist')
+          call docn_datamode_multilev_cplhist_init_pointers(dfields, &
+               exportState, sdat,  model_frac, logunit, mainproc, rc)
+          if (ChkErr(rc,__LINE__,u_FILE_u)) return
+          ! Note that there is no call to docn_init_dfields since the
+          ! initialization of dfields is done in the above routine
        end select
 
        ! Read restart if needed
@@ -579,7 +602,7 @@ subroutine docn_comp_run(gcomp, importState, exportState, clock, target_ymd, tar
           if (ChkErr(rc,__LINE__,u_FILE_u)) return
 
           select case (trim(datamode))
-          case('sstdata', 'sst_aquap_file', 'iaf', 'cplhist', 'multilev', 'mulitilev_dom')
+          case('sstdata', 'sst_aquap_file', 'iaf', 'cplhist', 'multilev', 'mulitilev_dom', 'multilev_cplhist')
              call dshr_restart_read(restfilm, rpfile, logunit, my_task, mpicom, sdat, rc)
              if (ChkErr(rc,__LINE__,u_FILE_u)) return
           case('som', 'som_aquap')
@@ -604,7 +627,7 @@ subroutine docn_comp_run(gcomp, importState, exportState, clock, target_ymd, tar
     ! Copy all fields from streams to export state as default
     ! This automatically will update the fields in the export state
     call ESMF_TraceRegionEnter('docn_dfield_copy')
-    if(.not. aquaplanet) then
+    if (.not. aquaplanet) then
        call dshr_dfield_copy(dfields, sdat, rc)
        if (ChkErr(rc,__LINE__,u_FILE_u)) return
     endif
@@ -636,20 +659,23 @@ subroutine docn_comp_run(gcomp, importState, exportState, clock, target_ymd, tar
     case('multilev_dom')
        call  docn_datamode_multilev_dom_advance(sdat, logunit, mainproc, rc=rc)
        if (ChkErr(rc,__LINE__,u_FILE_u)) return
+    case('multilev_cplhist')
+       call  docn_datamode_multilev_cplhist_advance(exportState, 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)
     if (restart_write) then
-          call shr_get_rpointer_name(gcomp, 'ocn', target_ymd, target_tod, rpfile, 'write', rc)
-          if (ChkErr(rc,__LINE__,u_FILE_u)) return
+       call shr_get_rpointer_name(gcomp, 'ocn', target_ymd, target_tod, rpfile, 'write', rc)
+       if (ChkErr(rc,__LINE__,u_FILE_u)) return
 
-          select case (trim(datamode))
-          case('sstdata', 'sst_aquap_file', 'iaf', 'cplhist', 'multilev', 'mulitilev_dom')
-             call dshr_restart_write(rpfile, case_name, 'docn', inst_suffix, target_ymd, target_tod, logunit, &
-                  my_task, sdat, rc)
-             if (ChkErr(rc,__LINE__,u_FILE_u)) return
-          case('som', 'som_aquap')
-             call docn_datamode_som_restart_write(rpfile, case_name, inst_suffix, target_ymd, target_tod, &
+       select case (trim(datamode))
+       case('sstdata', 'sst_aquap_file', 'iaf', 'cplhist', 'multilev', 'mulitilev_dom', 'multilev_cplhist')
+          call dshr_restart_write(rpfile, case_name, 'docn', inst_suffix, target_ymd, target_tod, logunit, &
+               my_task, sdat, rc)
+          if (ChkErr(rc,__LINE__,u_FILE_u)) return
+       case('som', 'som_aquap')
+          call docn_datamode_som_restart_write(rpfile, case_name, inst_suffix, target_ymd, target_tod, &
                logunit, my_task, sdat)
           case('sst_aquap_analytic', 'sst_aquap_constant')
              ! Do nothing
@@ -657,7 +683,7 @@ subroutine docn_comp_run(gcomp, importState, exportState, clock, target_ymd, tar
              call shr_log_error(subName//'datamode '//trim(datamode)//' not recognized', rc=rc)
              return
           end select
-          
+
        endif
 
     call ESMF_TraceRegionExit('DOCN_RUN')
diff --git a/drof/cime_config/config_component.xml b/drof/cime_config/config_component.xml
index 1db777be7..de0919cd7 100644
--- a/drof/cime_config/config_component.xml
+++ b/drof/cime_config/config_component.xml
@@ -13,7 +13,7 @@
   -->
 
   <description modifier_mode="1">
-    <desc rof="DROF[%NULL][%NYF][%IAF][%IAFAIS00][%IAFAIS45][%IAFAIS55][%CPLHIST][%JRA][%JRA-1p4-2018][%JRA-1p4-2018-AIS0ICE][%JRA-1p4-2018-AIS0LIQ][%JRA-1p4-2018-AIS0ROF][%JRA-1p5-2023][%JRA-RYF8485][%JRA-RYF9091][%JRA-RYF0304]">Data runoff model</desc>
+    <desc rof="DROF[%NULL][%NYF][%IAF][%IAFAIS00][%IAFAIS45][%IAFAIS55][%CPLHIST][%JRA][%JRA-1p4-2018][%JRA-1p4-2018-AIS0ICE][%JRA-1p4-2018-AIS0LIQ][%JRA-1p4-2018-AIS0ROF][%JRA-RYF8485][%JRA-RYF9091][%JRA-RYF0304]">Data runoff model</desc>
     <desc option="NULL"     >NULL mode</desc>
     <desc option="NYF"      >COREv2 normal year forcing:</desc>
     <desc option="IAF"      >COREv2 interannual year forcing:</desc>
@@ -25,7 +25,6 @@
     <desc option="JRA-1p4-2018-AIS0ICE">JRA55 interannual forcing, v1.4, through 2018, no rofi around AIS</desc>
     <desc option="JRA-1p4-2018-AIS0LIQ">JRA55 interannual forcing, v1.4, through 2018, no rofl around AIS</desc>
     <desc option="JRA-1p4-2018-AIS0ROF">JRA55 interannual forcing, v1.4, through 2018, no rofi or rofl around AIS</desc>
-    <desc option="JRA-1p5-2023">JRA55 interannual forcing, v1.5, through 2023</desc>
     <desc option="JRA"      >JRA55 interannual forcing</desc>
     <desc option="JRA-RYF8485">JRA55 Repeat Year Forcing v1.3 1984-1985</desc>
     <desc option="JRA-RYF9091">JRA55 Repeat Year Forcing v1.3 1990-1991</desc>
@@ -43,7 +42,7 @@
 
   <entry id="DROF_MODE">
     <type>char</type>
-    <valid_values>CPLHIST,DIATREN_ANN_RX1,DIATREN_IAF_RX1,DIATREN_IAF_AIS00_RX1,DIATREN_IAF_AIS45_RX1,DIATREN_IAF_AIS55_RX1,IAF_JRA,IAF_JRA_1p4_2018,IAF_JRA_1p4_2018_AIS0ICE,IAF_JRA_1p4_2018_AIS0LIQ,IAF_JRA_1p4_2018_AIS0ROF,IAF_JRA_1p5_2023,RYF8485_JRA,RYF9091_JRA,RYF0304_JRA,NULL</valid_values>
+    <valid_values>CPLHIST,DIATREN_ANN_RX1,DIATREN_IAF_RX1,DIATREN_IAF_AIS00_RX1,DIATREN_IAF_AIS45_RX1,DIATREN_IAF_AIS55_RX1,IAF_JRA,IAF_JRA_1p4_2018,IAF_JRA_1p4_2018_AIS0ICE,IAF_JRA_1p4_2018_AIS0LIQ,IAF_JRA_1p4_2018_AIS0ROF,RYF8485_JRA,RYF9091_JRA,RYF0304_JRA,NULL</valid_values>
     <default_value>DIATREN_ANN_RX1</default_value>
     <values match="last">
       <value compset="_DROF%NULL">NULL</value>
@@ -61,7 +60,6 @@
       <value compset="_DROF%JRA-1p4-2018-AIS0ICE" >IAF_JRA_1p4_2018_AIS0ICE</value>
       <value compset="_DROF%JRA-1p4-2018-AIS0LIQ" >IAF_JRA_1p4_2018_AIS0LIQ</value>
       <value compset="_DROF%JRA-1p4-2018-AIS0ROF" >IAF_JRA_1p4_2018_AIS0ROF</value>
-      <value compset="_DROF%JRA-1p5-2023" >IAF_JRA_1p5_2023</value>
       <value compset="_DROF%JRA-RYF8485" >RYF8485_JRA</value>
       <value compset="_DROF%JRA-RYF9091" >RYF9091_JRA</value>
       <value compset="_DROF%JRA-RYF0304" >RYF0304_JRA</value>
@@ -79,19 +77,28 @@
     default is DIATREN_ANN_RX1.</desc>
   </entry>
 
+  <entry id="DROF_CPLHIST_DIR">
+    <type>char</type>
+    <valid_values></valid_values>
+    <default_value>UNSET</default_value>
+    <group>run_component_drof</group>
+    <file>env_run.xml</file>
+    <desc>directory for coupler history data mode when DROF_MODE is CPLHIST</desc>
+  </entry>
+
   <entry id="DROF_CPLHIST_CASE">
     <type>char</type>
     <valid_values></valid_values>
     <default_value>UNSET</default_value>
     <group>run_component_drof</group>
     <file>env_run.xml</file>
-    <desc>case name for coupler history data mode (only used when DROF_MODE is CPLHIST mode)</desc>
+    <desc>case name for coupler history data mode when DROF_MODE is CPLHIST mode</desc>
   </entry>
 
   <entry id="DROF_CPLHIST_YR_ALIGN">
     <type>integer</type>
     <valid_values></valid_values>
-    <default_value>-999</default_value>
+    <default_value>1</default_value>
     <group>run_component_drof</group>
     <file>env_run.xml</file>
     <desc>
@@ -112,7 +119,7 @@
   <entry id="DROF_CPLHIST_YR_START">
     <type>integer</type>
     <valid_values></valid_values>
-    <default_value>-999</default_value>
+    <default_value>1</default_value>
     <group>run_component_drof</group>
     <file>env_run.xml</file>
     <desc>starting year to loop data over (only used when DROF_MODE is CPLHIST)</desc>
@@ -121,7 +128,7 @@
   <entry id="DROF_CPLHIST_YR_END">
     <type>integer</type>
     <valid_values></valid_values>
-    <default_value>-999</default_value>
+    <default_value>1</default_value>
     <group>run_component_drof</group>
     <file>env_run.xml</file>
     <desc>ending year to loop data over (only used when DROF_MODE is CPLHIST)</desc>
diff --git a/drof/cime_config/stream_definition_drof.xml b/drof/cime_config/stream_definition_drof.xml
index 1c87e690b..375b3f9d5 100644
--- a/drof/cime_config/stream_definition_drof.xml
+++ b/drof/cime_config/stream_definition_drof.xml
@@ -475,38 +475,6 @@
     <stream_readmode>single</stream_readmode>
   </stream_entry>
 
-  <stream_entry name="rof.iaf_jra_1p5_2023">
-    <stream_meshfile>
-      <meshfile>$DIN_LOC_ROOT/lnd/dlnd7/JRA55/JRA.v1.4.runoff.1958_ESMFmesh_cdf5_20201020.nc</meshfile>
-    </stream_meshfile>
-    <stream_datafiles>
-      <file first_year="1958" last_year="2023">$DIN_LOC_ROOT/ocn/jra55/v1.5_noleap/JRA.v1.5.runoff.%y.240411.nc</file>
-    </stream_datafiles>
-    <stream_datavars>
-      <var>rofl Forr_rofl</var>
-      <var>rofi Forr_rofi</var>
-    </stream_datavars>
-    <stream_lev_dimname>null</stream_lev_dimname>
-    <stream_mapalgo>
-      <mapalgo>bilinear</mapalgo>
-    </stream_mapalgo>
-    <stream_vectors>null</stream_vectors>
-    <stream_year_align>1</stream_year_align>
-    <stream_year_first>1958</stream_year_first>
-    <stream_year_last>2023</stream_year_last>
-    <stream_offset>0</stream_offset>
-    <stream_tintalgo>
-      <tintalgo>upper</tintalgo>
-    </stream_tintalgo>
-    <stream_taxmode>
-      <taxmode>cycle</taxmode>
-    </stream_taxmode>
-    <stream_dtlimit>
-      <dtlimit>3.0</dtlimit>
-    </stream_dtlimit>
-    <stream_readmode>single</stream_readmode>
-  </stream_entry>
-
   <stream_entry name="rof.ryf8485_jra">
     <stream_meshfile>
       <meshfile>$DIN_LOC_ROOT/lnd/dlnd7/JRA55/JRA.v1.4.runoff.1958_ESMFmesh_cdf5_20201020.nc</meshfile>
@@ -608,7 +576,7 @@
       <meshfile>$ROF_DOMAIN_MESH</meshfile>
     </stream_meshfile>
     <stream_datafiles>
-      <file>$DIN_LOC_ROOT/lnd/dlnd7/RX1/runoff.daitren.iaf.20120419.nc</file>
+      <file first_year="$DROF_CPLHIST_YR_START" last_year="$DROF_CPLHIST_YR_END">$DROF_CPLHIST_DIR/$DROF_CPLHIST_CASE.cpl.hx.rof.24h.avrg.%ymd-00000.nc</file>
     </stream_datafiles>
     <stream_datavars>
       <var>rofImp_Forr_rofl  Forr_rofl</var>
diff --git a/dshr/dshr_dfield_mod.F90 b/dshr/dshr_dfield_mod.F90
index bbd411572..d29e5a7c1 100644
--- a/dshr/dshr_dfield_mod.F90
+++ b/dshr/dshr_dfield_mod.F90
@@ -85,9 +85,9 @@ subroutine dshr_dfield_add_1d(dfields, sdat, state_fld, strm_fld, state, logunit
     dfield_new%stream_index = iunset
     dfield_new%fldbun_index = iunset
 
-    ! loop over all input streams and ! determine if the strm_fld is in the attribute vector of stream ns
+    ! loop over all input streams
     ! if strm_fld is in the field bundle of stream ns, set the field index of the field with the name strm_fld
-    ! and set the index of the stream
+    ! colon delimited string and set the index of the stream
 
     ! loop over all input streams and ! determine if the strm_fld is in the attribute vector of stream ns
     do ns = 1, shr_strdata_get_stream_count(sdat)


Reviews:
user: login: gold2718
body: Approving but please deallocate the strrm_flds_xxx arrays after using them.
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2024-11-28T20:34:14Z
user: login: gold2718
body: Better but please fix a few minor things.
state: CHANGES_REQUESTED
author_association: COLLABORATOR
submitted_at: 2025-04-11T17:00:09Z
user: login: mvertens
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-11T17:06:46Z
user: login: mvertens
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-11T17:06:53Z
user: login: mvertens
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-11T17:07:03Z
user: login: mvertens
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-11T17:08:24Z
user: login: mvertens
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-11T17:11:18Z
user: login: mvertens
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-11T17:12:14Z
user: login: mvertens
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-11T17:12:22Z
user: login: mvertens
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-11T17:12:35Z
user: login: gold2718
body: All looks good now, thanks!
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-04-11T18:00:36Z
user: login: gold2718
body: Thanks for adding tests!
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-04-13T20:54:26Z

Review comments:
diff_hunk: @@ -532,28 +535,35 @@ subroutine dlnd_comp_run(importState, exportState, target_ymd, target_tod, rc)
        ! Create stream-> export state mapping
        ! Note that strm_flds is the model name for the stream field
        ! Note that state_fld is the model name for the export field
-       allocate(strm_flds(0:glc_nec))
-       do n = 0,glc_nec
-          nec_str = glc_elevclass_as_string(n)
-          strm_flds(n) = 'Sl_tsrf_elev' // trim(nec_str)
-       end do
-       call dshr_dfield_add(dfields, sdat, state_fld='Sl_tsrf_elev', strm_flds=strm_flds, state=exportState, &
+       if (trim(datamode) == 'glc_forcing_mct' .or. trim(datamode) == 'glc_forcing' ) then
+          allocate(strm_flds_tsrf(1:glc_nec+1))
+          allocate(strm_flds_topo(1:glc_nec+1))
+          allocate(strm_flds_qice(1:glc_nec+1))
path: dlnd/lnd_comp_nuopc.F90
user: login: gold2718
body: Please deallocate these when they are no longer needed (between lines 570 and 571).
created_at: 2024-11-28T20:30:34Z
author_association: COLLABORATOR
diff_hunk: @@ -594,6 +600,27 @@ subroutine dlnd_comp_run(importState, exportState, target_ymd, target_tod, rc)
        ! do nothing extra
     end select
 
+    ! Set special value over masked points
+    if (trim(datamode) == 'glc_forcing_mct' .or. trim(datamode) == 'glc_forcing' ) then
+       call dshr_state_getfldptr(exportState, 'Sl_tsrf_elev', fldptr2=fldptr2, rc=rc)
+       if (chkerr(rc,__LINE__,u_FILE_u)) return
+       do n = 1,size(fldptr2,dim=2)
+          if (lfrac(n) == 0.) fldptr2(:,n) = 1.e30_r8
path: dlnd/lnd_comp_nuopc.F90
user: login: gold2718
body: Constants should have the proper type:
```suggestion
          if (lfrac(n) == 0._r8) fldptr2(:,n) = 1.e30_r8
```
created_at: 2025-04-11T13:40:21Z
author_association: COLLABORATOR
diff_hunk: @@ -594,6 +600,27 @@ subroutine dlnd_comp_run(importState, exportState, target_ymd, target_tod, rc)
        ! do nothing extra
     end select
 
+    ! Set special value over masked points
+    if (trim(datamode) == 'glc_forcing_mct' .or. trim(datamode) == 'glc_forcing' ) then
+       call dshr_state_getfldptr(exportState, 'Sl_tsrf_elev', fldptr2=fldptr2, rc=rc)
+       if (chkerr(rc,__LINE__,u_FILE_u)) return
+       do n = 1,size(fldptr2,dim=2)
+          if (lfrac(n) == 0.) fldptr2(:,n) = 1.e30_r8
+       end do
+
+       call dshr_state_getfldptr(exportState, 'Sl_topo_elev', fldptr2=fldptr2, rc=rc)
+       if (chkerr(rc,__LINE__,u_FILE_u)) return
+       do n = 1,size(fldptr2,dim=2)
+          if (lfrac(n) == 0.) fldptr2(:,n) = 1.e30_r8
path: dlnd/lnd_comp_nuopc.F90
user: login: gold2718
body: Constants should have the proper type:
```suggestion
          if (lfrac(n) == 0._r8) fldptr2(:,n) = 1.e30_r8
```
created_at: 2025-04-11T13:40:54Z
author_association: COLLABORATOR
diff_hunk: @@ -594,6 +600,27 @@ subroutine dlnd_comp_run(importState, exportState, target_ymd, target_tod, rc)
        ! do nothing extra
     end select
 
+    ! Set special value over masked points
+    if (trim(datamode) == 'glc_forcing_mct' .or. trim(datamode) == 'glc_forcing' ) then
+       call dshr_state_getfldptr(exportState, 'Sl_tsrf_elev', fldptr2=fldptr2, rc=rc)
+       if (chkerr(rc,__LINE__,u_FILE_u)) return
+       do n = 1,size(fldptr2,dim=2)
+          if (lfrac(n) == 0.) fldptr2(:,n) = 1.e30_r8
+       end do
+
+       call dshr_state_getfldptr(exportState, 'Sl_topo_elev', fldptr2=fldptr2, rc=rc)
+       if (chkerr(rc,__LINE__,u_FILE_u)) return
+       do n = 1,size(fldptr2,dim=2)
+          if (lfrac(n) == 0.) fldptr2(:,n) = 1.e30_r8
+       end do
+
+       call dshr_state_getfldptr(exportState, 'Flgl_qice_elev', fldptr2=fldptr2, rc=rc)
+       if (chkerr(rc,__LINE__,u_FILE_u)) return
+       do n = 1,size(fldptr2,dim=2)
+          if (lfrac(n) == 0.) fldptr2(:,n) = 1.e30_r8
path: dlnd/lnd_comp_nuopc.F90
user: login: gold2718
body: Constants should have the proper type:
```suggestion
          if (lfrac(n) == 0._r8) fldptr2(:,n) = 1.e30_r8
```
created_at: 2025-04-11T13:41:10Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,170 @@
+module docn_datamode_multilev_cplhist_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_strdata_mod , only : shr_strdata_get_stream_pointer, shr_strdata_type
+  use dshr_dfield_mod  , only : dfield_type, dshr_dfield_add
+
+  implicit none
+  private ! except
+
+  public :: docn_datamode_multilev_cplhist_advertise
+  public :: docn_datamode_multilev_cplhist_init_pointers
+  public :: docn_datamode_multilev_cplhist_advance
+
+  ! 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()
+
+  ! 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. /)
+
+  ! constants
+  character(*) , parameter :: nullstr = 'null'
+  character(*) , parameter :: u_FILE_u = &
+       __FILE__
+
+!===============================================================================
+contains
+!===============================================================================
+
+  subroutine docn_datamode_multilev_cplhist_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)
+
+    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_cplhist_advertise
+
+  !===============================================================================
+  subroutine docn_datamode_multilev_cplhist_init_pointers(dfields, &
+       exportState, sdat, ocn_fraction, logunit, mainproc, rc)
+
+    ! input/output variables
+    type(dfield_type)      , pointer       :: dfields
+    type(ESMF_State)       , intent(inout) :: exportState
+    type(shr_strdata_type) , intent(in)    :: sdat
+    real(r8)               , intent(in)    :: ocn_fraction(:)
+    integer                , intent(in)    :: logunit
+    logical                , intent(in)    :: mainproc
+    integer                , intent(out)   :: rc
+
+    ! local variables
+    integer                     :: n
+    character(len=2)            :: num_str
+    character(CS), allocatable  :: strm_flds_t_depth(:)
+    character(CS), allocatable  :: strm_flds_s_depth(:)
+    character(len=*), parameter :: subname='(docn_init_pointers): '
+    !-------------------------------------------------------------------------------
+
+    rc = ESMF_SUCCESS
+
+    ! Note - docn_datamode_multilev_mod the assumption is that the stream files contain single
+    ! stream fields which contain the full set of levels in the stream data (i.e. 2d)
+    ! Whereas here we are assuming a different stream field for each vertical level
+    ! However, in both cases the export field contains an ungridded dimension for each vertical level
+
+    ! Create stream-> export state mapping
+    ! Note that strm_flds is the model name for the stream field
+    ! Note that state_fld is the model name for the export field
+
+    allocate(strm_flds_t_depth(1:nlev_export))
+    allocate(strm_flds_s_depth(1:nlev_export))
+    do n = 1,nlev_export
+       if (n < 10) then
+          write(num_str, '(i1.1)') n
+       else
+          write(num_str, '(i2.2)') n
+       end if
path: docn/docn_datamode_multilev_cplhist_mod.F90
user: login: gold2718
body: Can this block be just:
```suggestion
       write(num_str, '(i0)') n
```
created_at: 2025-04-11T15:29:57Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,170 @@
+module docn_datamode_multilev_cplhist_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_strdata_mod , only : shr_strdata_get_stream_pointer, shr_strdata_type
+  use dshr_dfield_mod  , only : dfield_type, dshr_dfield_add
+
+  implicit none
+  private ! except
+
+  public :: docn_datamode_multilev_cplhist_advertise
+  public :: docn_datamode_multilev_cplhist_init_pointers
+  public :: docn_datamode_multilev_cplhist_advance
+
+  ! 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()
+
+  ! 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. /)
path: docn/docn_datamode_multilev_cplhist_mod.F90
user: login: gold2718
body: These should all have kind:
```suggestion
  real(r8) :: vertical_levels(nlev_export) = (/  &
       30._r8, 90._r8, 150._r8, 210._r8, 270._r8, 330._r8, 390._r8, 450._r8, 510._r8, 570._r8, &
       630._r8, 690._r8, 750._r8, 810._r8, 870._r8, 930._r8, 990._r8, 1050._r8, 1110._r8, 1170._r8, &
       1230._r8, 1290._r8, 1350._r8, 1410._r8, 1470._r8, 1530._r8, 1590._r8, 1650._r8, 1710._r8, 1770._r8 /)
```
created_at: 2025-04-11T15:32:49Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,170 @@
+module docn_datamode_multilev_cplhist_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_strdata_mod , only : shr_strdata_get_stream_pointer, shr_strdata_type
+  use dshr_dfield_mod  , only : dfield_type, dshr_dfield_add
+
+  implicit none
+  private ! except
+
+  public :: docn_datamode_multilev_cplhist_advertise
+  public :: docn_datamode_multilev_cplhist_init_pointers
+  public :: docn_datamode_multilev_cplhist_advance
+
+  ! 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()
+
+  ! 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. /)
+
+  ! constants
+  character(*) , parameter :: nullstr = 'null'
+  character(*) , parameter :: u_FILE_u = &
+       __FILE__
+
+!===============================================================================
+contains
+!===============================================================================
+
+  subroutine docn_datamode_multilev_cplhist_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)
+
+    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_cplhist_advertise
+
+  !===============================================================================
+  subroutine docn_datamode_multilev_cplhist_init_pointers(dfields, &
+       exportState, sdat, ocn_fraction, logunit, mainproc, rc)
+
+    ! input/output variables
+    type(dfield_type)      , pointer       :: dfields
+    type(ESMF_State)       , intent(inout) :: exportState
+    type(shr_strdata_type) , intent(in)    :: sdat
+    real(r8)               , intent(in)    :: ocn_fraction(:)
+    integer                , intent(in)    :: logunit
+    logical                , intent(in)    :: mainproc
+    integer                , intent(out)   :: rc
+
+    ! local variables
+    integer                     :: n
+    character(len=2)            :: num_str
+    character(CS), allocatable  :: strm_flds_t_depth(:)
+    character(CS), allocatable  :: strm_flds_s_depth(:)
+    character(len=*), parameter :: subname='(docn_init_pointers): '
+    !-------------------------------------------------------------------------------
+
+    rc = ESMF_SUCCESS
+
+    ! Note - docn_datamode_multilev_mod the assumption is that the stream files contain single
+    ! stream fields which contain the full set of levels in the stream data (i.e. 2d)
+    ! Whereas here we are assuming a different stream field for each vertical level
+    ! However, in both cases the export field contains an ungridded dimension for each vertical level
+
+    ! Create stream-> export state mapping
+    ! Note that strm_flds is the model name for the stream field
+    ! Note that state_fld is the model name for the export field
+
+    allocate(strm_flds_t_depth(1:nlev_export))
+    allocate(strm_flds_s_depth(1:nlev_export))
+    do n = 1,nlev_export
+       if (n < 10) then
+          write(num_str, '(i1.1)') n
+       else
+          write(num_str, '(i2.2)') n
+       end if
+       strm_flds_t_depth(n) = 'So_t_depth' // trim(num_str)
+       strm_flds_s_depth(n) = 'So_s_depth' // trim(num_str)
+    end do
+
+    ! The following maps stream input multiple fields to export field that has an ungridded dimension
+    call dshr_dfield_add(dfields, sdat, state_fld='So_t_depth', strm_flds=strm_flds_t_depth, state=exportState, &
+         logunit=logunit, mainproc=mainproc, rc=rc)
+    call dshr_dfield_add(dfields, sdat, state_fld='So_s_depth', strm_flds=strm_flds_s_depth, state=exportState, &
+         logunit=logunit, mainproc=mainproc, rc=rc)
+
+    ! Set export state ocean fraction (So_omask)
+    call dshr_state_getfldptr(exportState, 'So_omask', fldptr1=So_omask   , rc=rc)
+    if (chkerr(rc,__LINE__,u_FILE_u)) return
+    So_omask(:) = ocn_fraction(:)
+
+  end subroutine docn_datamode_multilev_cplhist_init_pointers
+
+  !===============================================================================
+  subroutine docn_datamode_multilev_cplhist_advance(exportState, rc)
+
+    use dshr_methods_mod , only : dshr_state_getfldptr
+
+    ! input/output variables
+    type(ESMF_State)       , intent(inout) :: exportState
+    integer                , intent(out)   :: rc
+
+    ! local variables
+    integer           :: idim1,idim2
+    real(r8), pointer :: fldptr2(:,:)
+    character(len=*), parameter :: subname='(docn_datamode_multilev): '
+    !-------------------------------------------------------------------------------
+
+    rc = ESMF_SUCCESS
+
+    call dshr_state_getfldptr(exportState, 'So_t_depth', fldptr2=fldptr2, rc=rc)
+    if (chkerr(rc,__LINE__,u_FILE_u)) return
+    do idim2 = 1,size(fldptr2,dim=2)
+       do idim1 = 1,size(fldptr2,dim=1)
+          if (fldptr2(idim1,idim2) == 0.) then
+             fldptr2(idim1,idim2) = 1.e30_r8
+          end if
+       end do
+    end do
+
+    call dshr_state_getfldptr(exportState, 'So_s_depth', fldptr2=fldptr2, rc=rc)
+    if (chkerr(rc,__LINE__,u_FILE_u)) return
+    do idim2 = 1,size(fldptr2,dim=2)
+       do idim1 = 1,size(fldptr2,dim=1)
+          if (fldptr2(idim1,idim2) == 0.) then
path: docn/docn_datamode_multilev_cplhist_mod.F90
user: login: gold2718
body: Constant should have kind:
```suggestion
          if (fldptr2(idim1,idim2) == 0._r8) then
```
created_at: 2025-04-11T16:56:15Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,170 @@
+module docn_datamode_multilev_cplhist_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_strdata_mod , only : shr_strdata_get_stream_pointer, shr_strdata_type
+  use dshr_dfield_mod  , only : dfield_type, dshr_dfield_add
+
+  implicit none
+  private ! except
+
+  public :: docn_datamode_multilev_cplhist_advertise
+  public :: docn_datamode_multilev_cplhist_init_pointers
+  public :: docn_datamode_multilev_cplhist_advance
+
+  ! 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()
+
+  ! 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. /)
+
+  ! constants
+  character(*) , parameter :: nullstr = 'null'
+  character(*) , parameter :: u_FILE_u = &
+       __FILE__
+
+!===============================================================================
+contains
+!===============================================================================
+
+  subroutine docn_datamode_multilev_cplhist_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)
+
+    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_cplhist_advertise
+
+  !===============================================================================
+  subroutine docn_datamode_multilev_cplhist_init_pointers(dfields, &
+       exportState, sdat, ocn_fraction, logunit, mainproc, rc)
+
+    ! input/output variables
+    type(dfield_type)      , pointer       :: dfields
+    type(ESMF_State)       , intent(inout) :: exportState
+    type(shr_strdata_type) , intent(in)    :: sdat
+    real(r8)               , intent(in)    :: ocn_fraction(:)
+    integer                , intent(in)    :: logunit
+    logical                , intent(in)    :: mainproc
+    integer                , intent(out)   :: rc
+
+    ! local variables
+    integer                     :: n
+    character(len=2)            :: num_str
+    character(CS), allocatable  :: strm_flds_t_depth(:)
+    character(CS), allocatable  :: strm_flds_s_depth(:)
+    character(len=*), parameter :: subname='(docn_init_pointers): '
+    !-------------------------------------------------------------------------------
+
+    rc = ESMF_SUCCESS
+
+    ! Note - docn_datamode_multilev_mod the assumption is that the stream files contain single
+    ! stream fields which contain the full set of levels in the stream data (i.e. 2d)
+    ! Whereas here we are assuming a different stream field for each vertical level
+    ! However, in both cases the export field contains an ungridded dimension for each vertical level
+
+    ! Create stream-> export state mapping
+    ! Note that strm_flds is the model name for the stream field
+    ! Note that state_fld is the model name for the export field
+
+    allocate(strm_flds_t_depth(1:nlev_export))
+    allocate(strm_flds_s_depth(1:nlev_export))
+    do n = 1,nlev_export
+       if (n < 10) then
+          write(num_str, '(i1.1)') n
+       else
+          write(num_str, '(i2.2)') n
+       end if
+       strm_flds_t_depth(n) = 'So_t_depth' // trim(num_str)
+       strm_flds_s_depth(n) = 'So_s_depth' // trim(num_str)
+    end do
+
+    ! The following maps stream input multiple fields to export field that has an ungridded dimension
+    call dshr_dfield_add(dfields, sdat, state_fld='So_t_depth', strm_flds=strm_flds_t_depth, state=exportState, &
+         logunit=logunit, mainproc=mainproc, rc=rc)
+    call dshr_dfield_add(dfields, sdat, state_fld='So_s_depth', strm_flds=strm_flds_s_depth, state=exportState, &
+         logunit=logunit, mainproc=mainproc, rc=rc)
+
+    ! Set export state ocean fraction (So_omask)
+    call dshr_state_getfldptr(exportState, 'So_omask', fldptr1=So_omask   , rc=rc)
+    if (chkerr(rc,__LINE__,u_FILE_u)) return
+    So_omask(:) = ocn_fraction(:)
+
+  end subroutine docn_datamode_multilev_cplhist_init_pointers
+
+  !===============================================================================
+  subroutine docn_datamode_multilev_cplhist_advance(exportState, rc)
+
+    use dshr_methods_mod , only : dshr_state_getfldptr
+
+    ! input/output variables
+    type(ESMF_State)       , intent(inout) :: exportState
+    integer                , intent(out)   :: rc
+
+    ! local variables
+    integer           :: idim1,idim2
+    real(r8), pointer :: fldptr2(:,:)
+    character(len=*), parameter :: subname='(docn_datamode_multilev): '
+    !-------------------------------------------------------------------------------
+
+    rc = ESMF_SUCCESS
+
+    call dshr_state_getfldptr(exportState, 'So_t_depth', fldptr2=fldptr2, rc=rc)
+    if (chkerr(rc,__LINE__,u_FILE_u)) return
+    do idim2 = 1,size(fldptr2,dim=2)
+       do idim1 = 1,size(fldptr2,dim=1)
+          if (fldptr2(idim1,idim2) == 0.) then
path: docn/docn_datamode_multilev_cplhist_mod.F90
user: login: gold2718
body: Constant should have kind:
```suggestion
          if (fldptr2(idim1,idim2) == 0._r8) then
```
created_at: 2025-04-11T16:56:30Z
author_association: COLLABORATOR
diff_hunk: @@ -594,6 +600,27 @@ subroutine dlnd_comp_run(importState, exportState, target_ymd, target_tod, rc)
        ! do nothing extra
     end select
 
+    ! Set special value over masked points
+    if (trim(datamode) == 'glc_forcing_mct' .or. trim(datamode) == 'glc_forcing' ) then
+       call dshr_state_getfldptr(exportState, 'Sl_tsrf_elev', fldptr2=fldptr2, rc=rc)
+       if (chkerr(rc,__LINE__,u_FILE_u)) return
+       do n = 1,size(fldptr2,dim=2)
+          if (lfrac(n) == 0.) fldptr2(:,n) = 1.e30_r8
path: dlnd/lnd_comp_nuopc.F90
user: login: mvertens
body: Done
created_at: 2025-04-11T17:06:46Z
author_association: COLLABORATOR
diff_hunk: @@ -594,6 +600,27 @@ subroutine dlnd_comp_run(importState, exportState, target_ymd, target_tod, rc)
        ! do nothing extra
     end select
 
+    ! Set special value over masked points
+    if (trim(datamode) == 'glc_forcing_mct' .or. trim(datamode) == 'glc_forcing' ) then
+       call dshr_state_getfldptr(exportState, 'Sl_tsrf_elev', fldptr2=fldptr2, rc=rc)
+       if (chkerr(rc,__LINE__,u_FILE_u)) return
+       do n = 1,size(fldptr2,dim=2)
+          if (lfrac(n) == 0.) fldptr2(:,n) = 1.e30_r8
+       end do
+
+       call dshr_state_getfldptr(exportState, 'Sl_topo_elev', fldptr2=fldptr2, rc=rc)
+       if (chkerr(rc,__LINE__,u_FILE_u)) return
+       do n = 1,size(fldptr2,dim=2)
+          if (lfrac(n) == 0.) fldptr2(:,n) = 1.e30_r8
path: dlnd/lnd_comp_nuopc.F90
user: login: mvertens
body: Done
created_at: 2025-04-11T17:06:53Z
author_association: COLLABORATOR
diff_hunk: @@ -594,6 +600,27 @@ subroutine dlnd_comp_run(importState, exportState, target_ymd, target_tod, rc)
        ! do nothing extra
     end select
 
+    ! Set special value over masked points
+    if (trim(datamode) == 'glc_forcing_mct' .or. trim(datamode) == 'glc_forcing' ) then
+       call dshr_state_getfldptr(exportState, 'Sl_tsrf_elev', fldptr2=fldptr2, rc=rc)
+       if (chkerr(rc,__LINE__,u_FILE_u)) return
+       do n = 1,size(fldptr2,dim=2)
+          if (lfrac(n) == 0.) fldptr2(:,n) = 1.e30_r8
+       end do
+
+       call dshr_state_getfldptr(exportState, 'Sl_topo_elev', fldptr2=fldptr2, rc=rc)
+       if (chkerr(rc,__LINE__,u_FILE_u)) return
+       do n = 1,size(fldptr2,dim=2)
+          if (lfrac(n) == 0.) fldptr2(:,n) = 1.e30_r8
+       end do
+
+       call dshr_state_getfldptr(exportState, 'Flgl_qice_elev', fldptr2=fldptr2, rc=rc)
+       if (chkerr(rc,__LINE__,u_FILE_u)) return
+       do n = 1,size(fldptr2,dim=2)
+          if (lfrac(n) == 0.) fldptr2(:,n) = 1.e30_r8
path: dlnd/lnd_comp_nuopc.F90
user: login: mvertens
body: Done
created_at: 2025-04-11T17:07:03Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,170 @@
+module docn_datamode_multilev_cplhist_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_strdata_mod , only : shr_strdata_get_stream_pointer, shr_strdata_type
+  use dshr_dfield_mod  , only : dfield_type, dshr_dfield_add
+
+  implicit none
+  private ! except
+
+  public :: docn_datamode_multilev_cplhist_advertise
+  public :: docn_datamode_multilev_cplhist_init_pointers
+  public :: docn_datamode_multilev_cplhist_advance
+
+  ! 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()
+
+  ! 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. /)
+
+  ! constants
+  character(*) , parameter :: nullstr = 'null'
+  character(*) , parameter :: u_FILE_u = &
+       __FILE__
+
+!===============================================================================
+contains
+!===============================================================================
+
+  subroutine docn_datamode_multilev_cplhist_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)
+
+    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_cplhist_advertise
+
+  !===============================================================================
+  subroutine docn_datamode_multilev_cplhist_init_pointers(dfields, &
+       exportState, sdat, ocn_fraction, logunit, mainproc, rc)
+
+    ! input/output variables
+    type(dfield_type)      , pointer       :: dfields
+    type(ESMF_State)       , intent(inout) :: exportState
+    type(shr_strdata_type) , intent(in)    :: sdat
+    real(r8)               , intent(in)    :: ocn_fraction(:)
+    integer                , intent(in)    :: logunit
+    logical                , intent(in)    :: mainproc
+    integer                , intent(out)   :: rc
+
+    ! local variables
+    integer                     :: n
+    character(len=2)            :: num_str
+    character(CS), allocatable  :: strm_flds_t_depth(:)
+    character(CS), allocatable  :: strm_flds_s_depth(:)
+    character(len=*), parameter :: subname='(docn_init_pointers): '
+    !-------------------------------------------------------------------------------
+
+    rc = ESMF_SUCCESS
+
+    ! Note - docn_datamode_multilev_mod the assumption is that the stream files contain single
+    ! stream fields which contain the full set of levels in the stream data (i.e. 2d)
+    ! Whereas here we are assuming a different stream field for each vertical level
+    ! However, in both cases the export field contains an ungridded dimension for each vertical level
+
+    ! Create stream-> export state mapping
+    ! Note that strm_flds is the model name for the stream field
+    ! Note that state_fld is the model name for the export field
+
+    allocate(strm_flds_t_depth(1:nlev_export))
+    allocate(strm_flds_s_depth(1:nlev_export))
+    do n = 1,nlev_export
+       if (n < 10) then
+          write(num_str, '(i1.1)') n
+       else
+          write(num_str, '(i2.2)') n
+       end if
path: docn/docn_datamode_multilev_cplhist_mod.F90
user: login: mvertens
body: Good suggestion. Done.
created_at: 2025-04-11T17:08:24Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,170 @@
+module docn_datamode_multilev_cplhist_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_strdata_mod , only : shr_strdata_get_stream_pointer, shr_strdata_type
+  use dshr_dfield_mod  , only : dfield_type, dshr_dfield_add
+
+  implicit none
+  private ! except
+
+  public :: docn_datamode_multilev_cplhist_advertise
+  public :: docn_datamode_multilev_cplhist_init_pointers
+  public :: docn_datamode_multilev_cplhist_advance
+
+  ! 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()
+
+  ! 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. /)
path: docn/docn_datamode_multilev_cplhist_mod.F90
user: login: mvertens
body: Done
created_at: 2025-04-11T17:11:18Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,170 @@
+module docn_datamode_multilev_cplhist_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_strdata_mod , only : shr_strdata_get_stream_pointer, shr_strdata_type
+  use dshr_dfield_mod  , only : dfield_type, dshr_dfield_add
+
+  implicit none
+  private ! except
+
+  public :: docn_datamode_multilev_cplhist_advertise
+  public :: docn_datamode_multilev_cplhist_init_pointers
+  public :: docn_datamode_multilev_cplhist_advance
+
+  ! 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()
+
+  ! 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. /)
+
+  ! constants
+  character(*) , parameter :: nullstr = 'null'
+  character(*) , parameter :: u_FILE_u = &
+       __FILE__
+
+!===============================================================================
+contains
+!===============================================================================
+
+  subroutine docn_datamode_multilev_cplhist_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)
+
+    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_cplhist_advertise
+
+  !===============================================================================
+  subroutine docn_datamode_multilev_cplhist_init_pointers(dfields, &
+       exportState, sdat, ocn_fraction, logunit, mainproc, rc)
+
+    ! input/output variables
+    type(dfield_type)      , pointer       :: dfields
+    type(ESMF_State)       , intent(inout) :: exportState
+    type(shr_strdata_type) , intent(in)    :: sdat
+    real(r8)               , intent(in)    :: ocn_fraction(:)
+    integer                , intent(in)    :: logunit
+    logical                , intent(in)    :: mainproc
+    integer                , intent(out)   :: rc
+
+    ! local variables
+    integer                     :: n
+    character(len=2)            :: num_str
+    character(CS), allocatable  :: strm_flds_t_depth(:)
+    character(CS), allocatable  :: strm_flds_s_depth(:)
+    character(len=*), parameter :: subname='(docn_init_pointers): '
+    !-------------------------------------------------------------------------------
+
+    rc = ESMF_SUCCESS
+
+    ! Note - docn_datamode_multilev_mod the assumption is that the stream files contain single
+    ! stream fields which contain the full set of levels in the stream data (i.e. 2d)
+    ! Whereas here we are assuming a different stream field for each vertical level
+    ! However, in both cases the export field contains an ungridded dimension for each vertical level
+
+    ! Create stream-> export state mapping
+    ! Note that strm_flds is the model name for the stream field
+    ! Note that state_fld is the model name for the export field
+
+    allocate(strm_flds_t_depth(1:nlev_export))
+    allocate(strm_flds_s_depth(1:nlev_export))
+    do n = 1,nlev_export
+       if (n < 10) then
+          write(num_str, '(i1.1)') n
+       else
+          write(num_str, '(i2.2)') n
+       end if
+       strm_flds_t_depth(n) = 'So_t_depth' // trim(num_str)
+       strm_flds_s_depth(n) = 'So_s_depth' // trim(num_str)
+    end do
+
+    ! The following maps stream input multiple fields to export field that has an ungridded dimension
+    call dshr_dfield_add(dfields, sdat, state_fld='So_t_depth', strm_flds=strm_flds_t_depth, state=exportState, &
+         logunit=logunit, mainproc=mainproc, rc=rc)
+    call dshr_dfield_add(dfields, sdat, state_fld='So_s_depth', strm_flds=strm_flds_s_depth, state=exportState, &
+         logunit=logunit, mainproc=mainproc, rc=rc)
+
+    ! Set export state ocean fraction (So_omask)
+    call dshr_state_getfldptr(exportState, 'So_omask', fldptr1=So_omask   , rc=rc)
+    if (chkerr(rc,__LINE__,u_FILE_u)) return
+    So_omask(:) = ocn_fraction(:)
+
+  end subroutine docn_datamode_multilev_cplhist_init_pointers
+
+  !===============================================================================
+  subroutine docn_datamode_multilev_cplhist_advance(exportState, rc)
+
+    use dshr_methods_mod , only : dshr_state_getfldptr
+
+    ! input/output variables
+    type(ESMF_State)       , intent(inout) :: exportState
+    integer                , intent(out)   :: rc
+
+    ! local variables
+    integer           :: idim1,idim2
+    real(r8), pointer :: fldptr2(:,:)
+    character(len=*), parameter :: subname='(docn_datamode_multilev): '
+    !-------------------------------------------------------------------------------
+
+    rc = ESMF_SUCCESS
+
+    call dshr_state_getfldptr(exportState, 'So_t_depth', fldptr2=fldptr2, rc=rc)
+    if (chkerr(rc,__LINE__,u_FILE_u)) return
+    do idim2 = 1,size(fldptr2,dim=2)
+       do idim1 = 1,size(fldptr2,dim=1)
+          if (fldptr2(idim1,idim2) == 0.) then
+             fldptr2(idim1,idim2) = 1.e30_r8
+          end if
+       end do
+    end do
+
+    call dshr_state_getfldptr(exportState, 'So_s_depth', fldptr2=fldptr2, rc=rc)
+    if (chkerr(rc,__LINE__,u_FILE_u)) return
+    do idim2 = 1,size(fldptr2,dim=2)
+       do idim1 = 1,size(fldptr2,dim=1)
+          if (fldptr2(idim1,idim2) == 0.) then
path: docn/docn_datamode_multilev_cplhist_mod.F90
user: login: mvertens
body: Done
created_at: 2025-04-11T17:12:13Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,170 @@
+module docn_datamode_multilev_cplhist_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_strdata_mod , only : shr_strdata_get_stream_pointer, shr_strdata_type
+  use dshr_dfield_mod  , only : dfield_type, dshr_dfield_add
+
+  implicit none
+  private ! except
+
+  public :: docn_datamode_multilev_cplhist_advertise
+  public :: docn_datamode_multilev_cplhist_init_pointers
+  public :: docn_datamode_multilev_cplhist_advance
+
+  ! 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()
+
+  ! 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. /)
+
+  ! constants
+  character(*) , parameter :: nullstr = 'null'
+  character(*) , parameter :: u_FILE_u = &
+       __FILE__
+
+!===============================================================================
+contains
+!===============================================================================
+
+  subroutine docn_datamode_multilev_cplhist_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)
+
+    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_cplhist_advertise
+
+  !===============================================================================
+  subroutine docn_datamode_multilev_cplhist_init_pointers(dfields, &
+       exportState, sdat, ocn_fraction, logunit, mainproc, rc)
+
+    ! input/output variables
+    type(dfield_type)      , pointer       :: dfields
+    type(ESMF_State)       , intent(inout) :: exportState
+    type(shr_strdata_type) , intent(in)    :: sdat
+    real(r8)               , intent(in)    :: ocn_fraction(:)
+    integer                , intent(in)    :: logunit
+    logical                , intent(in)    :: mainproc
+    integer                , intent(out)   :: rc
+
+    ! local variables
+    integer                     :: n
+    character(len=2)            :: num_str
+    character(CS), allocatable  :: strm_flds_t_depth(:)
+    character(CS), allocatable  :: strm_flds_s_depth(:)
+    character(len=*), parameter :: subname='(docn_init_pointers): '
+    !-------------------------------------------------------------------------------
+
+    rc = ESMF_SUCCESS
+
+    ! Note - docn_datamode_multilev_mod the assumption is that the stream files contain single
+    ! stream fields which contain the full set of levels in the stream data (i.e. 2d)
+    ! Whereas here we are assuming a different stream field for each vertical level
+    ! However, in both cases the export field contains an ungridded dimension for each vertical level
+
+    ! Create stream-> export state mapping
+    ! Note that strm_flds is the model name for the stream field
+    ! Note that state_fld is the model name for the export field
+
+    allocate(strm_flds_t_depth(1:nlev_export))
+    allocate(strm_flds_s_depth(1:nlev_export))
+    do n = 1,nlev_export
+       if (n < 10) then
+          write(num_str, '(i1.1)') n
+       else
+          write(num_str, '(i2.2)') n
+       end if
+       strm_flds_t_depth(n) = 'So_t_depth' // trim(num_str)
+       strm_flds_s_depth(n) = 'So_s_depth' // trim(num_str)
+    end do
+
+    ! The following maps stream input multiple fields to export field that has an ungridded dimension
+    call dshr_dfield_add(dfields, sdat, state_fld='So_t_depth', strm_flds=strm_flds_t_depth, state=exportState, &
+         logunit=logunit, mainproc=mainproc, rc=rc)
+    call dshr_dfield_add(dfields, sdat, state_fld='So_s_depth', strm_flds=strm_flds_s_depth, state=exportState, &
+         logunit=logunit, mainproc=mainproc, rc=rc)
+
+    ! Set export state ocean fraction (So_omask)
+    call dshr_state_getfldptr(exportState, 'So_omask', fldptr1=So_omask   , rc=rc)
+    if (chkerr(rc,__LINE__,u_FILE_u)) return
+    So_omask(:) = ocn_fraction(:)
+
+  end subroutine docn_datamode_multilev_cplhist_init_pointers
+
+  !===============================================================================
+  subroutine docn_datamode_multilev_cplhist_advance(exportState, rc)
+
+    use dshr_methods_mod , only : dshr_state_getfldptr
+
+    ! input/output variables
+    type(ESMF_State)       , intent(inout) :: exportState
+    integer                , intent(out)   :: rc
+
+    ! local variables
+    integer           :: idim1,idim2
+    real(r8), pointer :: fldptr2(:,:)
+    character(len=*), parameter :: subname='(docn_datamode_multilev): '
+    !-------------------------------------------------------------------------------
+
+    rc = ESMF_SUCCESS
+
+    call dshr_state_getfldptr(exportState, 'So_t_depth', fldptr2=fldptr2, rc=rc)
+    if (chkerr(rc,__LINE__,u_FILE_u)) return
+    do idim2 = 1,size(fldptr2,dim=2)
+       do idim1 = 1,size(fldptr2,dim=1)
+          if (fldptr2(idim1,idim2) == 0.) then
path: docn/docn_datamode_multilev_cplhist_mod.F90
user: login: mvertens
body: Done
created_at: 2025-04-11T17:12:22Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,170 @@
+module docn_datamode_multilev_cplhist_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_strdata_mod , only : shr_strdata_get_stream_pointer, shr_strdata_type
+  use dshr_dfield_mod  , only : dfield_type, dshr_dfield_add
+
+  implicit none
+  private ! except
+
+  public :: docn_datamode_multilev_cplhist_advertise
+  public :: docn_datamode_multilev_cplhist_init_pointers
+  public :: docn_datamode_multilev_cplhist_advance
+
+  ! 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()
+
+  ! 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. /)
path: docn/docn_datamode_multilev_cplhist_mod.F90
user: login: mvertens
body: Done
created_at: 2025-04-11T17:12:35Z
author_association: COLLABORATOR

PR comments:
user: login: mvertens
created_at: 2025-04-13T19:11:41Z
body: @gold2718 - this is now ready for a review again.
author_association: COLLABORATOR
user: login: gold2718
created_at: 2025-04-14T08:58:02Z
body: Tagged as `cdeps1.0.70_noresm_v1`
@mvdebolskiy 
author_association: COLLABORATOR
user: login: mvdebolskiy
created_at: 2025-04-14T10:12:00Z
body: @mvertens @gold2718 gnu gives errors (we set warnings to errors with gnu debug) with debug for unused variables in a private module 
```
Error: Unused PRIVATE module variable ‘vertical_levels’ declared at (1) [-Werror=unused-value]
f951: all warnings being treated as errors
make[2]: *** [docn/CMakeFiles/docn.dir/build.make:179: docn/CMakeFiles/docn.dir/docn_datamode_multilev_cplhist_mod.F90.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:1447: docn/CMakeFiles/docn.dir/all] Error 2
make: *** [Makefile:136: all] Error 2
```
There are bunch of those.
author_association: COLLABORATOR