MOM6
ocn_comp_mct Module Reference

Detailed Description

This is the main driver for MOM6 in CIME.

Fluxes imported from the coupler (MCT) to MOM6

The following summarizes the mismatches between MCT and MOM6 in terms of ice ocean fluxes.

Redundancies: x2o_Faxa_prec = x2o_Faxa_rain + x2o_Faxa_snow

Variables whose units and sign could not be verified so far: x2o_Foxx_rofl x2o_Foxx_rof

Variables in MOM6 fluxes that are NOT filled by the coupler: ustar_berg, frictional velocity beneath icebergs [m s-1] area_berg, area covered by icebergs(m2/m2) mass_berg, mass of icebergs(kg/m2) runoff_hflx, heat content of liquid runoff (W/m2) calving_hflx, heat content of frozen runoff (W/m2) mi, mass of ice (kg/m2)

Variables in the coupler that are NOT used in MOM6 (i.e., no corresponding field in fluxes): x2o_Si_ifrac, fractional ice wrt ocean x2o_So_duu10n, 10m wind speed squared (m^2/s^2) x2o_Sa_co2prog, bottom atm level prognostic CO2 x2o_Sa_co2diag, bottom atm level diagnostic CO2

\TODO Langmuir related fields: surface Stokes drift, x-comp. (x2o_Sw_ustokes) surface Stokes drift, y-comp. (x2o_Sw_vstokes) wave model langmuir multiplier (x2o_Sw_lamult)

\TODO Biogeochemistry: x2o_Fioi_bcpho, Black Carbon hydrophobic release from sea ice component x2o_Fioi_bcphi, Black Carbon hydrophilic release from sea ice component x2o_Fioi_flxdst, Dust release from sea ice component x2o_Faxa_bcphidry, Black Carbon hydrophilic dry deposition x2o_Faxa_bcphodry, Black Carbon hydrophobic dry deposition x2o_Faxa_bcphiwet, Black Carbon hydrophobic wet deposition x2o_Faxa_ocphidry, Organic Carbon hydrophilic dry deposition x2o_Faxa_ocphodry, Organic Carbon hydrophobic dry deposition x2o_Faxa_ocphiwet, Organic Carbon hydrophilic dry deposition x2o_Faxa_dstwet, Sizes 1 to 4 dust - wet deposition x2o_Faxa_dstdry, Sizes 1 to 4 dust - dry deposition

Fluxes exported from MOM6 to the coupler (MCT)

Variables that are currently being exported:

Surface temperature (Kelvin) Surface salinity (psu) Surface eastward velocity [m s-1] Surface northward velocity [m s-1] Zonal slope in the sea surface height Meridional slope in the sea surface height

\TODO Variables that are not currently being exported:

Boundary layer depth CO2 DMS

Data Types

type  mct_mom_data
 Control structure for this module. More...
 

Functions/Subroutines

subroutine, public ocn_init_mct (EClock, cdata_o, x2o_o, o2x_o, NLFilename)
 This subroutine initializes MOM6. More...
 
subroutine, public ocn_run_mct (EClock, cdata_o, x2o_o, o2x_o)
 Step forward ocean model for coupling interval. More...
 
subroutine, public ocn_final_mct (EClock, cdata_o, x2o_o, o2x_o)
 Finalizes MOM6. More...
 
subroutine, private ocn_setgsmap_mct (mpicom_ocn, MOM_MCT_ID, gsMap_ocn, gsMap3d_ocn)
 Sets mct global segment maps for the MOM decomposition. More...
 
subroutine, private ocn_domain_mct (lsize, gsMap_ocn, dom_ocn)
 Sets MCT global segment maps for the MOM6 decomposition. More...
 
character(32) function, private get_runtype ()
 Returns the CESM run type. More...
 
subroutine, private ocean_model_init_sfc (OS, Ocean_sfc)
 It has to be separate from the ocean_initialization call because the coupler module allocates the space for some of these variables. More...
 
subroutine iob_allocate (IOB, isc, iec, jsc, jec)
 Allocates ice-ocean boundary type containers and sets to 0. More...
 

Variables

logical, parameter debug =.true.
 
type(mct_mom_dataglb
 global structure More...
 
type(ice_ocean_boundary_type) ice_ocean_boundary
 

Function/Subroutine Documentation

◆ get_runtype()

character(32) function, private ocn_comp_mct::get_runtype ( )
private

Returns the CESM run type.

Definition at line 721 of file ocn_comp_mct.F90.

721  character(len=32) :: starttype !< infodata start type
722 
723  call seq_infodata_getdata( glb%infodata, start_type=starttype)
724 
725  if ( trim(starttype) == trim(seq_infodata_start_type_start)) then
726  get_runtype = "initial"
727  else if (trim(starttype) == trim(seq_infodata_start_type_cont) ) then
728  get_runtype = "continue"
729  else if (trim(starttype) == trim(seq_infodata_start_type_brnch)) then
730  get_runtype = "branch"
731  else
732  write(glb%stdout,*) 'ocn_comp_mct ERROR: unknown starttype'
733  call exit(0)
734  end if
735  return
736 

References glb.

Referenced by ocn_init_mct(), and ocn_run_mct().

Here is the caller graph for this function:

◆ iob_allocate()

subroutine ocn_comp_mct::iob_allocate ( type(ice_ocean_boundary_type), intent(inout)  IOB,
integer, intent(in)  isc,
integer, intent(in)  iec,
integer, intent(in)  jsc,
integer, intent(in)  jec 
)
private

Allocates ice-ocean boundary type containers and sets to 0.

Parameters
[in,out]iobAn ice-ocean boundary type with fluxes to drive
[in]jecThe ocean's local grid size

Definition at line 825 of file ocn_comp_mct.F90.

825  type(ice_ocean_boundary_type), intent(inout) :: IOB !< An ice-ocean boundary type with fluxes to drive
826  integer, intent(in) :: isc, iec, jsc, jec !< The ocean's local grid size
827 
828  allocate ( iob% rofl_flux (isc:iec,jsc:jec), &
829  iob% rofi_flux (isc:iec,jsc:jec), &
830  iob% u_flux (isc:iec,jsc:jec), &
831  iob% v_flux (isc:iec,jsc:jec), &
832  iob% t_flux (isc:iec,jsc:jec), &
833  iob% seaice_melt_heat (isc:iec,jsc:jec),&
834  iob% seaice_melt (isc:iec,jsc:jec), &
835  iob% q_flux (isc:iec,jsc:jec), &
836  iob% salt_flux (isc:iec,jsc:jec), &
837  iob% lw_flux (isc:iec,jsc:jec), &
838  iob% sw_flux_vis_dir (isc:iec,jsc:jec), &
839  iob% sw_flux_vis_dif (isc:iec,jsc:jec), &
840  iob% sw_flux_nir_dir (isc:iec,jsc:jec), &
841  iob% sw_flux_nir_dif (isc:iec,jsc:jec), &
842  iob% lprec (isc:iec,jsc:jec), &
843  iob% fprec (isc:iec,jsc:jec), &
844  iob% ustar_berg (isc:iec,jsc:jec), &
845  iob% area_berg (isc:iec,jsc:jec), &
846  iob% mass_berg (isc:iec,jsc:jec), &
847  iob% calving (isc:iec,jsc:jec), &
848  iob% runoff_hflx (isc:iec,jsc:jec), &
849  iob% calving_hflx (isc:iec,jsc:jec), &
850  iob% mi (isc:iec,jsc:jec), &
851  iob% p (isc:iec,jsc:jec))
852 
853  iob%rofl_flux = 0.0
854  iob%rofi_flux = 0.0
855  iob%u_flux = 0.0
856  iob%v_flux = 0.0
857  iob%t_flux = 0.0
858  iob%seaice_melt_heat = 0.0
859  iob%seaice_melt = 0.0
860  iob%q_flux = 0.0
861  iob%salt_flux = 0.0
862  iob%lw_flux = 0.0
863  iob%sw_flux_vis_dir = 0.0
864  iob%sw_flux_vis_dif = 0.0
865  iob%sw_flux_nir_dir = 0.0
866  iob%sw_flux_nir_dif = 0.0
867  iob%lprec = 0.0
868  iob%fprec = 0.0
869  iob%ustar_berg = 0.0
870  iob%area_berg = 0.0
871  iob%mass_berg = 0.0
872  iob%calving = 0.0
873  iob%runoff_hflx = 0.0
874  iob%calving_hflx = 0.0
875  iob%mi = 0.0
876  iob%p = 0.0
877 

Referenced by ocn_init_mct().

Here is the caller graph for this function:

◆ ocean_model_init_sfc()

subroutine, private ocn_comp_mct::ocean_model_init_sfc ( type(ocean_state_type), pointer  OS,
type(ocean_public_type), intent(inout)  Ocean_sfc 
)
private

It has to be separate from the ocean_initialization call because the coupler module allocates the space for some of these variables.

Definition at line 744 of file ocn_comp_mct.F90.

744  type(ocean_state_type), pointer :: OS
745  type(ocean_public_type), intent(inout) :: Ocean_sfc
746 
747  integer :: is, ie, js, je
748 
749  is = os%grid%isc ; ie = os%grid%iec ; js = os%grid%jsc ; je = os%grid%jec
750  call coupler_type_spawn(ocean_sfc%fields, os%sfc_state%tr_fields, &
751  (/is,is,ie,ie/), (/js,js,je,je/), as_needed=.true.)
752 
753  call extract_surface_state(os%MOM_CSp, os%sfc_state)
754 
755  call convert_state_to_ocean_type(os%sfc_state, ocean_sfc, os%grid, os%US)
756 

References mom_ocean_model_mct::convert_state_to_ocean_type(), and mom::extract_surface_state().

Referenced by ocn_init_mct().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ocn_domain_mct()

subroutine, private ocn_comp_mct::ocn_domain_mct ( integer, intent(in)  lsize,
type(mct_gsmap), intent(in)  gsMap_ocn,
type(mct_ggrid), intent(inout)  dom_ocn 
)
private

Sets MCT global segment maps for the MOM6 decomposition.

Parameters
[in]lsizeSize of attr. vector
[in]gsmap_ocnMCT global segment map for 2d data
[in,out]dom_ocnWHAT IS THIS?

Definition at line 639 of file ocn_comp_mct.F90.

639  integer , intent(in) :: lsize !< Size of attr. vector
640  type(mct_gsMap), intent(in) :: gsMap_ocn !< MCT global segment map for 2d data
641  type(mct_ggrid), intent(inout) :: dom_ocn !< WHAT IS THIS?
642 
643  ! Local Variables
644  integer, parameter :: SHR_REAL_R8 = selected_real_kind(12)
645  integer, pointer :: idata(:)
646  integer :: i,j,k
647  real(kind=shr_real_r8), pointer :: data(:)
648  real(kind=shr_real_r8) :: l2_to_rad2
649  type(ocean_grid_type), pointer :: grid => null() ! A pointer to a grid structure
650 
651  grid => glb%grid ! for convenience
652 
653  ! set coords to lat and lon, and areas to rad^2
654  call mct_ggrid_init(ggrid=dom_ocn, coordchars='lat:lon:hgt', otherchars='area:aream:mask:frac', lsize=lsize )
655 
656  call mct_avect_zero(dom_ocn%data)
657  allocate(data(lsize))
658 
659  ! Determine global gridpoint number attribute, GlobGridNum, which is set automatically by MCT
660  k = pe_here()
661  call mct_gsmap_orderedpoints(gsmap_ocn, k, idata)
662  call mct_ggrid_importiattr(dom_ocn,'GlobGridNum',idata,lsize)
663 
664  !initialization
665  data(:) = -9999.0
666  call mct_ggrid_importrattr(dom_ocn,"lat" ,data,lsize)
667  call mct_ggrid_importrattr(dom_ocn,"lon" ,data,lsize)
668  call mct_ggrid_importrattr(dom_ocn,"area" ,data,lsize)
669  call mct_ggrid_importrattr(dom_ocn,"aream",data,lsize)
670  data(:) = 0.0
671  call mct_ggrid_importrattr(dom_ocn,"mask",data,lsize)
672  call mct_ggrid_importrattr(dom_ocn,"frac",data,lsize)
673 
674  k = 0
675  do j = grid%jsc, grid%jec
676  do i = grid%isc, grid%iec
677  k = k + 1 ! Increment position within gindex
678  data(k) = grid%geoLonT(i,j)
679  enddo
680  enddo
681  call mct_ggrid_importrattr(dom_ocn,"lon",data,lsize)
682 
683  k = 0
684  do j = grid%jsc, grid%jec
685  do i = grid%isc, grid%iec
686  k = k + 1 ! Increment position within gindex
687  data(k) = grid%geoLatT(i,j)
688  enddo
689  enddo
690  call mct_ggrid_importrattr(dom_ocn,"lat",data,lsize)
691 
692  k = 0
693  l2_to_rad2 = grid%US%L_to_m**2 / grid%Rad_Earth**2
694  do j = grid%jsc, grid%jec
695  do i = grid%isc, grid%iec
696  k = k + 1 ! Increment position within gindex
697  data(k) = grid%AreaT(i,j) * l2_to_rad2
698  enddo
699  enddo
700  call mct_ggrid_importrattr(dom_ocn,"area",data,lsize)
701 
702  k = 0
703  do j = grid%jsc, grid%jec
704  do i = grid%isc, grid%iec
705  k = k + 1 ! Increment position within gindex
706  data(k) = grid%mask2dT(i,j)
707  enddo
708  enddo
709  call mct_ggrid_importrattr(dom_ocn,"mask",data,lsize)
710  call mct_ggrid_importrattr(dom_ocn,"frac",data,lsize)
711 
712  deallocate(data)
713  deallocate(idata)
714 

References glb.

Referenced by ocn_init_mct().

Here is the caller graph for this function:

◆ ocn_final_mct()

subroutine, public ocn_comp_mct::ocn_final_mct ( type(esmf_clock), intent(inout)  EClock,
type(seq_cdata), intent(inout)  cdata_o,
type(mct_avect), intent(inout)  x2o_o,
type(mct_avect), intent(inout)  o2x_o 
)

Finalizes MOM6.

Todo:
This needs to be done here.
Parameters
[in,out]x2o_oFluxes from coupler to ocean, computed by ocean
[in,out]o2x_oFluxes from ocean to coupler, computed by ocean

Definition at line 576 of file ocn_comp_mct.F90.

576  type(ESMF_Clock) , intent(inout) :: EClock
577  type(seq_cdata) , intent(inout) :: cdata_o
578  type(mct_aVect) , intent(inout) :: x2o_o !< Fluxes from coupler to ocean, computed by ocean
579  type(mct_aVect) , intent(inout) :: o2x_o !< Fluxes from ocean to coupler, computed by ocean
580 
581  call ocean_model_end(glb%ocn_public, glb%ocn_state, glb%ocn_state%Time)
582 

References glb.

◆ ocn_init_mct()

subroutine, public ocn_comp_mct::ocn_init_mct ( type(esmf_clock), intent(inout)  EClock,
type(seq_cdata), intent(inout)  cdata_o,
type(mct_avect), intent(inout)  x2o_o,
type(mct_avect), intent(inout)  o2x_o,
character(len=*), intent(in), optional  NLFilename 
)

This subroutine initializes MOM6.

Parameters
[in,out]eclockTime and time step ?
Todo:
Why must this be intent(inout)?
Parameters
[in,out]cdata_oInput parameters
[in,out]x2o_oFluxes from coupler to ocean, computed by ocean
[in,out]o2x_oFluxes from ocean to coupler, computed by ocean
[in]nlfilenameNamelist filename

Definition at line 105 of file ocn_comp_mct.F90.

105  type(ESMF_Clock), intent(inout) :: EClock !< Time and time step ? \todo Why must this
106  !! be intent(inout)?
107  type(seq_cdata) , intent(inout) :: cdata_o !< Input parameters
108  type(mct_aVect) , intent(inout) :: x2o_o !< Fluxes from coupler to ocean, computed by ocean
109  type(mct_aVect) , intent(inout) :: o2x_o !< Fluxes from ocean to coupler, computed by ocean
110  character(len=*), optional , intent(in) :: NLFilename !< Namelist filename
111 
112  ! local variable
113  type(time_type) :: time0 !< Start time of coupled model's calendar.
114  type(time_type) :: time_start !< The time at which to initialize the ocean model
115  type(ESMF_time) :: time_var !< ESMF_time variable to query time
116  type(ESMF_time) :: time_in_ESMF !< Initial time for ocean
117  type(ESMF_timeInterval) :: ocn_cpl_interval !< Ocean coupling interval
118  integer :: ncouple_per_day
119  integer :: year, month, day, hour, minute, seconds, seconds_n, seconds_d, rc
120  character(len=240) :: runid !< Run ID
121  character(len=32) :: runtype !< Run type
122  character(len=240) :: restartfile !< Path/Name of restart file
123  integer :: nu !< i/o unit to read pointer file
124  character(len=240) :: restart_pointer_file !< File name for restart pointer file
125  character(len=240) :: restartpath !< Path of the restart file
126  integer :: mpicom_ocn !< MPI ocn communicator
127  integer :: npes, pe0 !< # of processors and current processor
128  integer :: i, errorCode
129  integer :: lsize, nsend, nrecv
130  logical :: ldiag_cpl = .false.
131  integer :: isc, iec, jsc, jec, ni, nj !< Indices for the start and end of the domain
132  !! in the x and y dir., respectively.
133  ! runtime params
134  type(param_file_type) :: param_file !< A structure to parse for run-time parameters
135  type(directories) :: dirs_tmp !< A structure containing several relevant directory paths
136  character(len=40) :: mdl = "ocn_comp_mct" !< This module's name.
137 
138  ! mct variables (these are local for now)
139  integer :: MOM_MCT_ID
140  type(mct_gsMap), pointer :: MOM_MCT_gsMap => null() !< 2d, points to cdata
141  type(mct_gGrid), pointer :: MOM_MCT_dom => null() !< 2d, points to cdata
142  type(mct_gsMap) :: MOM_MCT_gsMap3d !< for 3d streams, local
143  type(mct_gGrid) :: MOM_MCT_dom3d !< for 3d streams, local
144 
145  ! time management
146  integer :: ocn_cpl_dt !< one ocn coupling interval in seconds. (to be received from cesm)
147  real (kind=8) :: mom_cpl_dt !< one ocn coupling interval in seconds. (internal)
148  real (kind=8), parameter :: &
149  seconds_in_minute = 60.0d0, &
150  seconds_in_hour = 3600.0d0, &
151  seconds_in_day = 86400.0d0, &
152  minutes_in_hour = 60.0d0
153 
154  character(len=99) :: ocn_modelio_name !< ocn model input namelist filename
155  integer :: shrlogunit !< original log file unit
156  integer :: shrloglev !< original log level
157 
158  integer(kind=4) :: inst_index !< instance control vars (these are local for now)
159  character(len=16) :: inst_name
160  character(len=16) :: inst_suffix
161 
162  ! TODO: Change the following vars with the corresponding MOM6 vars
163  integer :: km=1 !< Number of vertical levels
164  !logical :: lsend_precip_fact !< If T,send precip_fact to cpl for use in fw balance
165  !! (partially-coupled option)
166  character(len=128) :: err_msg !< Error message
167 
168  ! set the cdata pointers:
169  call seq_cdata_setptrs(cdata_o, id=mom_mct_id, mpicom=mpicom_ocn, &
170  gsmap=mom_mct_gsmap, dom=mom_mct_dom, infodata=glb%infodata)
171 
172  ! Determine attribute vector indices
173  call cpl_indices_init(glb%ind)
174 
175  call seq_infodata_getdata( glb%infodata, case_name=runid )
176 
177  ! instance control
178  inst_name = seq_comm_name(mom_mct_id)
179  inst_index = seq_comm_inst(mom_mct_id)
180  inst_suffix = seq_comm_suffix(mom_mct_id)
181 
182  call t_startf('MOM_init')
183 
184  ! Initialize MOM6 comm
185  call mom_infra_init(mpicom_ocn)
186 
187  ! initialize ocn log file
188  if (is_root_pe()) then
189 
190  ! get original log file properties
191  call shr_file_getlogunit (shrlogunit)
192  call shr_file_getloglevel(shrloglev)
193 
194  glb%stdout = shr_file_getunit() ! get an unused unit number
195 
196  ! open the ocn_modelio.nml file and then open a log file associated with stdout
197  ocn_modelio_name = 'ocn_modelio.nml' // trim(inst_suffix)
198  call shr_file_setio(ocn_modelio_name,glb%stdout)
199 
200  ! set the shr log io unit number
201  call shr_file_setlogunit(glb%stdout)
202  end if
203 
204  call set_calendar_type(noleap) !TODO: confirm this
205 
206  ! Get start time
207  call esmf_clockget(eclock, starttime=time_var, rc=rc)
208  call esmf_timeget(time_var, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc)
209  time0 = set_date(year, month, day, hour, minute, seconds, err_msg=err_msg)
210 
211  ! Get current time
212  call esmf_clockget(eclock, currtime=time_var, rc=rc)
213  call esmf_timeget(time_var, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc)
214  time_start = set_date(year, month, day, hour, minute, seconds, err_msg=err_msg)
215 
216  ! Debugging clocks
217  if (debug .and. is_root_pe()) then
218  write(glb%stdout,*) 'ocn_init_mct, current time: y,m,d-',year,month,day,'h,m,s=',hour,minute,seconds
219 
220  call esmf_clockget(eclock, starttime=time_var, rc=rc)
221  call esmf_timeget(time_var, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc)
222  write(glb%stdout,*) 'ocn_init_mct, start time: y,m,d-',year,month,day,'h,m,s=',hour,minute,seconds
223 
224  call esmf_clockget(eclock, stoptime=time_var, rc=rc)
225  call esmf_timeget(time_var, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc)
226  write(glb%stdout,*) 'ocn_init_mct, stop time: y,m,d-',year,month,day,'h,m,s=',hour,minute,seconds
227 
228  call esmf_clockget(eclock, prevtime=time_var, rc=rc)
229  call esmf_timeget(time_var, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc)
230  write(glb%stdout,*) 'ocn_init_mct, previous time: y,m,d-',year,month,day,'h,m,s=',hour,minute,seconds
231 
232  call esmf_clockget(eclock, timestep=ocn_cpl_interval, rc=rc)
233  call esmf_timeintervalget(ocn_cpl_interval, yy=year, mm=month, d=day, s=seconds, sn=seconds_n, sd=seconds_d, rc=rc)
234  write(glb%stdout,*) 'ocn_init_mct, time step: y,m,d-',year,month,day,'s,sn,sd=',seconds,seconds_n,seconds_d
235  endif
236 
237  npes = num_pes()
238  pe0 = root_pe()
239 
240  allocate(glb%ocn_public)
241  glb%ocn_public%is_ocean_PE = .true.
242 
243  allocate(glb%ocn_public%pelist(npes))
244  glb%ocn_public%pelist(:) = (/(i,i=pe0,pe0+npes)/)
245  ! \todo Set other bits of glb$ocn_public
246 
247  ! This include declares and sets the variable "version".
248  ! read useful runtime params
249  call get_mom_input(param_file, dirs_tmp, check_params=.false.)
250  !call log_version(param_file, mdl, version, "")
251 
252  call get_param(param_file, mdl, "POINTER_FILENAME", glb%pointer_filename, &
253  "Name of the ascii file that contains the path and filename of" // &
254  " the latest restart file.", default='rpointer.ocn')
255 
256  call get_param(param_file, mdl, "SW_DECOMP", glb%sw_decomp, &
257  "If True, read coeffs c1, c2, c3 and c4 and decompose" // &
258  "the net shortwave radiation (SW) into four components:\n" // &
259  "visible, direct shortwave = c1 * SW \n" // &
260  "visible, diffuse shortwave = c2 * SW \n" // &
261  "near-IR, direct shortwave = c3 * SW \n" // &
262  "near-IR, diffuse shortwave = c4 * SW", default=.true.)
263 
264  if (glb%sw_decomp) then
265  call get_param(param_file, mdl, "SW_c1", glb%c1, &
266  "Coeff. used to convert net shortwave rad. into "//&
267  "visible, direct shortwave.", units="nondim", default=0.285)
268 
269  call get_param(param_file, mdl, "SW_c2", glb%c2, &
270  "Coeff. used to convert net shortwave rad. into "//&
271  "visible, diffuse shortwave.", units="nondim", default=0.285)
272 
273  call get_param(param_file, mdl, "SW_c3", glb%c3, &
274  "Coeff. used to convert net shortwave rad. into "//&
275  "near-IR, direct shortwave.", units="nondim", default=0.215)
276 
277  call get_param(param_file, mdl, "SW_c4", glb%c4, &
278  "Coeff. used to convert net shortwave rad. into "//&
279  "near-IR, diffuse shortwave.", units="nondim", default=0.215)
280  else
281  glb%c1 = 0.0; glb%c2 = 0.0; glb%c3 = 0.0; glb%c4 = 0.0
282  endif
283 
284  ! Close param file before it gets opened by ocean_model_init again.
285  call close_param_file(param_file)
286 
287  ! Initialize the MOM6 model
288  runtype = get_runtype()
289  if (runtype == "initial") then
290  ! startup (new run) - 'n' is needed below since we don't specify input_filename in input.nml
291  call ocean_model_init(glb%ocn_public, glb%ocn_state, time0, time_start, input_restart_file = 'n')
292  else ! hybrid or branch or continuos runs
293  ! get output path root
294  call seq_infodata_getdata( glb%infodata, outpathroot=restartpath )
295  ! read name of restart file in the pointer file
296  nu = shr_file_getunit()
297  restart_pointer_file = trim(glb%pointer_filename)
298  if (is_root_pe()) write(glb%stdout,*) 'Reading ocn pointer file: ',restart_pointer_file
299  open(nu, file=restart_pointer_file, form='formatted', status='unknown')
300  read(nu,'(a)') restartfile
301  close(nu)
302  !restartfile = trim(restartpath) // trim(restartfile)
303  if (is_root_pe()) then
304  write(glb%stdout,*) 'Reading restart file: ',trim(restartfile)
305  end if
306  call shr_file_freeunit(nu)
307  call ocean_model_init(glb%ocn_public, glb%ocn_state, time0, time_start, input_restart_file=trim(restartfile))
308  endif
309  if (is_root_pe()) then
310  write(glb%stdout,'(/12x,a/)') '======== COMPLETED MOM INITIALIZATION ========'
311  end if
312 
313  ! Initialize ocn_state%sfc_state out of sight
314  call ocean_model_init_sfc(glb%ocn_state, glb%ocn_public)
315 
316  ! Store pointers to components inside MOM
317  glb%grid => glb%ocn_state%grid
318 
319  ! Allocate IOB data type (needs to be called after glb%grid is set)
320  !write(6,*)'DEBUG: isc,iec,jsc,jec= ',glb%grid%isc, glb%grid%iec, glb%grid%jsc, glb%grid%jec
321  call iob_allocate(ice_ocean_boundary, glb%grid%isc, glb%grid%iec, glb%grid%jsc, glb%grid%jec)
322 
323  call t_stopf('MOM_init')
324 
325  ! Initialize MCT attribute vectors and indices
326  call t_startf('MOM_mct_init')
327 
328  if (debug .and. root_pe().eq.pe_here()) print *, "calling ocn_SetGSMap_mct"
329 
330  ! Set mct global seg maps:
331 
332  call ocn_setgsmap_mct(mpicom_ocn, mom_mct_id, mom_mct_gsmap, mom_mct_gsmap3d)
333  lsize = mct_gsmap_lsize(mom_mct_gsmap, mpicom_ocn)
334 
335  ! Initialize mct ocn domain (needs ocn initialization info)
336 
337  if (debug .and. root_pe().eq.pe_here()) print *, "calling ocn_domain_mct"
338  call ocn_domain_mct(lsize, mom_mct_gsmap, mom_mct_dom)
339  !call ocn_domain_mct(lsize*km, MOM_MCT_gsmap3d, MOM_MCT_dom3d) !TODO: this is not used
340 
341  ! Inialize mct attribute vectors
342 
343  if (debug .and. root_pe().eq.pe_here()) print *, "calling mct_avect_init a"
344 
345  ! Initialize the mct attribute vector x2o_o, given Attribute list and length:
346  call mct_avect_init(x2o_o, rlist=seq_flds_x2o_fields, lsize=lsize)
347  ! set the mct attribute vector x2o_o to zero:
348  call mct_avect_zero(x2o_o)
349 
350  if (debug .and. root_pe().eq.pe_here()) print *, "calling mct_avect_init b"
351 
352  ! Initialize the mct attribute vector o2x_o, given Attribute list and length:
353  call mct_avect_init(o2x_o, rlist=seq_flds_o2x_fields, lsize=lsize)
354  ! set the mct attribute vector o2x_o to zero:
355  call mct_avect_zero(o2x_o)
356 
357  ! allocate send buffer
358  nsend = mct_avect_nrattr(o2x_o)
359  nrecv = mct_avect_nrattr(x2o_o)
360 
361  ! initialize necessary coupling info
362 
363  if (debug .and. root_pe().eq.pe_here()) print *, "calling seq_timemgr_eclockgetdata"
364 
365  call seq_timemgr_eclockgetdata(eclock, dtime=ocn_cpl_dt)
366 
367  ! \todo Need interface to get dt from MOM6
368  ncouple_per_day = seconds_in_day / ocn_cpl_dt
369  mom_cpl_dt = seconds_in_day / ncouple_per_day
370  if (mom_cpl_dt /= ocn_cpl_dt) then
371  write(glb%stdout,*) 'ERROR mom_cpl_dt and ocn_cpl_dt must be identical'
372  call exit(0)
373  end if
374 
375  ! send initial state to driver
376 
377  !TODO:
378  ! if ( lsend_precip_fact ) then
379  ! call seq_infodata_PutData( infodata, precip_fact=precip_fact)
380  ! end if
381 
382  if (debug .and. root_pe().eq.pe_here()) print *, "calling ocn_export"
383  call ocn_export(glb%ind, glb%ocn_public, glb%grid, o2x_o%rattr, mom_cpl_dt, ncouple_per_day)
384 
385  call t_stopf('MOM_mct_init')
386 
387  ! Size of global domain
388  call get_global_grid_size(glb%grid, ni, nj)
389 
390  if (debug .and. root_pe().eq.pe_here()) print *, "calling seq_infodata_putdata"
391 
392  call seq_infodata_putdata( glb%infodata, &
393  ocn_nx = ni , ocn_ny = nj)
394  call seq_infodata_putdata( glb%infodata, &
395  ocn_prognostic=.true., ocnrof_prognostic=.true.)
396 
397  if (debug .and. root_pe().eq.pe_here()) print *, "leaving ocean_init_mct"
398 
399  ! Reset shr logging to original values
400  if (is_root_pe()) then
401  call shr_file_setlogunit (shrlogunit)
402  call shr_file_setloglevel(shrloglev)
403  end if
404 

References mom_file_parser::close_param_file(), ocn_cpl_indices::cpl_indices_init(), debug, mom_grid::get_global_grid_size(), mom_get_input::get_mom_input(), get_runtype(), glb, ice_ocean_boundary, iob_allocate(), mom_error_handler::is_root_pe(), ocean_model_init_sfc(), ocn_domain_mct(), ocn_cap_methods::ocn_export(), and ocn_setgsmap_mct().

Here is the call graph for this function:

◆ ocn_run_mct()

subroutine, public ocn_comp_mct::ocn_run_mct ( type(esmf_clock), intent(inout)  EClock,
type(seq_cdata), intent(inout)  cdata_o,
type(mct_avect), intent(inout)  x2o_o,
type(mct_avect), intent(inout)  o2x_o 
)

Step forward ocean model for coupling interval.

Parameters
[in,out]eclockTime and time step ?
Todo:
Why must this be intent(inout)?
Parameters
[in,out]cdata_oInput parameters
[in,out]x2o_oFluxes from coupler to ocean, computed by ocean
[in,out]o2x_oFluxes from ocean to coupler, computed by ocean

Definition at line 411 of file ocn_comp_mct.F90.

411  type(ESMF_Clock), intent(inout) :: EClock !< Time and time step ? \todo Why must this be intent(inout)?
412  type(seq_cdata), intent(inout) :: cdata_o !< Input parameters
413  type(mct_aVect), intent(inout) :: x2o_o !< Fluxes from coupler to ocean, computed by ocean
414  type(mct_aVect), intent(inout) :: o2x_o !< Fluxes from ocean to coupler, computed by ocean
415  ! Local variables
416  type(ESMF_time) :: time_var !< ESMF_time variable to query time
417  type(ESMF_timeInterval) :: ocn_cpl_interval !< The length of one ocean coupling interval
418  integer :: year, month, day, hour, minute, seconds, seconds_n, seconds_d, rc
419  logical :: write_restart_at_eod !< Controls if restart files must be written
420  logical :: debug=.false.
421  type(time_type) :: time_start !< Start of coupled time interval to pass to MOM6
422  type(time_type) :: coupling_timestep !< Coupled time interval to pass to MOM6
423  character(len=128) :: err_msg !< Error message
424  character(len=32) :: timestamp !< Name of intermediate restart file
425  character(len=384) :: restartname !< The restart file name (no dir)
426  character(len=384) :: restart_pointer_file !< File name for restart pointer file
427  character(len=384) :: runid !< Run ID
428  character(len=32) :: runtype !< Run type
429  integer :: nu !< i/o unit to write pointer file
430  integer :: shrlogunit ! original log file unit
431  integer :: shrloglev ! original log level
432  logical, save :: firstCall = .true.
433  real (kind=8), parameter :: seconds_in_day = 86400.0 !< number of seconds in one day
434  integer :: ocn_cpl_dt !< one ocn coupling interval in seconds. (to be received from cesm)
435  real (kind=8) :: mom_cpl_dt !< one ocn coupling interval in seconds. (internal)
436  integer :: ncouple_per_day !< number of ocean coupled call in one day (non-dim)
437 
438  ! reset shr logging to ocn log file:
439  if (is_root_pe()) then
440  call shr_file_getlogunit(shrlogunit)
441  call shr_file_getloglevel(shrloglev)
442  call shr_file_setlogunit(glb%stdout)
443  endif
444 
445  ! Query the beginning time of the current coupling interval
446  call esmf_clockget(eclock, prevtime=time_var, rc=rc)
447  call esmf_timeget(time_var, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc)
448  time_start = set_date(year, month, day, hour, minute, seconds, err_msg=err_msg)
449 
450  ! Query the coupling interval duration
451  call esmf_clockget(eclock, timestep=ocn_cpl_interval, rc=rc)
452  call esmf_timeintervalget(ocn_cpl_interval, yy=year, mm=month, d=day, s=seconds, sn=seconds_n, sd=seconds_d, rc=rc)
453  coupling_timestep = set_time(seconds, days=day, err_msg=err_msg)
454 
455  call seq_timemgr_eclockgetdata(eclock, dtime=ocn_cpl_dt)
456  ncouple_per_day = seconds_in_day / ocn_cpl_dt
457  mom_cpl_dt = seconds_in_day / ncouple_per_day
458 
459  ! The following if-block is to correct monthly mean outputs:
460  ! With this change, MOM6 starts at the same date as the other components, and runs for the same
461  ! duration as other components, unlike POP, which would have one missing interval due to ocean
462  ! lag. MOM6 accounts for this lag by doubling the duration of the first coupling interval.
463  if (firstcall) then
464 
465  runtype = get_runtype()
466  if (runtype /= "continue" .and. runtype /= "branch") then
467 
468  if (debug .and. is_root_pe()) then
469  write(glb%stdout,*) 'doubling first interval duration!'
470  endif
471 
472  ! shift back the start time by one coupling interval (to align the start time with other components)
473  time_start = time_start-coupling_timestep
474  ! double the first coupling interval (to account for the missing coupling interval to due to lag)
475  coupling_timestep = coupling_timestep*2
476  end if
477 
478  firstcall = .false.
479  end if
480 
481  ! Debugging clocks
482  if (debug .and. is_root_pe()) then
483  call esmf_clockget(eclock, currtime=time_var, rc=rc)
484  call esmf_timeget(time_var, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc)
485  write(glb%stdout,*) 'ocn_run_mct, current time: y,m,d-',year,month,day,'h,m,s=',hour,minute,seconds
486  call esmf_clockget(eclock, starttime=time_var, rc=rc)
487  call esmf_timeget(time_var, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc)
488  write(glb%stdout,*) 'ocn_run_mct, start time: y,m,d-',year,month,day,'h,m,s=',hour,minute,seconds
489  call esmf_clockget(eclock, stoptime=time_var, rc=rc)
490  call esmf_timeget(time_var, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc)
491  write(glb%stdout,*) 'ocn_run_mct, stop time: y,m,d-',year,month,day,'h,m,s=',hour,minute,seconds
492  call esmf_clockget(eclock, prevtime=time_var, rc=rc)
493  call esmf_timeget(time_var, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc)
494  write(glb%stdout,*) 'ocn_run_mct, previous time: y,m,d-',year,month,day,'h,m,s=',hour,minute,seconds
495  call esmf_clockget(eclock, timestep=ocn_cpl_interval, rc=rc)
496  call esmf_timeintervalget(ocn_cpl_interval, yy=year, mm=month, d=day, s=seconds, sn=seconds_n, sd=seconds_d, rc=rc)
497  write(glb%stdout,*) 'ocn_init_mct, time step: y,m,d-',year,month,day,'s,sn,sd=',seconds,seconds_n,seconds_d
498  endif
499 
500  ! set the cdata pointers:
501  ! \todo this was done in _init_, is it needed again. Does this infodata need to be in glb%?
502  ! GMM, check if this is needed!
503  call seq_cdata_setptrs(cdata_o, infodata=glb%infodata)
504 
505  ! Translate import fields to ice_ocean_boundary
506  !TODO: make this an input variable
507  !glb%sw_decomp = .false.
508  !END TODO:
509  if (glb%sw_decomp) then
510  call ocn_import(x2o_o%rattr, glb%ind, glb%grid, ice_ocean_boundary, glb%ocn_public, glb%stdout, eclock, &
511  c1=glb%c1, c2=glb%c2, c3=glb%c3, c4=glb%c4)
512  else
513  call ocn_import(x2o_o%rattr, glb%ind, glb%grid, ice_ocean_boundary, glb%ocn_public, glb%stdout, eclock )
514  end if
515 
516  ! Update internal ocean
517  call update_ocean_model(ice_ocean_boundary, glb%ocn_state, glb%ocn_public, time_start, coupling_timestep)
518 
519  ! Return export state to driver
520  call ocn_export(glb%ind, glb%ocn_public, glb%grid, o2x_o%rattr, mom_cpl_dt, ncouple_per_day)
521 
522  !--- write out intermediate restart file when needed.
523  ! Check alarms for flag to write restart at end of day
524  write_restart_at_eod = seq_timemgr_restartalarmison(eclock)
525  if (debug .and. is_root_pe()) write(glb%stdout,*) 'ocn_run_mct, write_restart_at_eod=', write_restart_at_eod
526 
527  if (write_restart_at_eod) then
528  ! case name
529  call seq_infodata_getdata( glb%infodata, case_name=runid )
530  ! add time stamp to the restart filename
531  call esmf_clockget(eclock, currtime=time_var, rc=rc)
532  call esmf_timeget(time_var, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc)
533  seconds = seconds + hour*3600 + minute*60
534  write(restartname,'(A,".mom6.r.",I4.4,"-",I2.2,"-",I2.2,"-",I5.5)') trim(runid), year, month, day, seconds
535 
536  call save_restart(glb%ocn_state%dirs%restart_output_dir, glb%ocn_state%Time, glb%grid, &
537  glb%ocn_state%restart_CSp, .false., filename=restartname, gv=glb%ocn_state%GV)
538 
539  ! write name of restart file in the rpointer file
540  nu = shr_file_getunit()
541  if (is_root_pe()) then
542  restart_pointer_file = trim(glb%pointer_filename)
543  open(nu, file=restart_pointer_file, form='formatted', status='unknown')
544  write(nu,'(a)') trim(restartname) //'.nc'
545  close(nu)
546  write(glb%stdout,*) 'ocn restart pointer file written: ',trim(restartname)
547  endif
548  call shr_file_freeunit(nu)
549 
550  ! Is this needed?
551  call forcing_save_restart(glb%ocn_state%forcing_CSp, glb%grid, glb%ocn_state%Time, &
552  glb%ocn_state%dirs%restart_output_dir, .true.)
553 
554  ! Once we start using the ice shelf module, the following will be needed
555  if (glb%ocn_state%use_ice_shelf) then
556  call ice_shelf_save_restart(glb%ocn_state%Ice_shelf_CSp, glb%ocn_state%Time, &
557  glb%ocn_state%dirs%restart_output_dir, .true.)
558  endif
559 
560  endif
561 
562  ! reset shr logging to original values
563  if (is_root_pe()) then
564  call shr_file_setlogunit(shrlogunit)
565  call shr_file_setloglevel(shrloglev)
566  endif
567 

References debug, mom_surface_forcing_mct::forcing_save_restart(), get_runtype(), glb, ice_ocean_boundary, mom_ice_shelf::ice_shelf_save_restart(), mom_error_handler::is_root_pe(), ocn_cap_methods::ocn_export(), ocn_cap_methods::ocn_import(), and mom_restart::save_restart().

Here is the call graph for this function:

◆ ocn_setgsmap_mct()

subroutine, private ocn_comp_mct::ocn_setgsmap_mct ( integer, intent(in)  mpicom_ocn,
integer, intent(in)  MOM_MCT_ID,
type(mct_gsmap), intent(inout)  gsMap_ocn,
type(mct_gsmap), intent(inout)  gsMap3d_ocn 
)
private

Sets mct global segment maps for the MOM decomposition.

Todo:
Find out if we should only provide indirect indexing for ocean points and not land.
Parameters
[in]mpicom_ocnMPI communicator
[in]mom_mct_idMCT component ID
[in,out]gsmap_ocnMCT global segment map for 2d data
[in,out]gsmap3d_ocnMCT global segment map for 3d data

Definition at line 591 of file ocn_comp_mct.F90.

591  integer, intent(in) :: mpicom_ocn !< MPI communicator
592  integer, intent(in) :: MOM_MCT_ID !< MCT component ID
593  type(mct_gsMap), intent(inout) :: gsMap_ocn !< MCT global segment map for 2d data
594  type(mct_gsMap), intent(inout) :: gsMap3d_ocn !< MCT global segment map for 3d data
595 
596  ! Local variables
597  integer :: lsize !< Local size of indirect indexing array
598  integer :: i, j, k !< Local indices
599  integer :: ni, nj !< Declared sizes of h-point arrays
600  integer :: ig, jg !< Global indices
601  type(ocean_grid_type), pointer :: grid => null() !< A pointer to a grid structure
602  integer, allocatable :: gindex(:) !< Indirect indices
603 
604  grid => glb%grid ! for convenience
605  if (.not. associated(grid)) call mom_error(fatal, 'ocn_comp_mct.F90, ocn_SetGSMap_mct():' // &
606  'grid is not associated!')
607 
608  ! Size of computational domain
609  lsize = ( grid%iec - grid%isc + 1 ) * ( grid%jec - grid%jsc + 1 )
610 
611  ! Size of global domain
612  call get_global_grid_size(grid, ni, nj)
613 
614  ! Create indirect indices for the computational domain
615  allocate(gindex(lsize))
616 
617  ! Set indirect indices in gindex
618  k = 0
619  do j = grid%jsc, grid%jec
620  jg = j + grid%jdg_offset ! TODO: check this calculation
621  do i = grid%isc, grid%iec
622  ig = i + grid%idg_offset ! TODO: check this calculation
623  k = k + 1 ! Increment position within gindex
624  gindex(k) = ni * (jg - 1) + ig
625  enddo
626  enddo
627 
628  ! Tell MCT how to indirectly index into the 2d buffer
629  call mct_gsmap_init(gsmap_ocn, gindex, mpicom_ocn, mom_mct_id, lsize, ni * nj)
630 
631  deallocate(gindex)
632 

References mom_grid::get_global_grid_size(), glb, and mom_error_handler::mom_error().

Referenced by ocn_init_mct().

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ debug

logical, parameter ocn_comp_mct::debug =.true.
private

Definition at line 80 of file ocn_comp_mct.F90.

80 logical, parameter :: debug=.true.

Referenced by ocn_init_mct(), and ocn_run_mct().

◆ glb

type(mct_mom_data) ocn_comp_mct::glb
private

global structure

Definition at line 96 of file ocn_comp_mct.F90.

96 type(MCT_MOM_Data) :: glb !< global structure

Referenced by get_runtype(), ocn_domain_mct(), ocn_final_mct(), ocn_init_mct(), ocn_run_mct(), and ocn_setgsmap_mct().

◆ ice_ocean_boundary

type(ice_ocean_boundary_type) ocn_comp_mct::ice_ocean_boundary
private

Definition at line 97 of file ocn_comp_mct.F90.

97 type(ice_ocean_boundary_type) :: ice_ocean_boundary

Referenced by ocn_init_mct(), and ocn_run_mct().