From 711a613ec8ff1c70b8cd75f75cec1ac990a29636 Mon Sep 17 00:00:00 2001 From: Gustavo Marques Date: Fri, 23 Jun 2017 13:48:50 -0600 Subject: [PATCH 01/38] Removes frazil's contribution to evaporation Frazil formation was being converted to surface layer evaporation under ice sheves and this was double counting the effect of frazil on the system. --- src/ice_shelf/MOM_ice_shelf.F90 | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/ice_shelf/MOM_ice_shelf.F90 b/src/ice_shelf/MOM_ice_shelf.F90 index f7de07a41c..1294ed065b 100644 --- a/src/ice_shelf/MOM_ice_shelf.F90 +++ b/src/ice_shelf/MOM_ice_shelf.F90 @@ -1053,17 +1053,6 @@ subroutine add_shelf_flux(G, CS, state, fluxes) endif - ! Add frazil formation diagnosed by the ocean model (J m-2) in the - ! form of surface layer evaporation (kg m-2 s-1). Update lprec in the - ! control structure for diagnostic purposes. - - if (associated(state%frazil)) then - fraz = state%frazil(i,j) / CS%time_step / CS%Lat_fusion - if (associated(fluxes%evap)) fluxes%evap(i,j) = fluxes%evap(i,j) - fraz - CS%lprec(i,j)=CS%lprec(i,j) - fraz - state%frazil(i,j) = 0.0 - endif - if (associated(fluxes%sens)) fluxes%sens(i,j) = -frac_area*CS%t_flux(i,j)*CS%flux_factor if (associated(fluxes%salt_flux)) fluxes%salt_flux(i,j) = frac_area * CS%salt_flux(i,j)*CS%flux_factor if (associated(fluxes%p_surf)) fluxes%p_surf(i,j) = frac_area * CS%g_Earth * CS%mass_shelf(i,j) From 346097dd21e0ffafa6b29028a1e9264730ad0ac3 Mon Sep 17 00:00:00 2001 From: alperaltuntas Date: Thu, 29 Jun 2017 15:49:21 -0600 Subject: [PATCH 02/38] Moved blank ocn_comp_mct.F90 --- config_src/mct_driver/ocn_comp_mct.F90 | 140 +++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 config_src/mct_driver/ocn_comp_mct.F90 diff --git a/config_src/mct_driver/ocn_comp_mct.F90 b/config_src/mct_driver/ocn_comp_mct.F90 new file mode 100644 index 0000000000..905bb65eea --- /dev/null +++ b/config_src/mct_driver/ocn_comp_mct.F90 @@ -0,0 +1,140 @@ +module ocn_comp_mct + +!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +!BOP +! !MODULE: ocn_comp_mct +! !INTERFACE: + +! !DESCRIPTION: +! This is the main driver for the MOM6 in CIME +! +! !REVISION HISTORY: +! +! !USES: + use esmf + use seq_cdata_mod + use mct_mod + +! +! !PUBLIC MEMBER FUNCTIONS: + implicit none + public :: ocn_init_mct + public :: ocn_run_mct + public :: ocn_final_mct + private ! By default make data private + +! +! ! PUBLIC DATA: +! +! !REVISION HISTORY: +! Author: Mariana Vertenstein +! +!EOP +! !PRIVATE MODULE FUNCTIONS: + +! +! !PRIVATE MODULE VARIABLES + +!======================================================================= + +contains + +!*********************************************************************** +!BOP +! +! !IROUTINE: ocn_init_mct +! +! !INTERFACE: + subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) +! +! !DESCRIPTION: +! Initialize POP +! +! !INPUT/OUTPUT PARAMETERS: + + type(ESMF_Clock) , intent(inout) :: EClock + type(seq_cdata) , intent(inout) :: cdata_o + type(mct_aVect) , intent(inout) :: x2o_o, o2x_o + character(len=*), optional , intent(in) :: NLFilename ! Namelist filename +! +! !REVISION HISTORY: +! Author: Mariana Vertenstein +!EOP +!----------------------------------------------------------------------- +! +! local variables +! +!----------------------------------------------------------------------- + + +!----------------------------------------------------------------------- +!EOC + + end subroutine ocn_init_mct + +!*********************************************************************** +!BOP +! +! !IROUTINE: ocn_run_mct +! +! !INTERFACE: + subroutine ocn_run_mct( EClock, cdata_o, x2o_o, o2x_o) +! +! !DESCRIPTION: +! Run POP for a coupling interval +! +! !INPUT/OUTPUT PARAMETERS: + 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 + +! +! !REVISION HISTORY: +! Author: Mariana Vertenstein +!EOP +!----------------------------------------------------------------------- +! +! local variables +! +!----------------------------------------------------------------------- + +!----------------------------------------------------------------------- +!EOC + + end subroutine ocn_run_mct + +!*********************************************************************** +!BOP +! +! !IROUTINE: ocn_final_mct +! +! !INTERFACE: + subroutine ocn_final_mct( EClock, cdata_o, x2o_o, o2x_o) +! +! !DESCRIPTION: +! Finalize POP +! +! !USES: +! !ARGUMENTS: + 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 +! +! !REVISION HISTORY: +! Author: Fei Liu +!EOP +!BOC +!----------------------------------------------------------------------- +! +! local variables +! +!----------------------------------------------------------------------- + + end subroutine ocn_final_mct + + +end module ocn_comp_mct + +!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| From 426357ce7414d2b24234b6a6ac05f880e04003e1 Mon Sep 17 00:00:00 2001 From: alperaltuntas Date: Fri, 30 Jun 2017 17:45:54 -0600 Subject: [PATCH 03/38] Time and calendar initialization in ocn_comp_mct.F90 --- config_src/mct_driver/ocn_comp_mct.F90 | 36 +++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/config_src/mct_driver/ocn_comp_mct.F90 b/config_src/mct_driver/ocn_comp_mct.F90 index 905bb65eea..74333e2d42 100644 --- a/config_src/mct_driver/ocn_comp_mct.F90 +++ b/config_src/mct_driver/ocn_comp_mct.F90 @@ -15,6 +15,11 @@ module ocn_comp_mct use seq_cdata_mod use mct_mod + ! From MOM6 + use ocean_model_mod, only: ocean_state_type, ocean_public_type + use ocean_model_mod, only: ocean_model_init + use MOM_time_manager, only: time_type, set_date, set_calendar_type, THIRTY_DAY_MONTHS + use MOM_domains, only: MOM_infra_init ! ! !PUBLIC MEMBER FUNCTIONS: implicit none @@ -34,6 +39,8 @@ module ocn_comp_mct ! ! !PRIVATE MODULE VARIABLES + type(ocean_state_type), pointer :: ocn_state => NULL() ! Private state of ocean + type(ocean_public_type), pointer :: ocn_surface => NULL() ! Public surface state of ocean !======================================================================= @@ -52,10 +59,10 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) ! ! !INPUT/OUTPUT PARAMETERS: - type(ESMF_Clock) , intent(inout) :: EClock - type(seq_cdata) , intent(inout) :: cdata_o - type(mct_aVect) , intent(inout) :: x2o_o, o2x_o - character(len=*), optional , intent(in) :: NLFilename ! Namelist filename + type(ESMF_Clock) , intent(inout) :: EClock + type(seq_cdata) , intent(inout) :: cdata_o + type(mct_aVect) , intent(inout) :: x2o_o, o2x_o + character(len=*), optional , intent(in) :: NLFilename ! Namelist filename ! ! !REVISION HISTORY: ! Author: Mariana Vertenstein @@ -65,7 +72,28 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) ! local variables ! !----------------------------------------------------------------------- + type(time_type) :: time_init ! Start time of coupled model's calendar + type(time_type) :: time_in ! Start time for ocean model at initialization + type(ESMF_time) :: current_time + integer :: year, month, day, hour, minute, seconds, rc + character(len=128) :: errMsg + integer :: mpicom + + mpicom = cdata_o%mpicom + + call MOM_infra_init(mpicom) + + call ESMF_ClockGet(EClock, currTime=current_time, rc=rc) + + call ESMF_TimeGet(current_time, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc) + + call set_calendar_type(THIRTY_DAY_MONTHS) + + time_init = set_date(year, month, day, hour, minute, seconds, err_msg=errMsg) + + allocate(ocn_surface) + !call ocean_model_init(ocn_surface, ocn_state, time_init, time_in) !----------------------------------------------------------------------- !EOC From 54f79760e56afc83c1df323763b975505342df62 Mon Sep 17 00:00:00 2001 From: alperaltuntas Date: Mon, 3 Jul 2017 17:11:40 -0600 Subject: [PATCH 04/38] Most initialization working --- config_src/mct_driver/ocn_comp_mct.F90 | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/config_src/mct_driver/ocn_comp_mct.F90 b/config_src/mct_driver/ocn_comp_mct.F90 index 74333e2d42..fe3ccc24f1 100644 --- a/config_src/mct_driver/ocn_comp_mct.F90 +++ b/config_src/mct_driver/ocn_comp_mct.F90 @@ -18,8 +18,9 @@ module ocn_comp_mct ! From MOM6 use ocean_model_mod, only: ocean_state_type, ocean_public_type use ocean_model_mod, only: ocean_model_init - use MOM_time_manager, only: time_type, set_date, set_calendar_type, THIRTY_DAY_MONTHS - use MOM_domains, only: MOM_infra_init + use MOM_time_manager, only: time_type, set_date, set_calendar_type, NOLEAP + use MOM_domains, only: MOM_infra_init, num_pes, root_pe, pe_here + ! ! !PUBLIC MEMBER FUNCTIONS: implicit none @@ -78,22 +79,29 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) integer :: year, month, day, hour, minute, seconds, rc character(len=128) :: errMsg integer :: mpicom + integer :: npes, pe0 + integer :: i mpicom = cdata_o%mpicom call MOM_infra_init(mpicom) - call ESMF_ClockGet(EClock, currTime=current_time, rc=rc) - call ESMF_TimeGet(current_time, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc) - - call set_calendar_type(THIRTY_DAY_MONTHS) + ! we need to confirm this: + call set_calendar_type(NOLEAP) time_init = set_date(year, month, day, hour, minute, seconds, err_msg=errMsg) + time_in = set_date(year, month, day, hour, minute, seconds, err_msg=errMsg) + + npes = num_pes() + pe0 = root_pe() allocate(ocn_surface) + ocn_surface%is_ocean_PE = .true. + allocate(ocn_surface%pelist(npes)) + ocn_surface%pelist(:) = (/(i,i=pe0,pe0+npes)/) - !call ocean_model_init(ocn_surface, ocn_state, time_init, time_in) + call ocean_model_init(ocn_surface, ocn_state, time_init, time_in) !----------------------------------------------------------------------- !EOC From 86936ba6f9e5e1145e7eec38e72c874408036f88 Mon Sep 17 00:00:00 2001 From: Gustavo Marques Date: Wed, 5 Jul 2017 17:09:06 -0600 Subject: [PATCH 05/38] Adds option to read initial temp and salt from separate files This commit adds the option to read initial temperature and salinity fields from separate z-space input files. Before, both T and S had to be in the same file. The input parameter TEMP_SALT_Z_INIT_FILE is kept, so previous configurations do not to be changed. Two new parameters are introduced (TEMP_Z_INIT_FILE and SALT_Z_INIT_FILE). Answers should not change. --- .../MOM_state_initialization.F90 | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/initialization/MOM_state_initialization.F90 b/src/initialization/MOM_state_initialization.F90 index f522d07ae9..25222c2b40 100644 --- a/src/initialization/MOM_state_initialization.F90 +++ b/src/initialization/MOM_state_initialization.F90 @@ -1648,6 +1648,10 @@ subroutine MOM_temp_salt_initialize_from_Z(h, tv, G, GV, PF, dirs) character(len=200) :: filename ! The name of an input file containing temperature ! and salinity in z-space; also used for ice shelf area. + character(len=200) :: tfilename ! The name of an input file containing only temperature + ! in z-space. + character(len=200) :: sfilename ! The name of an input file containing only salinity + ! in z-space. character(len=200) :: inputdir ! The directory where NetCDF input files are. character(len=200) :: mesg, area_varname, ice_shelf_file @@ -1745,15 +1749,24 @@ subroutine MOM_temp_salt_initialize_from_Z(h, tv, G, GV, PF, dirs) call get_param(PF, mod, "TEMP_SALT_Z_INIT_FILE",filename, & "The name of the z-space input file used to initialize \n"//& - "the layer thicknesses, temperatures and salinities.", & - default="temp_salt_z.nc") + "temperatures (T) and salinities (S). If T and S are not \n" //& + "in the same file, TEMP_Z_INIT_FILE and SALT_Z_INIT_FILE \n" //& + "must be set.",default="temp_salt_z.nc") + call get_param(PF, mod, "TEMP_Z_INIT_FILE",tfilename, & + "The name of the z-space input file used to initialize \n"//& + "temperatures, only.", default=trim(filename)) + call get_param(PF, mod, "SALT_Z_INIT_FILE",sfilename, & + "The name of the z-space input file used to initialize \n"//& + "temperatures, only.", default=trim(filename)) filename = trim(inputdir)//trim(filename) + tfilename = trim(inputdir)//trim(tfilename) + sfilename = trim(inputdir)//trim(sfilename) call get_param(PF, mod, "Z_INIT_FILE_PTEMP_VAR", potemp_var, & "The name of the potential temperature variable in \n"//& - "TEMP_SALT_Z_INIT_FILE.", default="ptemp") + "TEMP_Z_INIT_FILE.", default="ptemp") call get_param(PF, mod, "Z_INIT_FILE_SALT_VAR", salin_var, & "The name of the salinity variable in \n"//& - "TEMP_SALT_Z_INIT_FILE.", default="salt") + "SALT_Z_INIT_FILE.", default="salt") call get_param(PF, mod, "Z_INIT_HOMOGENIZE", homogenize, & "If True, then horizontally homogenize the interpolated \n"//& "initial conditions.", default=.false.) @@ -1792,10 +1805,10 @@ subroutine MOM_temp_salt_initialize_from_Z(h, tv, G, GV, PF, dirs) ! value at the northernmost/southernmost latitude. - call horiz_interp_and_extrap_tracer(filename, potemp_var,1.0,1, & + call horiz_interp_and_extrap_tracer(tfilename, potemp_var,1.0,1, & G, temp_z, mask_z, z_in, z_edges_in, missing_value_temp, reentrant_x, tripolar_n, homogenize) - call horiz_interp_and_extrap_tracer(filename, salin_var,1.0,1, & + call horiz_interp_and_extrap_tracer(sfilename, salin_var,1.0,1, & G, salt_z, mask_z, z_in, z_edges_in, missing_value_salt, reentrant_x, tripolar_n, homogenize) kd = size(z_in,1) From fbd405bdbbd270e07940dea6b405c805c6baaa23 Mon Sep 17 00:00:00 2001 From: alperaltuntas Date: Fri, 7 Jul 2017 11:41:52 -0600 Subject: [PATCH 06/38] Added coupler indices module --- config_src/mct_driver/coupler_indices.F90 | 194 ++++++++++++++++++++++ config_src/mct_driver/ocn_comp_mct.F90 | 42 ++++- 2 files changed, 234 insertions(+), 2 deletions(-) create mode 100644 config_src/mct_driver/coupler_indices.F90 diff --git a/config_src/mct_driver/coupler_indices.F90 b/config_src/mct_driver/coupler_indices.F90 new file mode 100644 index 0000000000..bfb42de7f0 --- /dev/null +++ b/config_src/mct_driver/coupler_indices.F90 @@ -0,0 +1,194 @@ +module coupler_indices + + use seq_flds_mod, only : seq_flds_x2o_fields, seq_flds_o2x_fields + use seq_flds_mod, only : seq_flds_i2o_per_cat, ice_ncat + use mct_mod + + implicit none + + private + + public coupler_indices_init + + type, public :: cpl_indices + + ! ocn -> drv + + integer :: o2x_So_t + integer :: o2x_So_u + integer :: o2x_So_v + integer :: o2x_So_s + integer :: o2x_So_dhdx + integer :: o2x_So_dhdy + ! QL, 150526, to wav, boundary layer depth + integer :: o2x_So_bldepth + integer :: o2x_Fioo_q + integer :: o2x_Faoo_fco2_ocn + integer :: o2x_Faoo_fdms_ocn + + ! drv -> ocn + + integer :: x2o_Si_ifrac ! fractional ice wrt ocean + integer :: x2o_So_duu10n ! 10m wind speed squared (m^2/s^2) + integer :: x2o_Sa_pslv ! sea-level pressure (Pa) + integer :: x2o_Sa_co2prog ! bottom atm level prognostic CO2 + integer :: x2o_Sa_co2diag ! bottom atm level diagnostic CO2 + ! QL, 150526, from wav + integer :: x2o_Sw_lamult ! wave model langmuir multiplier + integer :: x2o_Sw_ustokes ! surface Stokes drift, x-component + integer :: x2o_Sw_vstokes ! surface Stokes drift, y-component + integer :: x2o_Foxx_taux ! zonal wind stress (taux) (W/m2 ) + integer :: x2o_Foxx_tauy ! meridonal wind stress (tauy) (W/m2 ) + integer :: x2o_Foxx_swnet ! net short-wave heat flux (W/m2 ) + integer :: x2o_Foxx_sen ! sensible heat flux (W/m2 ) + integer :: x2o_Foxx_lat + integer :: x2o_Foxx_lwup ! longwave radiation (up) (W/m2 ) + integer :: x2o_Faxa_lwdn ! longwave radiation (down) (W/m2 ) + integer :: x2o_Fioi_melth ! heat flux from snow & ice melt (W/m2 ) + integer :: x2o_Fioi_meltw ! snow melt flux (kg/m2/s) + integer :: x2o_Fioi_bcpho ! flux: Black Carbon hydrophobic release from sea ice component + integer :: x2o_Fioi_bcphi ! flux: Black Carbon hydrophilic release from sea ice component + integer :: x2o_Fioi_flxdst ! flux: dust release from sea ice component + integer :: x2o_Fioi_salt ! salt (kg(salt)/m2/s) + integer :: x2o_Foxx_evap ! evaporation flux (kg/m2/s) + integer :: x2o_Faxa_prec + integer :: x2o_Faxa_snow ! water flux due to snow (kg/m2/s) + integer :: x2o_Faxa_rain ! water flux due to rain (kg/m2/s) + integer :: x2o_Faxa_bcphidry ! flux: Black Carbon hydrophilic dry deposition + integer :: x2o_Faxa_bcphodry ! flux: Black Carbon hydrophobic dry deposition + integer :: x2o_Faxa_bcphiwet ! flux: Black Carbon hydrophilic wet deposition + integer :: x2o_Faxa_ocphidry ! flux: Organic Carbon hydrophilic dry deposition + integer :: x2o_Faxa_ocphodry ! flux: Organic Carbon hydrophobic dry deposition + integer :: x2o_Faxa_ocphiwet ! flux: Organic Carbon hydrophilic dry deposition + integer :: x2o_Faxa_dstwet1 ! flux: Size 1 dust -- wet deposition + integer :: x2o_Faxa_dstwet2 ! flux: Size 2 dust -- wet deposition + integer :: x2o_Faxa_dstwet3 ! flux: Size 3 dust -- wet deposition + integer :: x2o_Faxa_dstwet4 ! flux: Size 4 dust -- wet deposition + integer :: x2o_Faxa_dstdry1 ! flux: Size 1 dust -- dry deposition + integer :: x2o_Faxa_dstdry2 ! flux: Size 2 dust -- dry deposition + integer :: x2o_Faxa_dstdry3 ! flux: Size 3 dust -- dry deposition + integer :: x2o_Faxa_dstdry4 ! flux: Size 4 dust -- dry deposition + integer :: x2o_Foxx_rofl ! river runoff flux (kg/m2/s) + integer :: x2o_Foxx_rofi ! ice runoff flux (kg/m2/s) + + ! optional per thickness category fields + + integer, dimension(:), allocatable :: x2o_frac_col ! fraction of ocean cell, per column + integer, dimension(:), allocatable :: x2o_fracr_col ! fraction of ocean cell used in radiation computations, per column + integer, dimension(:), allocatable :: x2o_qsw_fracr_col ! qsw * fracr, per column + + end type cpl_indices + + ! Module data for storing + type(cpl_indices), public :: ind + +contains + + subroutine coupler_indices_init( ) + + type(mct_aVect) :: o2x ! temporary + type(mct_aVect) :: x2o ! temporary + + integer :: ncat ! thickness category index + character(len=2) :: cncat ! character version of ncat + integer :: ncol ! column index + integer :: mcog_ncols + integer :: lmcog_flds_sent + + ! Determine attribute vector indices + + ! create temporary attribute vectors + call mct_aVect_init(x2o, rList=seq_flds_x2o_fields, lsize=1) + call mct_aVect_init(o2x, rList=seq_flds_o2x_fields, lsize=1) + + ind%o2x_So_t = mct_avect_indexra(o2x,'So_t') + ind%o2x_So_u = mct_avect_indexra(o2x,'So_u') + ind%o2x_So_v = mct_avect_indexra(o2x,'So_v') + ind%o2x_So_s = mct_avect_indexra(o2x,'So_s') + ind%o2x_So_dhdx = mct_avect_indexra(o2x,'So_dhdx') + ind%o2x_So_dhdy = mct_avect_indexra(o2x,'So_dhdy') + ! QL, 150526, to wav, boundary layer depth + ind%o2x_So_bldepth = mct_avect_indexra(o2x,'So_bldepth') + ind%o2x_Fioo_q = mct_avect_indexra(o2x,'Fioo_q') + ind%o2x_Faoo_fco2_ocn = mct_avect_indexra(o2x,'Faoo_fco2_ocn',perrWith='quiet') + ind%o2x_Faoo_fdms_ocn = mct_avect_indexra(o2x,'Faoo_fdms_ocn',perrWith='quiet') + ind%x2o_Si_ifrac = mct_avect_indexra(x2o,'Si_ifrac') + ind%x2o_Sa_pslv = mct_avect_indexra(x2o,'Sa_pslv') + ind%x2o_So_duu10n = mct_avect_indexra(x2o,'So_duu10n') + ! QL, 150526, from wav + ind%x2o_Sw_lamult = mct_avect_indexra(x2o,'Sw_lamult') + ind%x2o_Sw_ustokes = mct_avect_indexra(x2o,'Sw_ustokes') + ind%x2o_Sw_vstokes = mct_avect_indexra(x2o,'Sw_vstokes') + + ind%x2o_Foxx_tauy = mct_avect_indexra(x2o,'Foxx_tauy') + ind%x2o_Foxx_taux = mct_avect_indexra(x2o,'Foxx_taux') + ind%x2o_Foxx_swnet = mct_avect_indexra(x2o,'Foxx_swnet') + ind%x2o_Foxx_lat = mct_avect_indexra(x2o,'Foxx_lat') + ind%x2o_Foxx_sen = mct_avect_indexra(x2o,'Foxx_sen') + ind%x2o_Foxx_lwup = mct_avect_indexra(x2o,'Foxx_lwup') + ind%x2o_Faxa_lwdn = mct_avect_indexra(x2o,'Faxa_lwdn') + ind%x2o_Fioi_melth = mct_avect_indexra(x2o,'Fioi_melth') + ind%x2o_Fioi_meltw = mct_avect_indexra(x2o,'Fioi_meltw') + ind%x2o_Fioi_salt = mct_avect_indexra(x2o,'Fioi_salt') + ind%x2o_Fioi_bcpho = mct_avect_indexra(x2o,'Fioi_bcpho') + ind%x2o_Fioi_bcphi = mct_avect_indexra(x2o,'Fioi_bcphi') + ind%x2o_Fioi_flxdst = mct_avect_indexra(x2o,'Fioi_flxdst') + ind%x2o_Faxa_prec = mct_avect_indexra(x2o,'Faxa_prec') + ind%x2o_Faxa_snow = mct_avect_indexra(x2o,'Faxa_snow') + ind%x2o_Faxa_rain = mct_avect_indexra(x2o,'Faxa_rain') + ind%x2o_Foxx_evap = mct_avect_indexra(x2o,'Foxx_evap') + ind%x2o_Foxx_rofl = mct_avect_indexra(x2o,'Foxx_rofl') + ind%x2o_Foxx_rofi = mct_avect_indexra(x2o,'Foxx_rofi') + ind%x2o_Faxa_bcphidry = mct_avect_indexra(x2o,'Faxa_bcphidry') + ind%x2o_Faxa_bcphodry = mct_avect_indexra(x2o,'Faxa_bcphodry') + ind%x2o_Faxa_bcphiwet = mct_avect_indexra(x2o,'Faxa_bcphiwet') + ind%x2o_Faxa_ocphidry = mct_avect_indexra(x2o,'Faxa_ocphidry') + ind%x2o_Faxa_ocphodry = mct_avect_indexra(x2o,'Faxa_ocphodry') + ind%x2o_Faxa_ocphiwet = mct_avect_indexra(x2o,'Faxa_ocphiwet') + ind%x2o_Faxa_dstdry1 = mct_avect_indexra(x2o,'Faxa_dstdry1') + ind%x2o_Faxa_dstdry2 = mct_avect_indexra(x2o,'Faxa_dstdry2') + ind%x2o_Faxa_dstdry3 = mct_avect_indexra(x2o,'Faxa_dstdry3') + ind%x2o_Faxa_dstdry4 = mct_avect_indexra(x2o,'Faxa_dstdry4') + ind%x2o_Faxa_dstwet1 = mct_avect_indexra(x2o,'Faxa_dstwet1') + ind%x2o_Faxa_dstwet2 = mct_avect_indexra(x2o,'Faxa_dstwet2') + ind%x2o_Faxa_dstwet3 = mct_avect_indexra(x2o,'Faxa_dstwet3') + ind%x2o_Faxa_dstwet4 = mct_avect_indexra(x2o,'Faxa_dstwet4') + ind%x2o_Sa_co2prog = mct_avect_indexra(x2o,'Sa_co2prog',perrWith='quiet') + ind%x2o_Sa_co2diag = mct_avect_indexra(x2o,'Sa_co2diag',perrWith='quiet') + + ! optional per thickness category fields + + ! convert cpl indices to mcog column indices + ! this implementation only handles columns due to ice thickness categories + + lmcog_flds_sent = seq_flds_i2o_per_cat + + if (seq_flds_i2o_per_cat) then + mcog_ncols = ice_ncat+1 + allocate(ind%x2o_frac_col(mcog_ncols)) + allocate(ind%x2o_fracr_col(mcog_ncols)) + allocate(ind%x2o_qsw_fracr_col(mcog_ncols)) + + ncol = 1 + ind%x2o_frac_col(ncol) = mct_avect_indexra(x2o,'Sf_afrac') + ind%x2o_fracr_col(ncol) = mct_avect_indexra(x2o,'Sf_afracr') + ind%x2o_qsw_fracr_col(ncol) = mct_avect_indexra(x2o,'Foxx_swnet_afracr') + + do ncat = 1, ice_ncat + write(cncat,'(i2.2)') ncat + ncol = ncat+1 + ind%x2o_frac_col(ncol) = mct_avect_indexra(x2o,'Si_ifrac_'//cncat) + ind%x2o_fracr_col(ncol) = ind%x2o_frac_col(ncol) + ind%x2o_qsw_fracr_col(ncol) = mct_avect_indexra(x2o,'PFioi_swpen_ifrac_'//cncat) + enddo + else + mcog_ncols = 1 + endif + + call mct_aVect_clean(x2o) + call mct_aVect_clean(o2x) + + + end subroutine coupler_indices_init + +end module coupler_indices diff --git a/config_src/mct_driver/ocn_comp_mct.F90 b/config_src/mct_driver/ocn_comp_mct.F90 index fe3ccc24f1..b3c760c0fd 100644 --- a/config_src/mct_driver/ocn_comp_mct.F90 +++ b/config_src/mct_driver/ocn_comp_mct.F90 @@ -14,12 +14,18 @@ module ocn_comp_mct use esmf use seq_cdata_mod use mct_mod - + use seq_infodata_mod, only: seq_infodata_type, & + seq_infodata_GetData, & + seq_infodata_start_type_start, & + seq_infodata_start_type_cont, & + seq_infodata_start_type_brnch + ! From MOM6 use ocean_model_mod, only: ocean_state_type, ocean_public_type use ocean_model_mod, only: ocean_model_init use MOM_time_manager, only: time_type, set_date, set_calendar_type, NOLEAP use MOM_domains, only: MOM_infra_init, num_pes, root_pe, pe_here + use coupler_indices, only: coupler_indices_init ! ! !PUBLIC MEMBER FUNCTIONS: @@ -43,6 +49,9 @@ module ocn_comp_mct type(ocean_state_type), pointer :: ocn_state => NULL() ! Private state of ocean type(ocean_public_type), pointer :: ocn_surface => NULL() ! Public surface state of ocean + type(seq_infodata_type), pointer :: & + infodata + !======================================================================= contains @@ -78,13 +87,18 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) type(ESMF_time) :: current_time integer :: year, month, day, hour, minute, seconds, rc character(len=128) :: errMsg + character(len=384) :: runid + character(len=384) :: runtype + character(len=32) :: starttype ! infodata start type integer :: mpicom integer :: npes, pe0 integer :: i - mpicom = cdata_o%mpicom + ! Initialize MOM6 + mpicom = cdata_o%mpicom call MOM_infra_init(mpicom) + call ESMF_ClockGet(EClock, currTime=current_time, rc=rc) call ESMF_TimeGet(current_time, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc) ! we need to confirm this: @@ -101,8 +115,32 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) allocate(ocn_surface%pelist(npes)) ocn_surface%pelist(:) = (/(i,i=pe0,pe0+npes)/) + ! initialize the model run call ocean_model_init(ocn_surface, ocn_state, time_init, time_in) + ! set infodata, a cdata pointer + call seq_cdata_setptrs(cdata_o, infodata=infodata) + + ! initialize coupler indices + call coupler_indices_init() + + ! get runid and starttype: + call seq_infodata_GetData( infodata, case_name=runid ) + call seq_infodata_GetData( infodata, start_type=starttype) + + + if ( trim(starttype) == trim(seq_infodata_start_type_start)) then + runtype = "initial" + else if (trim(starttype) == trim(seq_infodata_start_type_cont) ) then + runtype = "continue" + else if (trim(starttype) == trim(seq_infodata_start_type_brnch)) then + runtype = "branch" + else + write(*,*) 'ocn_comp_mct ERROR: unknown starttype' + call exit(0) + end if + + !----------------------------------------------------------------------- !EOC From 37e73567377b742a3e701dc00c81e1d5e8d8adf9 Mon Sep 17 00:00:00 2001 From: alperaltuntas Date: Thu, 13 Jul 2017 08:43:04 -0600 Subject: [PATCH 07/38] Added ocn_import_export.F90 --- config_src/mct_driver/ocn_comp_mct.F90 | 243 ++++++++++++++++---- config_src/mct_driver/ocn_import_export.F90 | 140 +++++++++++ 2 files changed, 341 insertions(+), 42 deletions(-) create mode 100644 config_src/mct_driver/ocn_import_export.F90 diff --git a/config_src/mct_driver/ocn_comp_mct.F90 b/config_src/mct_driver/ocn_comp_mct.F90 index b3c760c0fd..8e4dee42c8 100644 --- a/config_src/mct_driver/ocn_comp_mct.F90 +++ b/config_src/mct_driver/ocn_comp_mct.F90 @@ -6,26 +6,32 @@ module ocn_comp_mct ! !INTERFACE: ! !DESCRIPTION: -! This is the main driver for the MOM6 in CIME +! This is the main driver for MOM6 in CIME ! ! !REVISION HISTORY: ! ! !USES: - use esmf - use seq_cdata_mod - use mct_mod - use seq_infodata_mod, only: seq_infodata_type, & - seq_infodata_GetData, & - seq_infodata_start_type_start, & - seq_infodata_start_type_cont, & - seq_infodata_start_type_brnch + use esmf + use seq_cdata_mod + use mct_mod + use seq_flds_mod, only: seq_flds_x2o_fields, & + seq_flds_o2x_fields + use seq_infodata_mod, only: seq_infodata_type, & + seq_infodata_GetData, & + seq_infodata_start_type_start, & + seq_infodata_start_type_cont, & + seq_infodata_start_type_brnch + use seq_comm_mct, only: seq_comm_name, seq_comm_inst, seq_comm_suffix + use perf_mod, only: t_startf, t_stopf + ! From MOM6 - use ocean_model_mod, only: ocean_state_type, ocean_public_type - use ocean_model_mod, only: ocean_model_init - use MOM_time_manager, only: time_type, set_date, set_calendar_type, NOLEAP - use MOM_domains, only: MOM_infra_init, num_pes, root_pe, pe_here - use coupler_indices, only: coupler_indices_init + use ocean_model_mod, only: ocean_state_type, ocean_public_type + use ocean_model_mod, only: ocean_model_init + use MOM_time_manager, only: time_type, set_date, set_calendar_type, NOLEAP + use MOM_domains, only: MOM_infra_init, num_pes, root_pe, pe_here + use coupler_indices, only: coupler_indices_init + use ocn_import_export, only: SBUFF_SUM ! ! !PUBLIC MEMBER FUNCTIONS: @@ -43,13 +49,14 @@ module ocn_comp_mct ! !EOP ! !PRIVATE MODULE FUNCTIONS: + private :: ocn_SetGSMap_mct + private :: ocn_domain_mct -! ! !PRIVATE MODULE VARIABLES - type(ocean_state_type), pointer :: ocn_state => NULL() ! Private state of ocean - type(ocean_public_type), pointer :: ocn_surface => NULL() ! Public surface state of ocean + type(ocean_state_type), pointer :: ocn_state => NULL() ! Private state of ocean + type(ocean_public_type), pointer :: ocn_surface => NULL() ! Public surface state of ocean - type(seq_infodata_type), pointer :: & + type(seq_infodata_type), pointer :: & infodata !======================================================================= @@ -90,19 +97,69 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) character(len=384) :: runid character(len=384) :: runtype character(len=32) :: starttype ! infodata start type - integer :: mpicom + integer :: mpicom_ocn integer :: npes, pe0 integer :: i + integer :: lsize, nsend, nrecv + + ! mct variables (these are local for now) + integer :: MOM_MCT_ID + type(mct_gsMap), pointer :: MOM_MCT_gsMap ! 2d, points to cdata + type(mct_gGrid), pointer :: MOM_MCT_dom ! 2d, points to cdata + type(mct_gsMap) :: MOM_MCT_gsMap3d ! for 3d streams, local + type(mct_gGrid) :: MOM_MCT_dom3d ! for 3d streams, local + + ! instance control vars (these are local for now) + integer(kind=4) :: inst_index + character(len=16) :: inst_name + character(len=16) :: inst_suffix + + !!!DANGER!!!: change the following vars with the corresponding MOM6 vars + integer :: km=62 ! number of vertical levels +!----------------------------------------------------------------------- + + ! set (actually, get from mct) the cdata pointers: + call seq_cdata_setptrs(cdata_o, id=MOM_MCT_ID, mpicom=mpicom_ocn, infodata=infodata) - ! Initialize MOM6 - mpicom = cdata_o%mpicom - call MOM_infra_init(mpicom) + !--------------------------------------------------------------------- + ! Initialize the model run + !--------------------------------------------------------------------- + + call coupler_indices_init() + + call seq_infodata_GetData( infodata, case_name=runid ) + + call seq_infodata_GetData( infodata, start_type=starttype) + + if ( trim(starttype) == trim(seq_infodata_start_type_start)) then + runtype = "initial" + else if (trim(starttype) == trim(seq_infodata_start_type_cont) ) then + runtype = "continue" + else if (trim(starttype) == trim(seq_infodata_start_type_brnch)) then + runtype = "branch" + else + write(*,*) 'ocn_comp_mct ERROR: unknown starttype' + call exit(0) + end if + + ! instance control + + inst_name = seq_comm_name(MOM_MCT_ID) + inst_index = seq_comm_inst(MOM_MCT_ID) + inst_suffix = seq_comm_suffix(MOM_MCT_ID) + + !--------------------------------------------------------------------- + ! Initialize MOM6 + !--------------------------------------------------------------------- + + call t_startf('MOM_init') + + call MOM_infra_init(mpicom_ocn) call ESMF_ClockGet(EClock, currTime=current_time, rc=rc) call ESMF_TimeGet(current_time, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc) - ! we need to confirm this: - call set_calendar_type(NOLEAP) + call set_calendar_type(NOLEAP) !TODO: confirm this time_init = set_date(year, month, day, hour, minute, seconds, err_msg=errMsg) time_in = set_date(year, month, day, hour, minute, seconds, err_msg=errMsg) @@ -115,30 +172,59 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) allocate(ocn_surface%pelist(npes)) ocn_surface%pelist(:) = (/(i,i=pe0,pe0+npes)/) - ! initialize the model run + ! initialize the MOM6 model call ocean_model_init(ocn_surface, ocn_state, time_init, time_in) - ! set infodata, a cdata pointer - call seq_cdata_setptrs(cdata_o, infodata=infodata) + call t_stopf('MOM_init') + + !--------------------------------------------------------------------- + ! Initialize MCT attribute vectors and indices + !--------------------------------------------------------------------- + + call t_startf('MOM_mct_init') + + ! Set mct global seg maps: + + call ocn_SetGSMap_mct(mpicom_ocn, MOM_MCT_ID, MOM_MCT_GSMap, MOM_MCT_GSMap3d) + lsize = mct_gsMap_lsize(MOM_MCT_gsmap, mpicom_ocn) + + ! Initialize mct ocn domain (needs ocn initialization info) + + call ocn_domain_mct(lsize, MOM_MCT_gsmap, MOM_MCT_dom) + call ocn_domain_mct(lsize*km, MOM_MCT_gsmap3d, MOM_MCT_dom3d) + + ! Inialize mct attribute vectors + + ! Initialize the mct attribute vector x2o_o, given Attribute list and length: + call mct_aVect_init(x2o_o, rList=seq_flds_x2o_fields, lsize=lsize) + ! set the mct attribute vector x2o_o to zero: + call mct_aVect_zero(x2o_o) + + ! Initialize the mct attribute vector o2x_o, given Attribute list and length: + call mct_aVect_init(o2x_o, rList=seq_flds_o2x_fields, lsize=lsize) + ! set the mct attribute vector o2x_o to zero: + call mct_aVect_zero(o2x_o) + + nsend = mct_avect_nRattr(o2x_o) + nrecv = mct_avect_nRattr(x2o_o) + !allocate (SBUFF_SUM(nx_block,ny_block,max_blocks_clinic,nsend)) + + + + + + + + - ! initialize coupler indices - call coupler_indices_init() - ! get runid and starttype: - call seq_infodata_GetData( infodata, case_name=runid ) - call seq_infodata_GetData( infodata, start_type=starttype) - if ( trim(starttype) == trim(seq_infodata_start_type_start)) then - runtype = "initial" - else if (trim(starttype) == trim(seq_infodata_start_type_cont) ) then - runtype = "continue" - else if (trim(starttype) == trim(seq_infodata_start_type_brnch)) then - runtype = "branch" - else - write(*,*) 'ocn_comp_mct ERROR: unknown starttype' - call exit(0) - end if + + + + call t_stopf('MOM_mct_init') + !----------------------------------------------------------------------- @@ -209,6 +295,79 @@ subroutine ocn_final_mct( EClock, cdata_o, x2o_o, o2x_o) end subroutine ocn_final_mct +!*********************************************************************** +!BOP +!IROUTINE: ocn_SetGSMap_mct +! !INTERFACE: + + subroutine ocn_SetGSMap_mct(mpicom_ocn, MOM_MCT_ID, gsMap_ocn, gsMap3d_ocn) + +! !DESCRIPTION: +! This routine mct global seg maps for the MOM decomposition +! +! !REVISION HISTORY: +! same as module + +! !INPUT/OUTPUT PARAMETERS: + + implicit none + 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 + +!EOP +!BOC +!----------------------------------------------------------------------- +! +! local variables +! +!----------------------------------------------------------------------- + + + +!----------------------------------------------------------------------- +!EOC + + end subroutine ocn_SetGSMap_mct + + +!*********************************************************************** +!BOP +! !IROUTINE: ocn_domain_mct +! !INTERFACE: + + subroutine ocn_domain_mct( lsize, gsMap_ocn, dom_ocn) + +! !DESCRIPTION: +! This routine mct global seg maps for the pop decomposition +! +! !REVISION HISTORY: +! same as module +! +! !INPUT/OUTPUT PARAMETERS: + + implicit none + integer , intent(in) :: lsize + type(mct_gsMap), intent(in) :: gsMap_ocn + type(mct_ggrid), intent(inout) :: dom_ocn + +!EOP +!BOC +!----------------------------------------------------------------------- +! +! local variables +! +!----------------------------------------------------------------------- + + + +!----------------------------------------------------------------------- +!EOC + + end subroutine ocn_domain_mct + + end module ocn_comp_mct !||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| diff --git a/config_src/mct_driver/ocn_import_export.F90 b/config_src/mct_driver/ocn_import_export.F90 new file mode 100644 index 0000000000..6fd16835fb --- /dev/null +++ b/config_src/mct_driver/ocn_import_export.F90 @@ -0,0 +1,140 @@ +module ocn_import_export + + implicit none + public + save + + ! accumulated sum of send buffer quantities for averaging before being sent + !real (r8), dimension(:,:,:,:), allocatable :: SBUFF_SUM + !real (r8) :: tlast_coupled + + !TODO: update the types of following vars + double precision, dimension(:,:,:,:), allocatable :: SBUFF_SUM + double precision :: tlast_coupled +contains + +!*********************************************************************** +!BOP +! !IROUTINE: ocn_import +! !INTERFACE: + + subroutine ocn_import(x2o, ldiag_cpl, errorCode) + +! !DESCRIPTION: +!----------------------------------------------------------------------- +! This routine receives message from cpl7 driver +! +! The following fields are always received from the coupler: +! +! o taux -- zonal wind stress (taux) (W/m2 ) +! o tauy -- meridonal wind stress (tauy) (W/m2 ) +! o snow -- water flux due to snow (kg/m2/s) +! o rain -- water flux due to rain (kg/m2/s) +! o evap -- evaporation flux (kg/m2/s) +! o meltw -- snow melt flux (kg/m2/s) +! o salt -- salt (kg(salt)/m2/s) +! o swnet -- net short-wave heat flux (W/m2 ) +! o sen -- sensible heat flux (W/m2 ) +! o lwup -- longwave radiation (up) (W/m2 ) +! o lwdn -- longwave radiation (down) (W/m2 ) +! o melth -- heat flux from snow&ice melt (W/m2 ) +! o ifrac -- ice fraction +! o rofl -- river runoff flux (kg/m2/s) +! o rofi -- ice runoff flux (kg/m2/s) +! +! The following fields are sometimes received from the coupler, +! depending on model options: +! +! o pslv -- sea-level pressure (Pa) +! o duu10n -- 10m wind speed squared (m^2/s^2) +! o co2prog-- bottom atm level prognostic co2 +! o co2diag-- bottom atm level diagnostic co2 +! +!----------------------------------------------------------------------- +! +! !REVISION HISTORY: +! same as module + +! !INPUT/OUTPUT PARAMETERS: + + !real(r8) , intent(inout) :: x2o(:,:) + !logical (log_kind) , intent(in) :: ldiag_cpl + !integer (POP_i4) , intent(out) :: errorCode ! returned error code + + !TODO: update the types of following params + double precision, intent(inout) :: x2o(:,:) + logical, intent(in) :: ldiag_cpl + integer, intent(out) :: errorCode ! returned error code + +!EOP +!BOC +!----------------------------------------------------------------------- +! +! local variables +! +!----------------------------------------------------------------------- + + + + + + + + + + +!----------------------------------------------------------------------- +!EOC + + end subroutine ocn_import + +!*********************************************************************** +!BOP +! !IROUTINE: ocn_export_mct +! !INTERFACE: + + subroutine ocn_export(o2x, ldiag_cpl, errorCode) + +! !DESCRIPTION: +! This routine calls the routines necessary to send MOM6 fields to +! the CCSM cpl7 driver +! +! !REVISION HISTORY: +! same as module +! +! !INPUT/OUTPUT PARAMETERS: + + !real(r8) , intent(inout) :: o2x(:,:) + !logical (log_kind) , intent(in) :: ldiag_cpl + !integer (POP_i4) , intent(out) :: errorCode ! returned error code + + !TODO: update the types of following params + double precision, intent(inout) :: o2x(:,:) + logical, intent(in) :: ldiag_cpl + integer, intent(out) :: errorCode ! returned error code + +!EOP +!BOC +!----------------------------------------------------------------------- +! +! local variables +! +!----------------------------------------------------------------------- + + + + + + + + +!----------------------------------------------------------------------- +!EOC + + end subroutine ocn_export + +!*********************************************************************** + + +end module ocn_import_export + From 57e60868208767bc4720974ce5b8e30451957698 Mon Sep 17 00:00:00 2001 From: alperaltuntas Date: Thu, 13 Jul 2017 17:35:33 -0600 Subject: [PATCH 08/38] Added methods to return domain/grid shape - get_global_shape() returns niglobal, njglobal from domain type. - get_global_grid_shape() returns niglobal, njglobal by calling get_global_shape(). - This avoids exposing members inside opaque types otherwise needed for initializing under MCT. --- src/core/MOM_grid.F90 | 13 ++++++++++++- src/framework/MOM_domains.F90 | 13 ++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/core/MOM_grid.F90 b/src/core/MOM_grid.F90 index 6d5597ce4e..0f01700c01 100644 --- a/src/core/MOM_grid.F90 +++ b/src/core/MOM_grid.F90 @@ -5,6 +5,7 @@ module MOM_grid use MOM_hor_index, only : hor_index_type, hor_index_init use MOM_domains, only : MOM_domain_type, get_domain_extent, compute_block_extent +use MOM_domains, only : get_global_shape use MOM_error_handler, only : MOM_error, MOM_mesg, FATAL use MOM_file_parser, only : get_param, log_param, log_version, param_file_type @@ -13,7 +14,7 @@ module MOM_grid #include public MOM_grid_init, MOM_grid_end, set_derived_metrics, set_first_direction -public isPointInCell, hor_index_type +public isPointInCell, hor_index_type, get_global_grid_size !> Ocean grid type. See mom_grid for details. type, public :: ocean_grid_type @@ -443,6 +444,16 @@ subroutine set_first_direction(G, y_first) G%first_direction = y_first end subroutine set_first_direction +!> Return global shape of horizontal grid +subroutine get_global_grid_size(G, niglobal, njglobal) + type(ocean_grid_type), intent(inout) :: G !< The horizontal grid type + integer, intent(out) :: niglobal !< i-index global size of grid + integer, intent(out) :: njglobal !< j-index global size of grid + + call get_global_shape(G%domain, niglobal, njglobal) + +end subroutine get_global_grid_size + !> Allocate memory used by the ocean_grid_type and related structures. subroutine allocate_metrics(G) type(ocean_grid_type), intent(inout) :: G !< The horizontal grid type diff --git a/src/framework/MOM_domains.F90 b/src/framework/MOM_domains.F90 index ca1dc281a2..5e872d0a72 100644 --- a/src/framework/MOM_domains.F90 +++ b/src/framework/MOM_domains.F90 @@ -60,7 +60,7 @@ module MOM_domains public :: To_East, To_West, To_North, To_South, To_All, Omit_Corners public :: create_group_pass, do_group_pass, group_pass_type public :: start_group_pass, complete_group_pass -public :: compute_block_extent +public :: compute_block_extent, get_global_shape interface pass_var module procedure pass_var_3d, pass_var_2d @@ -1599,4 +1599,15 @@ subroutine get_domain_extent(Domain, isc, iec, jsc, jec, isd, ied, jsd, jed, & end subroutine get_domain_extent +!> Returns the global shape of h-point arrays +subroutine get_global_shape(domain, niglobal, njglobal) + type(MOM_domain_type), intent(in) :: domain !< MOM domain + integer, intent(out) :: niglobal !< i-index global size of h-point arrays + integer, intent(out) :: njglobal !< j-index global size of h-point arrays + + niglobal = domain%niglobal + njglobal = domain%njglobal + +end subroutine get_global_shape + end module MOM_domains From 5df3bc3ba707fdf9d1f5b214997479eeecfbba79 Mon Sep 17 00:00:00 2001 From: alperaltuntas Date: Thu, 13 Jul 2017 17:37:09 -0600 Subject: [PATCH 09/38] Added method to point ponters to members of ocean_state_type - To initialize within the MCT coupler we need access to members of ocean_state_type which are private. This method allows us to have local pointers to those members. --- config_src/coupled_driver/ocean_model_MOM.F90 | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/config_src/coupled_driver/ocean_model_MOM.F90 b/config_src/coupled_driver/ocean_model_MOM.F90 index 0f0f1f2622..dfcdded6f8 100644 --- a/config_src/coupled_driver/ocean_model_MOM.F90 +++ b/config_src/coupled_driver/ocean_model_MOM.F90 @@ -89,7 +89,9 @@ module ocean_model_mod public ocean_model_restart public ice_ocn_bnd_type_chksum public ocean_public_type_chksum -public ocean_model_data_get +public ocean_model_data_get +public get_state_pointers + interface ocean_model_data_get module procedure ocean_model_data1D_get module procedure ocean_model_data2D_get @@ -1083,4 +1085,13 @@ subroutine ocean_public_type_chksum(id, timestep, ocn) 100 FORMAT(" CHECKSUM::",A20," = ",Z20) end subroutine ocean_public_type_chksum +!> Returns pointers to objects within ocean_state_type +subroutine get_state_pointers(OS, grid) + type(ocean_state_type), pointer :: OS !< Ocean state type + type(ocean_grid_type), optional, pointer :: grid !< Ocean grid + + if (present(grid)) grid => OS%grid + +end subroutine get_state_pointers + end module ocean_model_mod From aba7dc2a3a1c52233ec5c7382858b0382395ba75 Mon Sep 17 00:00:00 2001 From: alperaltuntas Date: Thu, 13 Jul 2017 17:42:00 -0600 Subject: [PATCH 10/38] Completed ocn_init_mct --- config_src/mct_driver/ocn_comp_mct.F90 | 173 ++++++++++++++++--------- 1 file changed, 111 insertions(+), 62 deletions(-) diff --git a/config_src/mct_driver/ocn_comp_mct.F90 b/config_src/mct_driver/ocn_comp_mct.F90 index 8e4dee42c8..5aa1cd914b 100644 --- a/config_src/mct_driver/ocn_comp_mct.F90 +++ b/config_src/mct_driver/ocn_comp_mct.F90 @@ -20,18 +20,22 @@ module ocn_comp_mct seq_infodata_GetData, & seq_infodata_start_type_start, & seq_infodata_start_type_cont, & - seq_infodata_start_type_brnch + seq_infodata_start_type_brnch, & + seq_infodata_PutData use seq_comm_mct, only: seq_comm_name, seq_comm_inst, seq_comm_suffix + use seq_timemgr_mod, only: seq_timemgr_EClockGetData use perf_mod, only: t_startf, t_stopf - - + + ! From MOM6 use ocean_model_mod, only: ocean_state_type, ocean_public_type - use ocean_model_mod, only: ocean_model_init - use MOM_time_manager, only: time_type, set_date, set_calendar_type, NOLEAP + use ocean_model_mod, only: ocean_model_init, get_state_pointers use MOM_domains, only: MOM_infra_init, num_pes, root_pe, pe_here + use MOM_grid, only: ocean_grid_type, get_global_grid_size + use MOM_error_handler, only: MOM_error, FATAL, is_root_pe + use MOM_time_manager, only: time_type, set_date, set_calendar_type, NOLEAP use coupler_indices, only: coupler_indices_init - use ocn_import_export, only: SBUFF_SUM + use ocn_import_export, only: SBUFF_SUM, ocn_Export, mom_sum_buffer ! ! !PUBLIC MEMBER FUNCTIONS: @@ -72,7 +76,7 @@ module ocn_comp_mct subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) ! ! !DESCRIPTION: -! Initialize POP +! Initialize POP ! ! !INPUT/OUTPUT PARAMETERS: @@ -99,31 +103,50 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) character(len=32) :: starttype ! infodata start type integer :: mpicom_ocn integer :: npes, pe0 - integer :: i + integer :: i, errorCode integer :: lsize, nsend, nrecv + logical :: ldiag_cpl = .false. ! mct variables (these are local for now) integer :: MOM_MCT_ID - type(mct_gsMap), pointer :: MOM_MCT_gsMap ! 2d, points to cdata - type(mct_gGrid), pointer :: MOM_MCT_dom ! 2d, points to cdata + type(mct_gsMap), pointer :: MOM_MCT_gsMap => NULL() ! 2d, points to cdata + type(mct_gGrid), pointer :: MOM_MCT_dom => NULL() ! 2d, points to cdata type(mct_gsMap) :: MOM_MCT_gsMap3d ! for 3d streams, local type(mct_gGrid) :: MOM_MCT_dom3d ! for 3d streams, local + ! time management + integer :: ocn_cpl_dt + real (kind=8) :: mom_cpl_dt + real (kind=8), parameter :: & + seconds_in_minute = 60.0d0, & + seconds_in_hour = 3600.0d0, & + seconds_in_day = 86400.0d0, & + minutes_in_hour = 60.0d0 + + ! instance control vars (these are local for now) integer(kind=4) :: inst_index character(len=16) :: inst_name character(len=16) :: inst_suffix !!!DANGER!!!: change the following vars with the corresponding MOM6 vars - integer :: km=62 ! number of vertical levels + integer :: km=62 ! number of vertical levels + integer :: nx_block=0, ny_block=0 ! size of block domain in x,y dir including ghost cells + integer :: nx_global, ny_global! size of block domain in x,y dir including ghost cells + integer :: max_blocks_clinic=0 !max number of blocks per processor in each distribution + integer :: ncouple_per_day = 24 + logical :: lsend_precip_fact ! if T,send precip_fact to cpl for use in fw balance + ! (partially-coupled option) + !----------------------------------------------------------------------- ! set (actually, get from mct) the cdata pointers: - call seq_cdata_setptrs(cdata_o, id=MOM_MCT_ID, mpicom=mpicom_ocn, infodata=infodata) + call seq_cdata_setptrs(cdata_o, id=MOM_MCT_ID, mpicom=mpicom_ocn, & + gsMap=MOM_MCT_gsMap, dom=MOM_MCT_dom, infodata=infodata) !--------------------------------------------------------------------- - ! Initialize the model run + ! Initialize the model run !--------------------------------------------------------------------- call coupler_indices_init() @@ -150,14 +173,14 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) inst_suffix = seq_comm_suffix(MOM_MCT_ID) !--------------------------------------------------------------------- - ! Initialize MOM6 + ! Initialize MOM6 !--------------------------------------------------------------------- call t_startf('MOM_init') call MOM_infra_init(mpicom_ocn) - call ESMF_ClockGet(EClock, currTime=current_time, rc=rc) + call ESMF_ClockGet(EClock, currTime=current_time, rc=rc) call ESMF_TimeGet(current_time, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc) call set_calendar_type(NOLEAP) !TODO: confirm this @@ -178,15 +201,15 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) call t_stopf('MOM_init') !--------------------------------------------------------------------- - ! Initialize MCT attribute vectors and indices + ! Initialize MCT attribute vectors and indices !--------------------------------------------------------------------- call t_startf('MOM_mct_init') ! Set mct global seg maps: - call ocn_SetGSMap_mct(mpicom_ocn, MOM_MCT_ID, MOM_MCT_GSMap, MOM_MCT_GSMap3d) - lsize = mct_gsMap_lsize(MOM_MCT_gsmap, mpicom_ocn) + call ocn_SetGSMap_mct(mpicom_ocn, MOM_MCT_ID, MOM_MCT_GSMap, MOM_MCT_GSMap3d) + lsize = mct_gsMap_lsize(MOM_MCT_gsmap, mpicom_ocn) ! Initialize mct ocn domain (needs ocn initialization info) @@ -194,36 +217,51 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) call ocn_domain_mct(lsize*km, MOM_MCT_gsmap3d, MOM_MCT_dom3d) ! Inialize mct attribute vectors - + ! Initialize the mct attribute vector x2o_o, given Attribute list and length: call mct_aVect_init(x2o_o, rList=seq_flds_x2o_fields, lsize=lsize) ! set the mct attribute vector x2o_o to zero: call mct_aVect_zero(x2o_o) - + ! Initialize the mct attribute vector o2x_o, given Attribute list and length: call mct_aVect_init(o2x_o, rList=seq_flds_o2x_fields, lsize=lsize) ! set the mct attribute vector o2x_o to zero: call mct_aVect_zero(o2x_o) + ! allocate send buffer nsend = mct_avect_nRattr(o2x_o) - nrecv = mct_avect_nRattr(x2o_o) - !allocate (SBUFF_SUM(nx_block,ny_block,max_blocks_clinic,nsend)) - - - - + nrecv = mct_avect_nRattr(x2o_o) + allocate (SBUFF_SUM(nx_block,ny_block,max_blocks_clinic,nsend)) + ! initialize necessary coupling info + call seq_timemgr_EClockGetData(EClock, dtime=ocn_cpl_dt) + mom_cpl_dt = seconds_in_day / ncouple_per_day + if (mom_cpl_dt /= ocn_cpl_dt) then + write(*,*) 'ERROR pop_cpl_dt and ocn_cpl_dt must be identical' + call exit(0) + end if + ! send initial state to driver + !TODO: + ! if ( lsend_precip_fact ) then + ! call seq_infodata_PutData( infodata, precip_fact=precip_fact) + ! end if + call mom_sum_buffer + call ocn_export(o2x_o%rattr, ldiag_cpl, errorCode) + call t_stopf('MOM_mct_init') - call t_stopf('MOM_mct_init') + call seq_infodata_PutData( infodata, & + ocn_nx = nx_global , ocn_ny = ny_global) + call seq_infodata_PutData( infodata, & + ocn_prognostic=.true., ocnrof_prognostic=.true.) @@ -295,41 +333,52 @@ subroutine ocn_final_mct( EClock, cdata_o, x2o_o, o2x_o) end subroutine ocn_final_mct -!*********************************************************************** -!BOP -!IROUTINE: ocn_SetGSMap_mct -! !INTERFACE: - - subroutine ocn_SetGSMap_mct(mpicom_ocn, MOM_MCT_ID, gsMap_ocn, gsMap3d_ocn) - -! !DESCRIPTION: -! This routine mct global seg maps for the MOM decomposition -! -! !REVISION HISTORY: -! same as module - -! !INPUT/OUTPUT PARAMETERS: - - implicit none - 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 - -!EOP -!BOC -!----------------------------------------------------------------------- -! -! local variables -! -!----------------------------------------------------------------------- - - - -!----------------------------------------------------------------------- -!EOC - - end subroutine ocn_SetGSMap_mct +!> This routine mct global seg maps for the MOM decomposition +!! +!! \todo Find out if we should only provide indirect indexing for ocean points and not land. +subroutine ocn_SetGSMap_mct(mpicom_ocn, MOM_MCT_ID, gsMap_ocn, gsMap3d_ocn) + integer, intent(in) :: mpicom_ocn !< MPI communicator + integer, intent(in) :: MOM_MCT_ID !< MCT component ID + type(mct_gsMap), intent(inout) :: gsMap_ocn !< MCT global segment map for 2d data + type(mct_gsMap), intent(inout) :: gsMap3d_ocn !< MCT global segment map for 3d data + ! Local variables + integer :: lsize ! Local size of indirect indexing array + integer :: i, j, k ! Local indices + integer :: ni, nj ! Declared sizes of h-point arrays + integer :: ig, jg ! Global indices + type(ocean_grid_type), pointer :: grid => NULL() ! A pointer to a grid structure + integer, allocatable :: gindex(:) ! Indirect indices + + call get_state_pointers(ocn_state, grid=grid) + if (.not. associated(grid)) call MOM_error(FATAL, 'ocn_comp_mct.F90, ocn_SetGSMap_mct():' // & + 'grid returned from get_state_pointers() was not associated!') + + ! Size of computational domain + lsize = ( grid%iec - grid%isc + 1 ) * ( grid%jec - grid%jsc + 1 ) + + ! Size of global domain + call get_global_grid_size(grid, ni, nj) + + ! Create indirect indices for the computational domain + allocate( gindex( lsize ) ) + + ! Set indirect indices in gindex + k = 0 + do j = grid%jsc, grid%jec + jg = j - grid%jdg_offset ! TODO: check this calculation + do i = grid%isc, grid%iec + ig = i - grid%idg_offset ! TODO: check this calculation + k = k + 1 ! Increment position within gindex + gindex(k) = ni * ( jg - 1 ) + ig + enddo + enddo + + ! Tell MCT how to indirectly index into the 2d buffer + call mct_gsMap_init( gsMap_ocn, gindex, mpicom_ocn, MOM_MCT_ID, lsize, ni * nj) + + deallocate( gindex ) + +end subroutine ocn_SetGSMap_mct !*********************************************************************** From ed3ed306863252788464679bad76c852621b3eef Mon Sep 17 00:00:00 2001 From: alperaltuntas Date: Thu, 13 Jul 2017 17:42:25 -0600 Subject: [PATCH 11/38] Added ocn_import_export module --- config_src/mct_driver/ocn_import_export.F90 | 28 +++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/config_src/mct_driver/ocn_import_export.F90 b/config_src/mct_driver/ocn_import_export.F90 index 6fd16835fb..5cb025a706 100644 --- a/config_src/mct_driver/ocn_import_export.F90 +++ b/config_src/mct_driver/ocn_import_export.F90 @@ -136,5 +136,33 @@ end subroutine ocn_export !*********************************************************************** + subroutine MOM_sum_buffer + +! !DESCRIPTION: +! This routine accumulates sums for averaging fields to +! be sent to the coupler +! +! !REVISION HISTORY: +! same as module +! +!EOP +!BOC + +!----------------------------------------------------------------------- +! +! local variables +! +!----------------------------------------------------------------------- + +!----------------------------------------------------------------------- +!EOC + + end subroutine MOM_sum_buffer + +!*********************************************************************** + + + + end module ocn_import_export From 2540ed80cd9f15be8e5896891e558cecfd2a039c Mon Sep 17 00:00:00 2001 From: alperaltuntas Date: Wed, 19 Jul 2017 09:51:04 -0600 Subject: [PATCH 12/38] Filled empty subroutines in ocn_comp_mct.F90 --- config_src/mct_driver/ocn_comp_mct.F90 | 90 ++++++++++++++++++++++++-- 1 file changed, 83 insertions(+), 7 deletions(-) diff --git a/config_src/mct_driver/ocn_comp_mct.F90 b/config_src/mct_driver/ocn_comp_mct.F90 index 5aa1cd914b..9b6099fb71 100644 --- a/config_src/mct_driver/ocn_comp_mct.F90 +++ b/config_src/mct_driver/ocn_comp_mct.F90 @@ -15,7 +15,9 @@ module ocn_comp_mct use seq_cdata_mod use mct_mod use seq_flds_mod, only: seq_flds_x2o_fields, & - seq_flds_o2x_fields + seq_flds_o2x_fields, & + SEQ_FLDS_DOM_COORD, & + SEQ_FLDS_DOM_other use seq_infodata_mod, only: seq_infodata_type, & seq_infodata_GetData, & seq_infodata_start_type_start, & @@ -25,6 +27,7 @@ module ocn_comp_mct use seq_comm_mct, only: seq_comm_name, seq_comm_inst, seq_comm_suffix use seq_timemgr_mod, only: seq_timemgr_EClockGetData use perf_mod, only: t_startf, t_stopf + use shr_kind_mod, only: SHR_KIND_R8 ! From MOM6 @@ -134,7 +137,7 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) integer :: nx_block=0, ny_block=0 ! size of block domain in x,y dir including ghost cells integer :: nx_global, ny_global! size of block domain in x,y dir including ghost cells integer :: max_blocks_clinic=0 !max number of blocks per processor in each distribution - integer :: ncouple_per_day = 24 + integer :: ncouple_per_day = 48 logical :: lsend_precip_fact ! if T,send precip_fact to cpl for use in fw balance ! (partially-coupled option) @@ -386,7 +389,7 @@ end subroutine ocn_SetGSMap_mct ! !IROUTINE: ocn_domain_mct ! !INTERFACE: - subroutine ocn_domain_mct( lsize, gsMap_ocn, dom_ocn) +subroutine ocn_domain_mct( lsize, gsMap_ocn, dom_ocn) ! !DESCRIPTION: ! This routine mct global seg maps for the pop decomposition @@ -396,10 +399,83 @@ subroutine ocn_domain_mct( lsize, gsMap_ocn, dom_ocn) ! ! !INPUT/OUTPUT PARAMETERS: - implicit none - integer , intent(in) :: lsize - type(mct_gsMap), intent(in) :: gsMap_ocn - type(mct_ggrid), intent(inout) :: dom_ocn + implicit none + integer , intent(in) :: lsize + type(mct_gsMap), intent(in) :: gsMap_ocn + type(mct_ggrid), intent(inout) :: dom_ocn + +! Local Variables + integer, parameter :: SHR_REAL_R8 = selected_real_kind (12) + integer, pointer :: idata(:) + integer :: i,j,k + real(kind=SHR_REAL_R8), pointer :: data(:) + real(kind=SHR_REAL_R8) :: m2_to_rad2 + type(ocean_grid_type), pointer :: grid => NULL() ! A pointer to a grid structure + + call get_state_pointers(ocn_state, grid=grid) + + ! set coords to lat and lon, and areas to rad^2 + call mct_gGrid_init(GGrid=dom_ocn, CoordChars=trim(seq_flds_dom_coord), & + OtherChars=trim(seq_flds_dom_other), lsize=lsize ) + + call mct_avect_zero(dom_ocn%data) + allocate(data(lsize)) + + ! Determine global gridpoint number attribute, GlobGridNum, which is set automatically by MCT + k = pe_here() + call mct_gsMap_orderedPoints(gsMap_ocn, k, idata) + call mct_gGrid_importIAttr(dom_ocn,'GlobGridNum',idata,lsize) + + !initialization + data(:) = -9999.0 + call mct_gGrid_importRAttr(dom_ocn,"lat" ,data,lsize) + call mct_gGrid_importRAttr(dom_ocn,"lon" ,data,lsize) + call mct_gGrid_importRAttr(dom_ocn,"area" ,data,lsize) + call mct_gGrid_importRAttr(dom_ocn,"aream",data,lsize) + data(:) = 0.0 + call mct_gGrid_importRAttr(dom_ocn,"mask",data,lsize) + call mct_gGrid_importRAttr(dom_ocn,"frac",data,lsize) + + k = 0 + do j = grid%jsc, grid%jec + do i = grid%isc, grid%iec + k = k + 1 ! Increment position within gindex + data(k) = grid%geoLonT(i,j) + enddo + enddo + call mct_gGrid_importRattr(dom_ocn,"lon",data,lsize) + + k = 0 + do j = grid%jsc, grid%jec + do i = grid%isc, grid%iec + k = k + 1 ! Increment position within gindex + data(k) = grid%geoLatT(i,j) + enddo + enddo + call mct_gGrid_importRattr(dom_ocn,"lat",data,lsize) + + k = 0 + m2_to_rad2 = 1./grid%Rad_Earth**2 + do j = grid%jsc, grid%jec + do i = grid%isc, grid%iec + k = k + 1 ! Increment position within gindex + data(k) = grid%AreaT(i,j) * m2_to_rad2 + enddo + enddo + call mct_gGrid_importRattr(dom_ocn,"area",data,lsize) + + k = 0 + do j = grid%jsc, grid%jec + do i = grid%isc, grid%iec + k = k + 1 ! Increment position within gindex + data(k) = grid%mask2dT(i,j) + enddo + enddo + call mct_gGrid_importRattr(dom_ocn,"mask",data,lsize) + call mct_gGrid_importRattr(dom_ocn,"frac",data,lsize) + + deallocate(data) + deallocate(idata) !EOP !BOC From 970f8482ace6f6f0a54e803087157ad61432c1f5 Mon Sep 17 00:00:00 2001 From: alperaltuntas Date: Wed, 19 Jul 2017 10:33:22 -0600 Subject: [PATCH 13/38] added debugging --- config_src/mct_driver/ocn_comp_mct.F90 | 29 ++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/config_src/mct_driver/ocn_comp_mct.F90 b/config_src/mct_driver/ocn_comp_mct.F90 index 9b6099fb71..bb67603f06 100644 --- a/config_src/mct_driver/ocn_comp_mct.F90 +++ b/config_src/mct_driver/ocn_comp_mct.F90 @@ -47,6 +47,7 @@ module ocn_comp_mct public :: ocn_run_mct public :: ocn_final_mct private ! By default make data private + logical, parameter :: debug=.true. ! ! ! PUBLIC DATA: @@ -109,6 +110,7 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) integer :: i, errorCode integer :: lsize, nsend, nrecv logical :: ldiag_cpl = .false. + integer :: ni, nj ! mct variables (these are local for now) integer :: MOM_MCT_ID @@ -133,14 +135,14 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) character(len=16) :: inst_suffix !!!DANGER!!!: change the following vars with the corresponding MOM6 vars - integer :: km=62 ! number of vertical levels + integer :: km=1 ! number of vertical levels integer :: nx_block=0, ny_block=0 ! size of block domain in x,y dir including ghost cells - integer :: nx_global, ny_global! size of block domain in x,y dir including ghost cells integer :: max_blocks_clinic=0 !max number of blocks per processor in each distribution integer :: ncouple_per_day = 48 logical :: lsend_precip_fact ! if T,send precip_fact to cpl for use in fw balance ! (partially-coupled option) + type(ocean_grid_type), pointer :: grid => NULL() ! A pointer to a grid structure !----------------------------------------------------------------------- @@ -209,6 +211,8 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) call t_startf('MOM_mct_init') + if (debug .and. root_pe().eq.pe_here()) print *, "calling ocn_SetGSMap_mct" + ! Set mct global seg maps: call ocn_SetGSMap_mct(mpicom_ocn, MOM_MCT_ID, MOM_MCT_GSMap, MOM_MCT_GSMap3d) @@ -216,16 +220,21 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) ! Initialize mct ocn domain (needs ocn initialization info) + if (debug .and. root_pe().eq.pe_here()) print *, "calling ocn_domain_mct" call ocn_domain_mct(lsize, MOM_MCT_gsmap, MOM_MCT_dom) - call ocn_domain_mct(lsize*km, MOM_MCT_gsmap3d, MOM_MCT_dom3d) + call ocn_domain_mct(lsize*km, MOM_MCT_gsmap3d, MOM_MCT_dom3d) !TODO: this is not used ! Inialize mct attribute vectors + if (debug .and. root_pe().eq.pe_here()) print *, "calling mct_avect_init a" + ! Initialize the mct attribute vector x2o_o, given Attribute list and length: call mct_aVect_init(x2o_o, rList=seq_flds_x2o_fields, lsize=lsize) ! set the mct attribute vector x2o_o to zero: call mct_aVect_zero(x2o_o) + if (debug .and. root_pe().eq.pe_here()) print *, "calling mct_avect_init b" + ! Initialize the mct attribute vector o2x_o, given Attribute list and length: call mct_aVect_init(o2x_o, rList=seq_flds_o2x_fields, lsize=lsize) ! set the mct attribute vector o2x_o to zero: @@ -238,6 +247,8 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) ! initialize necessary coupling info + if (debug .and. root_pe().eq.pe_here()) print *, "calling seq_timemgr_eclockgetdata" + call seq_timemgr_EClockGetData(EClock, dtime=ocn_cpl_dt) mom_cpl_dt = seconds_in_day / ncouple_per_day if (mom_cpl_dt /= ocn_cpl_dt) then @@ -252,21 +263,31 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) ! call seq_infodata_PutData( infodata, precip_fact=precip_fact) ! end if + if (debug .and. root_pe().eq.pe_here()) print *, "calling momo_sum_buffer" call mom_sum_buffer + if (debug .and. root_pe().eq.pe_here()) print *, "calling ocn_export" + call ocn_export(o2x_o%rattr, ldiag_cpl, errorCode) call t_stopf('MOM_mct_init') + if (debug .and. root_pe().eq.pe_here()) print *, "calling get_state_pointers" + + ! Size of global domain + call get_state_pointers(ocn_state, grid=grid) + call get_global_grid_size(grid, ni, nj) + if (debug .and. root_pe().eq.pe_here()) print *, "calling seq_infodata_putdata" call seq_infodata_PutData( infodata, & - ocn_nx = nx_global , ocn_ny = ny_global) + ocn_nx = ni , ocn_ny = nj) call seq_infodata_PutData( infodata, & ocn_prognostic=.true., ocnrof_prognostic=.true.) + if (debug .and. root_pe().eq.pe_here()) print *, "leaving ocean_init_mct" !----------------------------------------------------------------------- !EOC From 8b381416fed31b967f1590ece86c4ad032c28d0f Mon Sep 17 00:00:00 2001 From: alperaltuntas Date: Wed, 19 Jul 2017 14:37:30 -0600 Subject: [PATCH 14/38] Wrapped global data --- config_src/mct_driver/coupler_indices.F90 | 9 ++--- config_src/mct_driver/ocn_comp_mct.F90 | 43 +++++++++++++---------- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/config_src/mct_driver/coupler_indices.F90 b/config_src/mct_driver/coupler_indices.F90 index bfb42de7f0..e98540084d 100644 --- a/config_src/mct_driver/coupler_indices.F90 +++ b/config_src/mct_driver/coupler_indices.F90 @@ -79,12 +79,13 @@ module coupler_indices end type cpl_indices - ! Module data for storing - type(cpl_indices), public :: ind - contains - subroutine coupler_indices_init( ) + subroutine coupler_indices_init(ind) + + type(cpl_indices), intent(inout) :: ind + + ! Local Variables type(mct_aVect) :: o2x ! temporary type(mct_aVect) :: x2o ! temporary diff --git a/config_src/mct_driver/ocn_comp_mct.F90 b/config_src/mct_driver/ocn_comp_mct.F90 index bb67603f06..30e0d1d345 100644 --- a/config_src/mct_driver/ocn_comp_mct.F90 +++ b/config_src/mct_driver/ocn_comp_mct.F90 @@ -37,7 +37,7 @@ module ocn_comp_mct use MOM_grid, only: ocean_grid_type, get_global_grid_size use MOM_error_handler, only: MOM_error, FATAL, is_root_pe use MOM_time_manager, only: time_type, set_date, set_calendar_type, NOLEAP - use coupler_indices, only: coupler_indices_init + use coupler_indices, only: coupler_indices_init, cpl_indices use ocn_import_export, only: SBUFF_SUM, ocn_Export, mom_sum_buffer ! @@ -61,11 +61,16 @@ module ocn_comp_mct private :: ocn_domain_mct ! !PRIVATE MODULE VARIABLES - type(ocean_state_type), pointer :: ocn_state => NULL() ! Private state of ocean - type(ocean_public_type), pointer :: ocn_surface => NULL() ! Public surface state of ocean + type MCT_MOM_Data + type(ocean_state_type), pointer :: ocn_state => NULL() !< Private state of ocean + type(ocean_public_type), pointer :: ocn_surface => NULL() !< Public surface state of ocean - type(seq_infodata_type), pointer :: & - infodata + type(seq_infodata_type), pointer :: infodata + + type(cpl_indices), public :: ind !< Variable IDs + + end type + type(MCT_MOM_Data) :: glb !======================================================================= @@ -148,17 +153,17 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) ! set (actually, get from mct) the cdata pointers: call seq_cdata_setptrs(cdata_o, id=MOM_MCT_ID, mpicom=mpicom_ocn, & - gsMap=MOM_MCT_gsMap, dom=MOM_MCT_dom, infodata=infodata) + gsMap=MOM_MCT_gsMap, dom=MOM_MCT_dom, infodata=glb%infodata) !--------------------------------------------------------------------- ! Initialize the model run !--------------------------------------------------------------------- - call coupler_indices_init() + call coupler_indices_init(glb%ind) - call seq_infodata_GetData( infodata, case_name=runid ) + call seq_infodata_GetData( glb%infodata, case_name=runid ) - call seq_infodata_GetData( infodata, start_type=starttype) + call seq_infodata_GetData( glb%infodata, start_type=starttype) if ( trim(starttype) == trim(seq_infodata_start_type_start)) then runtype = "initial" @@ -195,13 +200,13 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) npes = num_pes() pe0 = root_pe() - allocate(ocn_surface) - ocn_surface%is_ocean_PE = .true. - allocate(ocn_surface%pelist(npes)) - ocn_surface%pelist(:) = (/(i,i=pe0,pe0+npes)/) + allocate(glb%ocn_surface) + glb%ocn_surface%is_ocean_PE = .true. + allocate(glb%ocn_surface%pelist(npes)) + glb%ocn_surface%pelist(:) = (/(i,i=pe0,pe0+npes)/) ! initialize the MOM6 model - call ocean_model_init(ocn_surface, ocn_state, time_init, time_in) + call ocean_model_init(glb%ocn_surface, glb%ocn_state, time_init, time_in) call t_stopf('MOM_init') @@ -276,14 +281,14 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) if (debug .and. root_pe().eq.pe_here()) print *, "calling get_state_pointers" ! Size of global domain - call get_state_pointers(ocn_state, grid=grid) + call get_state_pointers(glb%ocn_state, grid=grid) call get_global_grid_size(grid, ni, nj) if (debug .and. root_pe().eq.pe_here()) print *, "calling seq_infodata_putdata" - call seq_infodata_PutData( infodata, & + call seq_infodata_PutData( glb%infodata, & ocn_nx = ni , ocn_ny = nj) - call seq_infodata_PutData( infodata, & + call seq_infodata_PutData( glb%infodata, & ocn_prognostic=.true., ocnrof_prognostic=.true.) @@ -373,7 +378,7 @@ subroutine ocn_SetGSMap_mct(mpicom_ocn, MOM_MCT_ID, gsMap_ocn, gsMap3d_ocn) type(ocean_grid_type), pointer :: grid => NULL() ! A pointer to a grid structure integer, allocatable :: gindex(:) ! Indirect indices - call get_state_pointers(ocn_state, grid=grid) + call get_state_pointers(glb%ocn_state, grid=grid) if (.not. associated(grid)) call MOM_error(FATAL, 'ocn_comp_mct.F90, ocn_SetGSMap_mct():' // & 'grid returned from get_state_pointers() was not associated!') @@ -433,7 +438,7 @@ subroutine ocn_domain_mct( lsize, gsMap_ocn, dom_ocn) real(kind=SHR_REAL_R8) :: m2_to_rad2 type(ocean_grid_type), pointer :: grid => NULL() ! A pointer to a grid structure - call get_state_pointers(ocn_state, grid=grid) + call get_state_pointers(glb%ocn_state, grid=grid) ! set coords to lat and lon, and areas to rad^2 call mct_gGrid_init(GGrid=dom_ocn, CoordChars=trim(seq_flds_dom_coord), & From 3a923a224ceb0a3bbe03034c45628b71b03e8dd5 Mon Sep 17 00:00:00 2001 From: alperaltuntas Date: Thu, 20 Jul 2017 10:49:33 -0600 Subject: [PATCH 15/38] Got initialization working --- config_src/coupled_driver/ocean_model_MOM.F90 | 4 +- config_src/mct_driver/coupler_indices.F90 | 163 ++++++++++++++++++ config_src/mct_driver/ocn_comp_mct.F90 | 53 +++--- config_src/mct_driver/ocn_import_export.F90 | 27 --- 4 files changed, 198 insertions(+), 49 deletions(-) diff --git a/config_src/coupled_driver/ocean_model_MOM.F90 b/config_src/coupled_driver/ocean_model_MOM.F90 index dfcdded6f8..8a5f934d12 100644 --- a/config_src/coupled_driver/ocean_model_MOM.F90 +++ b/config_src/coupled_driver/ocean_model_MOM.F90 @@ -1086,11 +1086,13 @@ subroutine ocean_public_type_chksum(id, timestep, ocn) end subroutine ocean_public_type_chksum !> Returns pointers to objects within ocean_state_type -subroutine get_state_pointers(OS, grid) +subroutine get_state_pointers(OS, grid, surf) type(ocean_state_type), pointer :: OS !< Ocean state type type(ocean_grid_type), optional, pointer :: grid !< Ocean grid + type(surface), optional, pointer :: surf !< Ocean surface state if (present(grid)) grid => OS%grid + if (present(surf)) surf=> OS%state end subroutine get_state_pointers diff --git a/config_src/mct_driver/coupler_indices.F90 b/config_src/mct_driver/coupler_indices.F90 index e98540084d..a2b11a015c 100644 --- a/config_src/mct_driver/coupler_indices.F90 +++ b/config_src/mct_driver/coupler_indices.F90 @@ -1,14 +1,22 @@ module coupler_indices + ! From MCT: use seq_flds_mod, only : seq_flds_x2o_fields, seq_flds_o2x_fields use seq_flds_mod, only : seq_flds_i2o_per_cat, ice_ncat use mct_mod + ! From MOM: + use MOM_grid, only : ocean_grid_type + use MOM_domains, only : pass_var + use MOM_variables, only : surface + implicit none private + public alloc_sbuffer public coupler_indices_init + public time_avg_state type, public :: cpl_indices @@ -77,10 +85,15 @@ module coupler_indices integer, dimension(:), allocatable :: x2o_fracr_col ! fraction of ocean cell used in radiation computations, per column integer, dimension(:), allocatable :: x2o_qsw_fracr_col ! qsw * fracr, per column + real, dimension(:,:,:),allocatable :: time_avg_sbuffer !< time averages of send buffer + real :: accum_time !< time for accumulation + end type cpl_indices contains + + subroutine coupler_indices_init(ind) type(cpl_indices), intent(inout) :: ind @@ -192,4 +205,154 @@ subroutine coupler_indices_init(ind) end subroutine coupler_indices_init + + subroutine alloc_sbuffer(ind, grid, nsend) + + ! Parameters + type(cpl_indices), intent(inout) :: ind + type(ocean_grid_type), intent(in) :: grid + integer, intent(in) :: nsend + + allocate(ind%time_avg_sbuffer(grid%isd:grid%ied,grid%jsd:grid%jed,nsend)) + + end subroutine alloc_sbuffer + + + subroutine time_avg_state(ind, grid, surf_state, dt, reset, last) + + type(cpl_indices), intent(inout) :: ind !< module control structure + type(ocean_grid_type), intent(inout) :: grid !< ocean grid (inout in order to do halo update) + type(surface), intent(in) :: surf_state !< ocean surface state + real, intent(in) :: dt !< time interval to accumulate (seconds) + logical, optional, intent(in) :: reset !< if present and true, reset accumulations + logical, optional, intent(in) :: last !< if present and true, divide by accumulated time + + ! local variables + integer :: i,j,nvar + real :: rtime, slp_L, slp_R, slp_C, u_min, u_max, slope + real, dimension(grid%isd:grid%ied, grid%jsd:grid%jed) :: ssh + + if (present(reset)) then + if (reset) then + ind%time_avg_sbuffer(:,:,:) = 0. + ind%accum_time = 0. + end if + end if + + ! sst + nvar = ind%o2x_So_t + do j=grid%jsc, grid%jec ; do i=grid%isc,grid%iec + ind%time_avg_sbuffer(i,j,nvar) = ind%time_avg_sbuffer(i,j,nvar)+dt * surf_state%sst(i,j) + end do; end do + + ! sss + nvar = ind%o2x_So_s + do j=grid%jsc, grid%jec ; do i=grid%isc,grid%iec + ind%time_avg_sbuffer(i,j,nvar) = ind%time_avg_sbuffer(i,j,nvar)+dt * surf_state%sss(i,j) + end do; end do + + + ! u + nvar = ind%o2x_So_u + do j=grid%jsc, grid%jec ; do i=grid%isc,grid%iec + ind%time_avg_sbuffer(i,j,nvar) = ind%time_avg_sbuffer(i,j,nvar)+dt * & + 0.5*(surf_state%u(I,j)+surf_state%u(I-1,j)) + end do; end do + + ! v + nvar = ind%o2x_So_v + do j=grid%jsc, grid%jec ; do i=grid%isc,grid%iec + ind%time_avg_sbuffer(i,j,nvar) = ind%time_avg_sbuffer(i,j,nvar)+dt * & + 0.5*(surf_state%v(i,J)+surf_state%v(i,J-1)) + end do; end do + + ! ssh + do j=grid%jsc, grid%jec ; do i=grid%isc,grid%iec + ssh(i,j) = surf_state%sea_lev(i,j) + end do; end do + call pass_var(ssh, grid%domain) + + ! d/dx ssh + nvar = ind%o2x_So_dhdx + do j=grid%jsc, grid%jec ; do i=grid%isc,grid%iec + ! This is a simple second-order difference + ! ind%time_avg_sbuffer(i,j,nvar) = ind%time_avg_sbuffer(i,j,nvar) + dt * & + ! 0.5 * (ssh(i+1,j) + ssh(i-1,j)) * grid%IdxT(i,j) * grid%mask2dT(i,j) + ! This is a PLM slope which might be less prone to the A-grid null mode + slp_L = ssh(i,j) - ssh(i-1,j) + slp_R = ssh(i+1,j) - ssh(i,j) + slp_C = 0.5 * (slp_L + slp_R) + if ( (slp_L * slp_R) > 0.0 ) then + ! This limits the slope so that the edge values are bounded by the + ! two cell averages spanning the edge. + u_min = min( ssh(i-1,j), ssh(i,j), ssh(i+1,j) ) + u_max = max( ssh(i-1,j), ssh(i,j), ssh(i+1,j) ) + slope = sign( min( abs(slp_C), 2.*min( ssh(i,j) - u_min, u_max - ssh(i,j) ) ), slp_C ) + else + ! Extrema in the mean values require a PCM reconstruction avoid generating + ! larger extreme values. + slope = 0.0 + end if + ind%time_avg_sbuffer(i,j,nvar) = ind%time_avg_sbuffer(i,j,nvar) + dt * slope * grid%IdxT(i,j) * grid%mask2dT(i,j) + end do; end do + + ! d/dy ssh + nvar = ind%o2x_So_dhdy + do j=grid%jsc, grid%jec ; do i=grid%isc,grid%iec + ! This is a simple second-order difference + ! ind%time_avg_sbuffer(i,j,nvar) = ind%time_avg_sbuffer(i,j,nvar) + dt * & + ! 0.5 * (ssh(i,j+1) + ssh(i,j-1)) * grid%IdyT(i,j) * grid%mask2dT(i,j) + ! This is a PLM slope which might be less prone to the A-grid null mode + slp_L = ssh(i,j) - ssh(i,j-1) + slp_R = ssh(i,j+1) - ssh(i,j) + slp_C = 0.5 * (slp_L + slp_R) + if ( (slp_L * slp_R) > 0.0 ) then + ! This limits the slope so that the edge values are bounded by the + ! two cell averages spanning the edge. + u_min = min( ssh(i,j-1), ssh(i,j), ssh(i,j+1) ) + u_max = max( ssh(i,j-1), ssh(i,j), ssh(i,j+1) ) + slope = sign( min( abs(slp_C), 2.*min( ssh(i,j) - u_min, u_max - ssh(i,j) ) ), slp_C ) + else + ! Extrema in the mean values require a PCM reconstruction avoid generating + ! larger extreme values. + slope = 0.0 + end if + ind%time_avg_sbuffer(i,j,nvar) = ind%time_avg_sbuffer(i,j,nvar) + dt * slope * grid%IdyT(i,j) * grid%mask2dT(i,j) + end do; end do + + ! Divide by total accumulated time + ind%accum_time = ind%accum_time + dt + if (present(last)) then + + !! \todo Do dhdx,dhdy need to be rotated before sending to the coupler? + !! \todo Do u,v need to be rotated before sending to the coupler? + + rtime = 1./ind%accum_time + if (last) ind%time_avg_sbuffer(:,:,:) = ind%time_avg_sbuffer(:,:,:) * rtime + end if + + end subroutine time_avg_state + + + subroutine ocn_export(ind, grid, o2x) + + type(cpl_indices), intent(in) :: ind + type(ocean_grid_type), intent(in) :: grid + real(kind=8), intent(inout) :: o2x(:,:) + + integer :: i, j, n + + n = 0 + do j=grid%jsc, grid%jec ; do i=grid%isc,grid%iec + n = n+1 + o2x(ind%o2x_So_t, n) = ind%time_avg_sbuffer(i,j,ind%o2x_So_t) + o2x(ind%o2x_So_s, n) = ind%time_avg_sbuffer(i,j,ind%o2x_So_s) + o2x(ind%o2x_So_u, n) = ind%time_avg_sbuffer(i,j,ind%o2x_So_u) + o2x(ind%o2x_So_v, n) = ind%time_avg_sbuffer(i,j,ind%o2x_So_v) + o2x(ind%o2x_So_dhdx, n) = ind%time_avg_sbuffer(i,j,ind%o2x_So_dhdx) + o2x(ind%o2x_So_dhdy, n) = ind%time_avg_sbuffer(i,j,ind%o2x_So_dhdy) + end do; end do + + end subroutine ocn_export + end module coupler_indices diff --git a/config_src/mct_driver/ocn_comp_mct.F90 b/config_src/mct_driver/ocn_comp_mct.F90 index 30e0d1d345..85a2e5b650 100644 --- a/config_src/mct_driver/ocn_comp_mct.F90 +++ b/config_src/mct_driver/ocn_comp_mct.F90 @@ -31,14 +31,15 @@ module ocn_comp_mct ! From MOM6 - use ocean_model_mod, only: ocean_state_type, ocean_public_type + use ocean_model_mod, only: ocean_state_type, ocean_public_type, ocean_model_init_sfc use ocean_model_mod, only: ocean_model_init, get_state_pointers use MOM_domains, only: MOM_infra_init, num_pes, root_pe, pe_here use MOM_grid, only: ocean_grid_type, get_global_grid_size + use MOM_variables, only: surface use MOM_error_handler, only: MOM_error, FATAL, is_root_pe use MOM_time_manager, only: time_type, set_date, set_calendar_type, NOLEAP - use coupler_indices, only: coupler_indices_init, cpl_indices - use ocn_import_export, only: SBUFF_SUM, ocn_Export, mom_sum_buffer + use coupler_indices, only: coupler_indices_init, cpl_indices, alloc_sbuffer, time_avg_state + use ocn_import_export, only: ocn_Export ! ! !PUBLIC MEMBER FUNCTIONS: @@ -63,7 +64,9 @@ module ocn_comp_mct ! !PRIVATE MODULE VARIABLES type MCT_MOM_Data type(ocean_state_type), pointer :: ocn_state => NULL() !< Private state of ocean - type(ocean_public_type), pointer :: ocn_surface => NULL() !< Public surface state of ocean + type(ocean_public_type), pointer :: ocn_public => NULL() !< Public state of ocean + type(ocean_grid_type), pointer :: grid => NULL() ! A pointer to a grid structure + type(surface), pointer :: ocn_surface => NULL() !< A pointer to the ocean surface state type(seq_infodata_type), pointer :: infodata @@ -147,8 +150,6 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) logical :: lsend_precip_fact ! if T,send precip_fact to cpl for use in fw balance ! (partially-coupled option) - type(ocean_grid_type), pointer :: grid => NULL() ! A pointer to a grid structure - !----------------------------------------------------------------------- ! set (actually, get from mct) the cdata pointers: @@ -200,13 +201,19 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) npes = num_pes() pe0 = root_pe() - allocate(glb%ocn_surface) - glb%ocn_surface%is_ocean_PE = .true. - allocate(glb%ocn_surface%pelist(npes)) - glb%ocn_surface%pelist(:) = (/(i,i=pe0,pe0+npes)/) + allocate(glb%ocn_public) + glb%ocn_public%is_ocean_PE = .true. + allocate(glb%ocn_public%pelist(npes)) + glb%ocn_public%pelist(:) = (/(i,i=pe0,pe0+npes)/) + + ! Initialize the MOM6 model + call ocean_model_init(glb%ocn_public, glb%ocn_state, time_init, time_in) + + ! Initialize ocn_state%state out of sight + call ocean_model_init_sfc(glb%ocn_state, glb%ocn_public) - ! initialize the MOM6 model - call ocean_model_init(glb%ocn_surface, glb%ocn_state, time_init, time_in) + ! store pointers to components inside MOM + call get_state_pointers(glb%ocn_state, grid=glb%grid, surf=glb%ocn_surface) call t_stopf('MOM_init') @@ -248,7 +255,11 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) ! allocate send buffer nsend = mct_avect_nRattr(o2x_o) nrecv = mct_avect_nRattr(x2o_o) - allocate (SBUFF_SUM(nx_block,ny_block,max_blocks_clinic,nsend)) + + if (debug .and. root_pe().eq.pe_here()) print *, "calling alloc_sbuffer()", nsend + + call alloc_sbuffer(glb%ind,glb%grid,nsend) + ! initialize necessary coupling info @@ -269,8 +280,9 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) ! end if if (debug .and. root_pe().eq.pe_here()) print *, "calling momo_sum_buffer" - - call mom_sum_buffer + + ! Reset time average of send buffer + call time_avg_state(glb%ind, glb%grid, glb%ocn_surface, 1., reset=.true., last=.true.) if (debug .and. root_pe().eq.pe_here()) print *, "calling ocn_export" @@ -281,8 +293,7 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) if (debug .and. root_pe().eq.pe_here()) print *, "calling get_state_pointers" ! Size of global domain - call get_state_pointers(glb%ocn_state, grid=grid) - call get_global_grid_size(grid, ni, nj) + call get_global_grid_size(glb%grid, ni, nj) if (debug .and. root_pe().eq.pe_here()) print *, "calling seq_infodata_putdata" @@ -378,7 +389,7 @@ subroutine ocn_SetGSMap_mct(mpicom_ocn, MOM_MCT_ID, gsMap_ocn, gsMap3d_ocn) type(ocean_grid_type), pointer :: grid => NULL() ! A pointer to a grid structure integer, allocatable :: gindex(:) ! Indirect indices - call get_state_pointers(glb%ocn_state, grid=grid) + grid => glb%grid ! for convenience if (.not. associated(grid)) call MOM_error(FATAL, 'ocn_comp_mct.F90, ocn_SetGSMap_mct():' // & 'grid returned from get_state_pointers() was not associated!') @@ -394,9 +405,9 @@ subroutine ocn_SetGSMap_mct(mpicom_ocn, MOM_MCT_ID, gsMap_ocn, gsMap3d_ocn) ! Set indirect indices in gindex k = 0 do j = grid%jsc, grid%jec - jg = j - grid%jdg_offset ! TODO: check this calculation + jg = j + grid%jdg_offset ! TODO: check this calculation do i = grid%isc, grid%iec - ig = i - grid%idg_offset ! TODO: check this calculation + ig = i + grid%idg_offset ! TODO: check this calculation k = k + 1 ! Increment position within gindex gindex(k) = ni * ( jg - 1 ) + ig enddo @@ -438,7 +449,7 @@ subroutine ocn_domain_mct( lsize, gsMap_ocn, dom_ocn) real(kind=SHR_REAL_R8) :: m2_to_rad2 type(ocean_grid_type), pointer :: grid => NULL() ! A pointer to a grid structure - call get_state_pointers(glb%ocn_state, grid=grid) + grid => glb%grid ! for convenience ! set coords to lat and lon, and areas to rad^2 call mct_gGrid_init(GGrid=dom_ocn, CoordChars=trim(seq_flds_dom_coord), & diff --git a/config_src/mct_driver/ocn_import_export.F90 b/config_src/mct_driver/ocn_import_export.F90 index 5cb025a706..a314e60960 100644 --- a/config_src/mct_driver/ocn_import_export.F90 +++ b/config_src/mct_driver/ocn_import_export.F90 @@ -136,33 +136,6 @@ end subroutine ocn_export !*********************************************************************** - subroutine MOM_sum_buffer - -! !DESCRIPTION: -! This routine accumulates sums for averaging fields to -! be sent to the coupler -! -! !REVISION HISTORY: -! same as module -! -!EOP -!BOC - -!----------------------------------------------------------------------- -! -! local variables -! -!----------------------------------------------------------------------- - -!----------------------------------------------------------------------- -!EOC - - end subroutine MOM_sum_buffer - -!*********************************************************************** - - - end module ocn_import_export From beac3ed5ba3ed8f7aeafe484075d5eb7f1f132ee Mon Sep 17 00:00:00 2001 From: Alistair Adcroft Date: Thu, 20 Jul 2017 16:48:22 -0600 Subject: [PATCH 16/38] Adds "only" for all use statements - In keeping with MOM6 style guide, all module use statements now have "only" and each imported entity is explicitly listed. --- config_src/mct_driver/coupler_indices.F90 | 9 ++++++--- config_src/mct_driver/ocn_comp_mct.F90 | 14 +++++++++----- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/config_src/mct_driver/coupler_indices.F90 b/config_src/mct_driver/coupler_indices.F90 index a2b11a015c..29e74dd437 100644 --- a/config_src/mct_driver/coupler_indices.F90 +++ b/config_src/mct_driver/coupler_indices.F90 @@ -1,12 +1,15 @@ module coupler_indices - ! From MCT: + ! MCT types + use mct_mod, only : mct_aVect + ! MCT fucntions + use mct_mod, only : mct_avect_indexra, mct_aVect_init, mct_aVect_clean use seq_flds_mod, only : seq_flds_x2o_fields, seq_flds_o2x_fields use seq_flds_mod, only : seq_flds_i2o_per_cat, ice_ncat - use mct_mod - ! From MOM: + ! MOM types use MOM_grid, only : ocean_grid_type + ! MOM functions use MOM_domains, only : pass_var use MOM_variables, only : surface diff --git a/config_src/mct_driver/ocn_comp_mct.F90 b/config_src/mct_driver/ocn_comp_mct.F90 index 85a2e5b650..56bd487267 100644 --- a/config_src/mct_driver/ocn_comp_mct.F90 +++ b/config_src/mct_driver/ocn_comp_mct.F90 @@ -11,9 +11,13 @@ module ocn_comp_mct ! !REVISION HISTORY: ! ! !USES: - use esmf - use seq_cdata_mod - use mct_mod + use ESMF, only: ESMF_clock, ESMF_time + use ESMF, only: ESMF_ClockGet, ESMF_TimeGet + use seq_cdata_mod, only: seq_cdata + use seq_cdata_mod, only: seq_cdata_setptrs + use mct_mod, only: mct_gsMap, mct_gsmap_init, mct_gsMap_lsize, mct_gsmap_orderedpoints + use mct_mod, only: mct_aVect, mct_aVect_init, mct_aVect_zero, mct_aVect_nRattr + use mct_mod, only: mct_gGrid, mct_gGrid_init, mct_gGrid_importRAttr, mct_gGrid_importIAttr use seq_flds_mod, only: seq_flds_x2o_fields, & seq_flds_o2x_fields, & SEQ_FLDS_DOM_COORD, & @@ -92,7 +96,7 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) ! ! !INPUT/OUTPUT PARAMETERS: - type(ESMF_Clock) , intent(inout) :: EClock + type(ESMF_clock) , intent(inout) :: EClock type(seq_cdata) , intent(inout) :: cdata_o type(mct_aVect) , intent(inout) :: x2o_o, o2x_o character(len=*), optional , intent(in) :: NLFilename ! Namelist filename @@ -442,7 +446,7 @@ subroutine ocn_domain_mct( lsize, gsMap_ocn, dom_ocn) type(mct_ggrid), intent(inout) :: dom_ocn ! Local Variables - integer, parameter :: SHR_REAL_R8 = selected_real_kind (12) + integer, parameter :: SHR_REAL_R8 = selected_real_kind(12) integer, pointer :: idata(:) integer :: i,j,k real(kind=SHR_REAL_R8), pointer :: data(:) From a1db77f788348894510ab92c5b809064399281de Mon Sep 17 00:00:00 2001 From: Alistair Adcroft Date: Fri, 21 Jul 2017 13:26:49 -0600 Subject: [PATCH 17/38] Cleans up white space - something we'll get in the habit of doing... --- config_src/mct_driver/coupler_indices.F90 | 58 ++++++++++----------- config_src/mct_driver/ocn_comp_mct.F90 | 10 ++-- config_src/mct_driver/ocn_import_export.F90 | 18 +++---- 3 files changed, 43 insertions(+), 43 deletions(-) diff --git a/config_src/mct_driver/coupler_indices.F90 b/config_src/mct_driver/coupler_indices.F90 index 29e74dd437..24e52fa059 100644 --- a/config_src/mct_driver/coupler_indices.F90 +++ b/config_src/mct_driver/coupler_indices.F90 @@ -1,11 +1,11 @@ module coupler_indices - + ! MCT types use mct_mod, only : mct_aVect ! MCT fucntions use mct_mod, only : mct_avect_indexra, mct_aVect_init, mct_aVect_clean - use seq_flds_mod, only : seq_flds_x2o_fields, seq_flds_o2x_fields - use seq_flds_mod, only : seq_flds_i2o_per_cat, ice_ncat + use seq_flds_mod, only : seq_flds_x2o_fields, seq_flds_o2x_fields + use seq_flds_mod, only : seq_flds_i2o_per_cat, ice_ncat ! MOM types use MOM_grid, only : ocean_grid_type @@ -25,7 +25,7 @@ module coupler_indices ! ocn -> drv - integer :: o2x_So_t + integer :: o2x_So_t integer :: o2x_So_u integer :: o2x_So_v integer :: o2x_So_s @@ -52,7 +52,7 @@ module coupler_indices integer :: x2o_Foxx_tauy ! meridonal wind stress (tauy) (W/m2 ) integer :: x2o_Foxx_swnet ! net short-wave heat flux (W/m2 ) integer :: x2o_Foxx_sen ! sensible heat flux (W/m2 ) - integer :: x2o_Foxx_lat + integer :: x2o_Foxx_lat integer :: x2o_Foxx_lwup ! longwave radiation (up) (W/m2 ) integer :: x2o_Faxa_lwdn ! longwave radiation (down) (W/m2 ) integer :: x2o_Fioi_melth ! heat flux from snow & ice melt (W/m2 ) @@ -62,7 +62,7 @@ module coupler_indices integer :: x2o_Fioi_flxdst ! flux: dust release from sea ice component integer :: x2o_Fioi_salt ! salt (kg(salt)/m2/s) integer :: x2o_Foxx_evap ! evaporation flux (kg/m2/s) - integer :: x2o_Faxa_prec + integer :: x2o_Faxa_prec integer :: x2o_Faxa_snow ! water flux due to snow (kg/m2/s) integer :: x2o_Faxa_rain ! water flux due to rain (kg/m2/s) integer :: x2o_Faxa_bcphidry ! flux: Black Carbon hydrophilic dry deposition @@ -88,7 +88,7 @@ module coupler_indices integer, dimension(:), allocatable :: x2o_fracr_col ! fraction of ocean cell used in radiation computations, per column integer, dimension(:), allocatable :: x2o_qsw_fracr_col ! qsw * fracr, per column - real, dimension(:,:,:),allocatable :: time_avg_sbuffer !< time averages of send buffer + real, dimension(:,:,:),allocatable :: time_avg_sbuffer !< time averages of send buffer real :: accum_time !< time for accumulation end type cpl_indices @@ -109,7 +109,7 @@ subroutine coupler_indices_init(ind) integer :: ncat ! thickness category index character(len=2) :: cncat ! character version of ncat integer :: ncol ! column index - integer :: mcog_ncols + integer :: mcog_ncols integer :: lmcog_flds_sent ! Determine attribute vector indices @@ -144,15 +144,15 @@ subroutine coupler_indices_init(ind) ind%x2o_Foxx_sen = mct_avect_indexra(x2o,'Foxx_sen') ind%x2o_Foxx_lwup = mct_avect_indexra(x2o,'Foxx_lwup') ind%x2o_Faxa_lwdn = mct_avect_indexra(x2o,'Faxa_lwdn') - ind%x2o_Fioi_melth = mct_avect_indexra(x2o,'Fioi_melth') + ind%x2o_Fioi_melth = mct_avect_indexra(x2o,'Fioi_melth') ind%x2o_Fioi_meltw = mct_avect_indexra(x2o,'Fioi_meltw') - ind%x2o_Fioi_salt = mct_avect_indexra(x2o,'Fioi_salt') + ind%x2o_Fioi_salt = mct_avect_indexra(x2o,'Fioi_salt') ind%x2o_Fioi_bcpho = mct_avect_indexra(x2o,'Fioi_bcpho') ind%x2o_Fioi_bcphi = mct_avect_indexra(x2o,'Fioi_bcphi') ind%x2o_Fioi_flxdst = mct_avect_indexra(x2o,'Fioi_flxdst') - ind%x2o_Faxa_prec = mct_avect_indexra(x2o,'Faxa_prec') - ind%x2o_Faxa_snow = mct_avect_indexra(x2o,'Faxa_snow') - ind%x2o_Faxa_rain = mct_avect_indexra(x2o,'Faxa_rain') + ind%x2o_Faxa_prec = mct_avect_indexra(x2o,'Faxa_prec') + ind%x2o_Faxa_snow = mct_avect_indexra(x2o,'Faxa_snow') + ind%x2o_Faxa_rain = mct_avect_indexra(x2o,'Faxa_rain') ind%x2o_Foxx_evap = mct_avect_indexra(x2o,'Foxx_evap') ind%x2o_Foxx_rofl = mct_avect_indexra(x2o,'Foxx_rofl') ind%x2o_Foxx_rofi = mct_avect_indexra(x2o,'Foxx_rofi') @@ -220,9 +220,9 @@ subroutine alloc_sbuffer(ind, grid, nsend) end subroutine alloc_sbuffer - + subroutine time_avg_state(ind, grid, surf_state, dt, reset, last) - + type(cpl_indices), intent(inout) :: ind !< module control structure type(ocean_grid_type), intent(inout) :: grid !< ocean grid (inout in order to do halo update) type(surface), intent(in) :: surf_state !< ocean surface state @@ -231,7 +231,7 @@ subroutine time_avg_state(ind, grid, surf_state, dt, reset, last) logical, optional, intent(in) :: last !< if present and true, divide by accumulated time ! local variables - integer :: i,j,nvar + integer :: i,j,nvar real :: rtime, slp_L, slp_R, slp_C, u_min, u_max, slope real, dimension(grid%isd:grid%ied, grid%jsd:grid%jed) :: ssh @@ -240,30 +240,30 @@ subroutine time_avg_state(ind, grid, surf_state, dt, reset, last) ind%time_avg_sbuffer(:,:,:) = 0. ind%accum_time = 0. end if - end if + end if ! sst - nvar = ind%o2x_So_t + nvar = ind%o2x_So_t do j=grid%jsc, grid%jec ; do i=grid%isc,grid%iec ind%time_avg_sbuffer(i,j,nvar) = ind%time_avg_sbuffer(i,j,nvar)+dt * surf_state%sst(i,j) end do; end do ! sss - nvar = ind%o2x_So_s + nvar = ind%o2x_So_s do j=grid%jsc, grid%jec ; do i=grid%isc,grid%iec ind%time_avg_sbuffer(i,j,nvar) = ind%time_avg_sbuffer(i,j,nvar)+dt * surf_state%sss(i,j) end do; end do - + ! u - nvar = ind%o2x_So_u + nvar = ind%o2x_So_u do j=grid%jsc, grid%jec ; do i=grid%isc,grid%iec ind%time_avg_sbuffer(i,j,nvar) = ind%time_avg_sbuffer(i,j,nvar)+dt * & 0.5*(surf_state%u(I,j)+surf_state%u(I-1,j)) end do; end do - + ! v - nvar = ind%o2x_So_v + nvar = ind%o2x_So_v do j=grid%jsc, grid%jec ; do i=grid%isc,grid%iec ind%time_avg_sbuffer(i,j,nvar) = ind%time_avg_sbuffer(i,j,nvar)+dt * & 0.5*(surf_state%v(i,J)+surf_state%v(i,J-1)) @@ -274,7 +274,7 @@ subroutine time_avg_state(ind, grid, surf_state, dt, reset, last) ssh(i,j) = surf_state%sea_lev(i,j) end do; end do call pass_var(ssh, grid%domain) - + ! d/dx ssh nvar = ind%o2x_So_dhdx do j=grid%jsc, grid%jec ; do i=grid%isc,grid%iec @@ -298,7 +298,7 @@ subroutine time_avg_state(ind, grid, surf_state, dt, reset, last) end if ind%time_avg_sbuffer(i,j,nvar) = ind%time_avg_sbuffer(i,j,nvar) + dt * slope * grid%IdxT(i,j) * grid%mask2dT(i,j) end do; end do - + ! d/dy ssh nvar = ind%o2x_So_dhdy do j=grid%jsc, grid%jec ; do i=grid%isc,grid%iec @@ -322,9 +322,9 @@ subroutine time_avg_state(ind, grid, surf_state, dt, reset, last) end if ind%time_avg_sbuffer(i,j,nvar) = ind%time_avg_sbuffer(i,j,nvar) + dt * slope * grid%IdyT(i,j) * grid%mask2dT(i,j) end do; end do - + ! Divide by total accumulated time - ind%accum_time = ind%accum_time + dt + ind%accum_time = ind%accum_time + dt if (present(last)) then !! \todo Do dhdx,dhdy need to be rotated before sending to the coupler? @@ -332,7 +332,7 @@ subroutine time_avg_state(ind, grid, surf_state, dt, reset, last) rtime = 1./ind%accum_time if (last) ind%time_avg_sbuffer(:,:,:) = ind%time_avg_sbuffer(:,:,:) * rtime - end if + end if end subroutine time_avg_state @@ -344,7 +344,7 @@ subroutine ocn_export(ind, grid, o2x) real(kind=8), intent(inout) :: o2x(:,:) integer :: i, j, n - + n = 0 do j=grid%jsc, grid%jec ; do i=grid%isc,grid%iec n = n+1 diff --git a/config_src/mct_driver/ocn_comp_mct.F90 b/config_src/mct_driver/ocn_comp_mct.F90 index 56bd487267..e747035ec8 100644 --- a/config_src/mct_driver/ocn_comp_mct.F90 +++ b/config_src/mct_driver/ocn_comp_mct.F90 @@ -43,7 +43,7 @@ module ocn_comp_mct use MOM_error_handler, only: MOM_error, FATAL, is_root_pe use MOM_time_manager, only: time_type, set_date, set_calendar_type, NOLEAP use coupler_indices, only: coupler_indices_init, cpl_indices, alloc_sbuffer, time_avg_state - use ocn_import_export, only: ocn_Export + use ocn_import_export, only: ocn_Export ! ! !PUBLIC MEMBER FUNCTIONS: @@ -66,7 +66,7 @@ module ocn_comp_mct private :: ocn_domain_mct ! !PRIVATE MODULE VARIABLES - type MCT_MOM_Data + type MCT_MOM_Data type(ocean_state_type), pointer :: ocn_state => NULL() !< Private state of ocean type(ocean_public_type), pointer :: ocn_public => NULL() !< Public state of ocean type(ocean_grid_type), pointer :: grid => NULL() ! A pointer to a grid structure @@ -76,7 +76,7 @@ module ocn_comp_mct type(cpl_indices), public :: ind !< Variable IDs - end type + end type type(MCT_MOM_Data) :: glb !======================================================================= @@ -263,7 +263,7 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) if (debug .and. root_pe().eq.pe_here()) print *, "calling alloc_sbuffer()", nsend call alloc_sbuffer(glb%ind,glb%grid,nsend) - + ! initialize necessary coupling info @@ -284,7 +284,7 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) ! end if if (debug .and. root_pe().eq.pe_here()) print *, "calling momo_sum_buffer" - + ! Reset time average of send buffer call time_avg_state(glb%ind, glb%grid, glb%ocn_surface, 1., reset=.true., last=.true.) diff --git a/config_src/mct_driver/ocn_import_export.F90 b/config_src/mct_driver/ocn_import_export.F90 index a314e60960..cc7cc37e0b 100644 --- a/config_src/mct_driver/ocn_import_export.F90 +++ b/config_src/mct_driver/ocn_import_export.F90 @@ -5,12 +5,12 @@ module ocn_import_export save ! accumulated sum of send buffer quantities for averaging before being sent - !real (r8), dimension(:,:,:,:), allocatable :: SBUFF_SUM - !real (r8) :: tlast_coupled + !real (r8), dimension(:,:,:,:), allocatable :: SBUFF_SUM + !real (r8) :: tlast_coupled !TODO: update the types of following vars - double precision, dimension(:,:,:,:), allocatable :: SBUFF_SUM - double precision :: tlast_coupled + double precision, dimension(:,:,:,:), allocatable :: SBUFF_SUM + double precision :: tlast_coupled contains !*********************************************************************** @@ -25,7 +25,7 @@ subroutine ocn_import(x2o, ldiag_cpl, errorCode) ! This routine receives message from cpl7 driver ! ! The following fields are always received from the coupler: -! +! ! o taux -- zonal wind stress (taux) (W/m2 ) ! o tauy -- meridonal wind stress (tauy) (W/m2 ) ! o snow -- water flux due to snow (kg/m2/s) @@ -41,15 +41,15 @@ subroutine ocn_import(x2o, ldiag_cpl, errorCode) ! o ifrac -- ice fraction ! o rofl -- river runoff flux (kg/m2/s) ! o rofi -- ice runoff flux (kg/m2/s) -! +! ! The following fields are sometimes received from the coupler, ! depending on model options: -! +! ! o pslv -- sea-level pressure (Pa) ! o duu10n -- 10m wind speed squared (m^2/s^2) ! o co2prog-- bottom atm level prognostic co2 ! o co2diag-- bottom atm level diagnostic co2 -! +! !----------------------------------------------------------------------- ! ! !REVISION HISTORY: @@ -93,7 +93,7 @@ end subroutine ocn_import ! !IROUTINE: ocn_export_mct ! !INTERFACE: - subroutine ocn_export(o2x, ldiag_cpl, errorCode) + subroutine ocn_export(o2x, ldiag_cpl, errorCode) ! !DESCRIPTION: ! This routine calls the routines necessary to send MOM6 fields to From 714e8d687cbb2edb8bc8d505e0f4b9acf4021f47 Mon Sep 17 00:00:00 2001 From: Alistair Adcroft Date: Fri, 21 Jul 2017 15:52:04 -0600 Subject: [PATCH 18/38] Adds placeholders for stepping foward MOM - Add place holders and diagnostics of time types --- config_src/mct_driver/ocn_comp_mct.F90 | 119 ++++++++++++++++++------- 1 file changed, 85 insertions(+), 34 deletions(-) diff --git a/config_src/mct_driver/ocn_comp_mct.F90 b/config_src/mct_driver/ocn_comp_mct.F90 index e747035ec8..ae944a30fc 100644 --- a/config_src/mct_driver/ocn_comp_mct.F90 +++ b/config_src/mct_driver/ocn_comp_mct.F90 @@ -11,8 +11,8 @@ module ocn_comp_mct ! !REVISION HISTORY: ! ! !USES: - use ESMF, only: ESMF_clock, ESMF_time - use ESMF, only: ESMF_ClockGet, ESMF_TimeGet + use ESMF, only: ESMF_clock, ESMF_time, ESMF_timeInterval + use ESMF, only: ESMF_ClockGet, ESMF_TimeGet, ESMF_TimeIntervalGet use seq_cdata_mod, only: seq_cdata use seq_cdata_mod, only: seq_cdata_setptrs use mct_mod, only: mct_gsMap, mct_gsmap_init, mct_gsMap_lsize, mct_gsmap_orderedpoints @@ -29,7 +29,7 @@ module ocn_comp_mct seq_infodata_start_type_brnch, & seq_infodata_PutData use seq_comm_mct, only: seq_comm_name, seq_comm_inst, seq_comm_suffix - use seq_timemgr_mod, only: seq_timemgr_EClockGetData + use seq_timemgr_mod, only: seq_timemgr_EClockGetData, seq_timemgr_RestartAlarmIsOn use perf_mod, only: t_startf, t_stopf use shr_kind_mod, only: SHR_KIND_R8 @@ -37,6 +37,7 @@ module ocn_comp_mct ! From MOM6 use ocean_model_mod, only: ocean_state_type, ocean_public_type, ocean_model_init_sfc use ocean_model_mod, only: ocean_model_init, get_state_pointers + use ocean_model_mod, only: ice_ocean_boundary_type, update_ocean_model use MOM_domains, only: MOM_infra_init, num_pes, root_pe, pe_here use MOM_grid, only: ocean_grid_type, get_global_grid_size use MOM_variables, only: surface @@ -96,7 +97,7 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) ! ! !INPUT/OUTPUT PARAMETERS: - type(ESMF_clock) , intent(inout) :: EClock + type(ESMF_Clock), intent(inout) :: EClock !< Time and time step ? \todo Why must this be intent(inout)? type(seq_cdata) , intent(inout) :: cdata_o type(mct_aVect) , intent(inout) :: x2o_o, o2x_o character(len=*), optional , intent(in) :: NLFilename ! Namelist filename @@ -112,8 +113,8 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) type(time_type) :: time_init ! Start time of coupled model's calendar type(time_type) :: time_in ! Start time for ocean model at initialization type(ESMF_time) :: current_time - integer :: year, month, day, hour, minute, seconds, rc - character(len=128) :: errMsg + type(ESMF_timeInterval) :: time_interval + integer :: year, month, day, hour, minute, seconds, seconds_n, seconds_d, rc character(len=384) :: runid character(len=384) :: runtype character(len=32) :: starttype ! infodata start type @@ -153,6 +154,7 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) integer :: ncouple_per_day = 48 logical :: lsend_precip_fact ! if T,send precip_fact to cpl for use in fw balance ! (partially-coupled option) + character(len=128) :: err_msg !----------------------------------------------------------------------- @@ -199,8 +201,26 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) call ESMF_TimeGet(current_time, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc) call set_calendar_type(NOLEAP) !TODO: confirm this - time_init = set_date(year, month, day, hour, minute, seconds, err_msg=errMsg) - time_in = set_date(year, month, day, hour, minute, seconds, err_msg=errMsg) + + time_init = set_date(year, month, day, hour, minute, seconds, err_msg=err_msg) + time_in = set_date(year, month, day, hour, minute, seconds, err_msg=err_msg) + + ! Debugging clocks + if (debug .and. is_root_pe()) then + write(6,*) 'ocn_init_mct, current time: y,m,d-',year,month,day,'h,m,s=',hour,minute,seconds + call ESMF_ClockGet(EClock, StartTime=current_time, rc=rc) + call ESMF_TimeGet(current_time, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc) + write(6,*) 'ocn_init_mct, start time: y,m,d-',year,month,day,'h,m,s=',hour,minute,seconds + call ESMF_ClockGet(EClock, StopTime=current_time, rc=rc) + call ESMF_TimeGet(current_time, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc) + write(6,*) 'ocn_init_mct, stop time: y,m,d-',year,month,day,'h,m,s=',hour,minute,seconds + call ESMF_ClockGet(EClock, PrevTime=current_time, rc=rc) + call ESMF_TimeGet(current_time, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc) + write(6,*) 'ocn_init_mct, previous time: y,m,d-',year,month,day,'h,m,s=',hour,minute,seconds + call ESMF_ClockGet(EClock, TimeStep=time_interval, rc=rc) + call ESMF_TimeIntervalGet(time_interval, yy=year, mm=month, d=day, s=seconds, sn=seconds_n, sd=seconds_d, rc=rc) + write(6,*) 'ocn_init_mct, time step: y,m,d-',year,month,day,'s,sn,sd=',seconds,seconds_n,seconds_d + endif npes = num_pes() pe0 = root_pe() @@ -270,6 +290,8 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) if (debug .and. root_pe().eq.pe_here()) print *, "calling seq_timemgr_eclockgetdata" call seq_timemgr_EClockGetData(EClock, dtime=ocn_cpl_dt) + + ! \todo Need interface to get dt from MOM6 mom_cpl_dt = seconds_in_day / ncouple_per_day if (mom_cpl_dt /= ocn_cpl_dt) then write(*,*) 'ERROR pop_cpl_dt and ocn_cpl_dt must be identical' @@ -314,35 +336,64 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) end subroutine ocn_init_mct -!*********************************************************************** -!BOP -! -! !IROUTINE: ocn_run_mct -! -! !INTERFACE: + !> Step forward ocean model for coupling interval subroutine ocn_run_mct( EClock, cdata_o, x2o_o, o2x_o) -! -! !DESCRIPTION: -! Run POP for a coupling interval -! -! !INPUT/OUTPUT PARAMETERS: - 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 + type(ESMF_Clock), intent(inout) :: EClock !< Time and time step ? \todo Why must this be intent(inout)? + type(seq_cdata), intent(inout) :: cdata_o + type(mct_aVect), intent(inout) :: x2o_o + type(mct_aVect), intent(inout) :: o2x_o + ! Local variables + type(ESMF_time) :: current_time + type(ESMF_timeInterval) :: time_interval + integer :: year, month, day, hour, minute, seconds, seconds_n, seconds_d, rc + logical :: write_restart_at_eod + type(time_type) :: time_start ! Start of coupled time interval to pass to MOM6 + type(time_type) :: coupling_timestep ! Coupled time interval to pass to MOM6 + character(len=128) :: err_msg + + ! Might need to be in glb to live on heap + type(ice_ocean_boundary_type) :: Ice_ocean_boundary + + ! Translate the current time (start of coupling interval) + call ESMF_ClockGet(EClock, currTime=current_time, rc=rc) + call ESMF_TimeGet(current_time, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc) + time_start = set_date(year, month, day, hour, minute, seconds, err_msg=err_msg) + + ! Debugging clocks + if (debug .and. is_root_pe()) then + write(6,*) 'ocn_run_mct, current time: y,m,d-',year,month,day,'h,m,s=',hour,minute,seconds + call ESMF_ClockGet(EClock, StartTime=current_time, rc=rc) + call ESMF_TimeGet(current_time, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc) + write(6,*) 'ocn_run_mct, start time: y,m,d-',year,month,day,'h,m,s=',hour,minute,seconds + call ESMF_ClockGet(EClock, StopTime=current_time, rc=rc) + call ESMF_TimeGet(current_time, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc) + write(6,*) 'ocn_run_mct, stop time: y,m,d-',year,month,day,'h,m,s=',hour,minute,seconds + call ESMF_ClockGet(EClock, PrevTime=current_time, rc=rc) + call ESMF_TimeGet(current_time, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc) + write(6,*) 'ocn_run_mct, previous time: y,m,d-',year,month,day,'h,m,s=',hour,minute,seconds + endif + + ! Translate the coupling time interval + call ESMF_ClockGet(EClock, TimeStep=time_interval, rc=rc) + call ESMF_TimeIntervalGet(time_interval, yy=year, mm=month, d=day, s=seconds, sn=seconds_n, sd=seconds_d, rc=rc) + time_start = set_date(year, month, day, 0, 0, seconds, err_msg=err_msg) + if (debug .and. is_root_pe()) then + write(6,*) 'ocn_run_mct, time step: y,m,d-',year,month,day,'s,sn,sd=',seconds,seconds_n,seconds_d + endif -! -! !REVISION HISTORY: -! Author: Mariana Vertenstein -!EOP -!----------------------------------------------------------------------- -! -! local variables -! -!----------------------------------------------------------------------- + ! set (actually, get from mct) the cdata pointers: + ! \todo this was done in _init_, is it needed again. Does this infodata need to be in glb%? + call seq_cdata_setptrs(cdata_o, infodata=glb%infodata) -!----------------------------------------------------------------------- -!EOC + ! Check alarms for flag to write restart at end of day + write_restart_at_eod = seq_timemgr_RestartAlarmIsOn(EClock) + ! \todo Let MOM6 know to write restart... + if (debug .and. is_root_pe()) write(6,*) 'ocn_run_mct, write_restart_at_eod=', write_restart_at_eod + + !call ocn_imprt goes her + + !call update_ocean_model(ice_ocean_boundary, glb%ocn_state, glb%ocn_public, & + ! time_start, coupling_timestep) end subroutine ocn_run_mct From 5cd8d7adac0df720d69036a2d7d68407c6b26ca4 Mon Sep 17 00:00:00 2001 From: Gustavo Marques Date: Mon, 24 Jul 2017 17:00:59 -0600 Subject: [PATCH 19/38] Filling ice_ocean_bnd, still needs work --- config_src/mct_driver/coupler_indices.F90 | 76 ++++++++++++++++++++ config_src/mct_driver/ocn_comp_mct.F90 | 87 +++++++++++++++-------- 2 files changed, 132 insertions(+), 31 deletions(-) diff --git a/config_src/mct_driver/coupler_indices.F90 b/config_src/mct_driver/coupler_indices.F90 index 24e52fa059..177da71120 100644 --- a/config_src/mct_driver/coupler_indices.F90 +++ b/config_src/mct_driver/coupler_indices.F90 @@ -9,6 +9,7 @@ module coupler_indices ! MOM types use MOM_grid, only : ocean_grid_type + use MOM_surface_forcing, only: ice_ocean_boundary_type ! MOM functions use MOM_domains, only : pass_var use MOM_variables, only : surface @@ -20,6 +21,7 @@ module coupler_indices public alloc_sbuffer public coupler_indices_init public time_avg_state + public fill_ice_ocean_bnd type, public :: cpl_indices @@ -358,4 +360,78 @@ subroutine ocn_export(ind, grid, o2x) end subroutine ocn_export + + subroutine fill_ice_ocean_bnd(ice_ocean_boundary, grid, x2o_o, ind) + type(ice_ocean_boundary_type), intent(in) :: ice_ocean_boundary !< A type for the ice ocean boundary + type(ocean_grid_type), intent(in) :: grid + !type(mct_aVect), intent(in) :: x2o_o + real(kind=8), intent(in) :: x2o_o(:,:) + type(cpl_indices), intent(inout) :: ind + + ! local variables + integer :: i, j, k, var + + ! variable that are not in ice_ocean_boundary: + ! latent (x2o_Foxx_lat) + ! surface Stokes drift, x-comp. (x2o_Sw_ustokes) + ! surface Stokes drift, y-comp. (x2o_Sw_vstokes) + ! wave model langmuir multiplier (x2o_Sw_lamult) + + ! biogeochemistry + ! Black Carbon hydrophobic release from sea ice component (x2o_Fioi_bcpho) + ! Black Carbon hydrophilic release from sea ice component (x2o_Fioi_bcphi) + ! dust release from sea ice component (x2o_Fioi_flxdst) + ! Black Carbon hydrophilic dry deposition (x2o_Faxa_bcphidry) + ! Black Carbon hydrophobic dry deposition (x2o_Faxa_bcphodry) + ! Black Carbon hydrophobic wet deposition (x2o_Faxa_bcphiwet) + ! Organic Carbon hydrophilic dry deposition (x2o_Faxa_ocphidry) + ! Organic Carbon hydrophobic dry deposition (x2o_Faxa_ocphodry) + ! Organic Carbon hydrophilic dry deposition (x2o_Faxa_ocphiwet) + ! Sizes 1 to 4 dust - wet deposition (x2o_Faxa_dstwet?) + ! Sizes 1 to 4 dust - dry deposition (x2o_Faxa_dstdry?) + + + ! need wind_stress_multiplier? + + write(*,*) 'max. k is:', (grid%jec-grid%jsc) * (grid%iec-grid%isc) + ! zonal wind stress (taux) + var = ind%x2o_Foxx_taux + write(*,*) 'taux', SIZE(x2o_o(:,var)) + write(*,*) 'ice_ocean_boundary%u_flux', SIZE(ice_ocean_boundary%u_flux(:,:)) + k = 0 + do j = grid%jsc, grid%jec + do i = grid%isc, grid%iec + k = k + 1 ! Increment position within gindex + ! zonal wind stress (taux) + ice_ocean_boundary%u_flux(i,j) = x2o_o(k,ind%x2o_Foxx_taux) + ! meridional wind stress (tauy) + ice_ocean_boundary%v_flux(i,j) = x2o_o(k,ind%x2o_Foxx_tauy) + ! sensible heat flux + ice_ocean_boundary%t_flux(i,j) = x2o_o(k,ind%x2o_Foxx_sen) + ! salt flux + ice_ocean_boundary%salt_flux(i,j) = x2o_o(k,ind%x2o_Fioi_salt) + ! heat flux from snow & ice melt + ice_ocean_boundary%calving_hflx(i,j) = x2o_o(k,ind%x2o_Fioi_melth) + ! snow melt flux + ice_ocean_boundary%fprec(i,j) = x2o_o(k,ind%x2o_Fioi_meltw) + ! river runoff flux + ice_ocean_boundary%runoff(i,j) = x2o_o(k,ind%x2o_Foxx_rofl) + ! ice runoff flux + ice_ocean_boundary%calving(i,j) = x2o_o(k,ind%x2o_Foxx_rofi) + ! liquid precipitation (rain) + ice_ocean_boundary%lprec(i,j) = x2o_o(k,ind%x2o_Faxa_rain) + ! froze precipitation (snow) + ice_ocean_boundary%fprec(i,j) = x2o_o(k,ind%x2o_Faxa_snow) + !!!!!!! LONGWAVE NEEDS TO BE FIXED !!!!!!! + ! longwave radiation (up) + ice_ocean_boundary%lw_flux(i,j) = x2o_o(k,ind%x2o_Foxx_lwup) + ! longwave radiation (down) + ice_ocean_boundary%lw_flux(i,j) = x2o_o(k,ind%x2o_Faxa_lwdn) + !!!!!!! SHORTWAVE NEEDS TO BE COMBINED !!!!!!! + ! net short-wave heat flux + ice_ocean_boundary%u_flux(i,j) = x2o_o(k,ind%x2o_Foxx_swnet) + enddo + enddo + + end subroutine fill_ice_ocean_bnd end module coupler_indices diff --git a/config_src/mct_driver/ocn_comp_mct.F90 b/config_src/mct_driver/ocn_comp_mct.F90 index ae944a30fc..69deabfce8 100644 --- a/config_src/mct_driver/ocn_comp_mct.F90 +++ b/config_src/mct_driver/ocn_comp_mct.F90 @@ -11,40 +11,41 @@ module ocn_comp_mct ! !REVISION HISTORY: ! ! !USES: - use ESMF, only: ESMF_clock, ESMF_time, ESMF_timeInterval - use ESMF, only: ESMF_ClockGet, ESMF_TimeGet, ESMF_TimeIntervalGet - use seq_cdata_mod, only: seq_cdata - use seq_cdata_mod, only: seq_cdata_setptrs - use mct_mod, only: mct_gsMap, mct_gsmap_init, mct_gsMap_lsize, mct_gsmap_orderedpoints - use mct_mod, only: mct_aVect, mct_aVect_init, mct_aVect_zero, mct_aVect_nRattr - use mct_mod, only: mct_gGrid, mct_gGrid_init, mct_gGrid_importRAttr, mct_gGrid_importIAttr - use seq_flds_mod, only: seq_flds_x2o_fields, & + use ESMF, only: ESMF_clock, ESMF_time, ESMF_timeInterval + use ESMF, only: ESMF_ClockGet, ESMF_TimeGet, ESMF_TimeIntervalGet + use seq_cdata_mod, only: seq_cdata + use seq_cdata_mod, only: seq_cdata_setptrs + use mct_mod, only: mct_gsMap, mct_gsmap_init, mct_gsMap_lsize, mct_gsmap_orderedpoints + use mct_mod, only: mct_aVect, mct_aVect_init, mct_aVect_zero, mct_aVect_nRattr + use mct_mod, only: mct_gGrid, mct_gGrid_init, mct_gGrid_importRAttr, mct_gGrid_importIAttr + use seq_flds_mod, only: seq_flds_x2o_fields, & seq_flds_o2x_fields, & SEQ_FLDS_DOM_COORD, & SEQ_FLDS_DOM_other - use seq_infodata_mod, only: seq_infodata_type, & + use seq_infodata_mod, only: seq_infodata_type, & seq_infodata_GetData, & seq_infodata_start_type_start, & seq_infodata_start_type_cont, & seq_infodata_start_type_brnch, & seq_infodata_PutData - use seq_comm_mct, only: seq_comm_name, seq_comm_inst, seq_comm_suffix - use seq_timemgr_mod, only: seq_timemgr_EClockGetData, seq_timemgr_RestartAlarmIsOn - use perf_mod, only: t_startf, t_stopf - use shr_kind_mod, only: SHR_KIND_R8 + use seq_comm_mct, only: seq_comm_name, seq_comm_inst, seq_comm_suffix + use seq_timemgr_mod, only: seq_timemgr_EClockGetData, seq_timemgr_RestartAlarmIsOn + use perf_mod, only: t_startf, t_stopf + use shr_kind_mod, only: SHR_KIND_R8 ! From MOM6 - use ocean_model_mod, only: ocean_state_type, ocean_public_type, ocean_model_init_sfc - use ocean_model_mod, only: ocean_model_init, get_state_pointers - use ocean_model_mod, only: ice_ocean_boundary_type, update_ocean_model - use MOM_domains, only: MOM_infra_init, num_pes, root_pe, pe_here - use MOM_grid, only: ocean_grid_type, get_global_grid_size - use MOM_variables, only: surface - use MOM_error_handler, only: MOM_error, FATAL, is_root_pe - use MOM_time_manager, only: time_type, set_date, set_calendar_type, NOLEAP - use coupler_indices, only: coupler_indices_init, cpl_indices, alloc_sbuffer, time_avg_state - use ocn_import_export, only: ocn_Export + use ocean_model_mod, only: ocean_state_type, ocean_public_type, ocean_model_init_sfc + use ocean_model_mod, only: ocean_model_init, get_state_pointers, update_ocean_model + use MOM_surface_forcing, only: ice_ocean_boundary_type + use MOM_domains, only: MOM_infra_init, num_pes, root_pe, pe_here + use MOM_grid, only: ocean_grid_type, get_global_grid_size + use MOM_variables, only: surface + use MOM_error_handler, only: MOM_error, FATAL, is_root_pe + use MOM_time_manager, only: time_type, set_date, set_calendar_type, NOLEAP + use coupler_indices, only: coupler_indices_init, cpl_indices, alloc_sbuffer + use coupler_indices, only: time_avg_state, fill_ice_ocean_bnd + use ocn_import_export, only: ocn_Export ! ! !PUBLIC MEMBER FUNCTIONS: @@ -70,9 +71,9 @@ module ocn_comp_mct type MCT_MOM_Data type(ocean_state_type), pointer :: ocn_state => NULL() !< Private state of ocean type(ocean_public_type), pointer :: ocn_public => NULL() !< Public state of ocean - type(ocean_grid_type), pointer :: grid => NULL() ! A pointer to a grid structure + type(ocean_grid_type), pointer :: grid => NULL() !< A pointer to a grid structure type(surface), pointer :: ocn_surface => NULL() !< A pointer to the ocean surface state - + type(ice_ocean_boundary_type) :: ice_ocean_boundary !< A pointer to the ice ocean boundary type type(seq_infodata_type), pointer :: infodata type(cpl_indices), public :: ind !< Variable IDs @@ -124,7 +125,8 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) integer :: lsize, nsend, nrecv logical :: ldiag_cpl = .false. integer :: ni, nj - + integer :: isc, iec, jsc, jec !< Indices for the start and end of the domain + !! in the x and y dir., respectively. ! mct variables (these are local for now) integer :: MOM_MCT_ID type(mct_gsMap), pointer :: MOM_MCT_gsMap => NULL() ! 2d, points to cdata @@ -241,6 +243,7 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) call t_stopf('MOM_init') + !--------------------------------------------------------------------- ! Initialize MCT attribute vectors and indices !--------------------------------------------------------------------- @@ -321,6 +324,29 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) ! Size of global domain call get_global_grid_size(glb%grid, ni, nj) + ! allocate ice_ocean_boundary + isc = glb%grid%isc; iec = glb%grid%iec; + jsc = glb%grid%jsc; jec = glb%grid%jec; + allocate(glb%ice_ocean_boundary%u_flux(isc:iec,jsc:jec)); glb%ice_ocean_boundary%u_flux(:,:) = 0.0 + allocate(glb%ice_ocean_boundary%v_flux(isc:iec,jsc:jec)); glb%ice_ocean_boundary%v_flux(:,:) = 0.0 + allocate(glb%ice_ocean_boundary%t_flux(isc:iec,jsc:jec)); glb%ice_ocean_boundary%t_flux(:,:) = 0.0 + allocate(glb%ice_ocean_boundary%q_flux(isc:iec,jsc:jec)); glb%ice_ocean_boundary%q_flux(:,:) = 0.0 + allocate(glb%ice_ocean_boundary%salt_flux(isc:iec,jsc:jec)); glb%ice_ocean_boundary%salt_flux(:,:) = 0.0 + allocate(glb%ice_ocean_boundary%lw_flux(isc:iec,jsc:jec)); glb%ice_ocean_boundary%lw_flux(:,:) = 0.0 + allocate(glb%ice_ocean_boundary%sw_flux_vis_dir(isc:iec,jsc:jec)); glb%ice_ocean_boundary%sw_flux_vis_dir(:,:) = 0.0 + allocate(glb%ice_ocean_boundary%sw_flux_vis_dif(isc:iec,jsc:jec)); glb%ice_ocean_boundary%sw_flux_vis_dif(:,:) = 0.0 + allocate(glb%ice_ocean_boundary%sw_flux_nir_dir(isc:iec,jsc:jec)); glb%ice_ocean_boundary%sw_flux_nir_dir(:,:) = 0.0 + allocate(glb%ice_ocean_boundary%sw_flux_nir_dif(isc:iec,jsc:jec)); glb%ice_ocean_boundary%sw_flux_nir_dif(:,:) = 0.0 + allocate(glb%ice_ocean_boundary%lprec(isc:iec,jsc:jec)); glb%ice_ocean_boundary%lprec(:,:) = 0.0 + allocate(glb%ice_ocean_boundary%fprec(isc:iec,jsc:jec)); glb%ice_ocean_boundary%fprec(:,:) = 0.0 + allocate(glb%ice_ocean_boundary%runoff(isc:iec,jsc:jec)); glb%ice_ocean_boundary%runoff(:,:) = 0.0 + allocate(glb%ice_ocean_boundary%calving(isc:iec,jsc:jec)); glb%ice_ocean_boundary%calving(:,:) = 0.0 + allocate(glb%ice_ocean_boundary%runoff_hflx(isc:iec,jsc:jec)); glb%ice_ocean_boundary%runoff_hflx(:,:) = 0.0 + allocate(glb%ice_ocean_boundary%calving_hflx(isc:iec,jsc:jec)); glb%ice_ocean_boundary%calving_hflx(:,:) = 0.0 + allocate(glb%ice_ocean_boundary%p(isc:iec,jsc:jec)); glb%ice_ocean_boundary%p(:,:) = 0.0 + allocate(glb%ice_ocean_boundary%mi(isc:iec,jsc:jec)); glb%ice_ocean_boundary%mi(:,:) = 0.0 + + if (debug .and. root_pe().eq.pe_here()) print *, "calling seq_infodata_putdata" call seq_infodata_PutData( glb%infodata, & @@ -351,9 +377,6 @@ subroutine ocn_run_mct( EClock, cdata_o, x2o_o, o2x_o) type(time_type) :: coupling_timestep ! Coupled time interval to pass to MOM6 character(len=128) :: err_msg - ! Might need to be in glb to live on heap - type(ice_ocean_boundary_type) :: Ice_ocean_boundary - ! Translate the current time (start of coupling interval) call ESMF_ClockGet(EClock, currTime=current_time, rc=rc) call ESMF_TimeGet(current_time, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc) @@ -390,9 +413,11 @@ subroutine ocn_run_mct( EClock, cdata_o, x2o_o, o2x_o) ! \todo Let MOM6 know to write restart... if (debug .and. is_root_pe()) write(6,*) 'ocn_run_mct, write_restart_at_eod=', write_restart_at_eod - !call ocn_imprt goes her + ! fill ice ocean boundary + call fill_ice_ocean_bnd(glb%ice_ocean_boundary, glb%grid, x2o_o%rattr, glb%ind) + if (debug .and. is_root_pe()) write(6,*) 'fill_ice_ocean_bnd' - !call update_ocean_model(ice_ocean_boundary, glb%ocn_state, glb%ocn_public, & + !call update_ocean_model(glb%ice_ocean_boundary, glb%ocn_state, glb%ocn_public, & ! time_start, coupling_timestep) end subroutine ocn_run_mct From 1f39c84cebed6dbaf0acd6a7df1b4f358349bed0 Mon Sep 17 00:00:00 2001 From: Alistair Adcroft Date: Tue, 25 Jul 2017 08:47:50 -0600 Subject: [PATCH 20/38] Replaces use of "surface" with "ocean_public_type" - To later facilitate MOM doing the time-averaging within the DT_FORCING time-step, we need to use the ocean_public_type when export surface state to the MCT coupler. - Removes a buffer array inspired by POP interface. - Removes the time-averaging routine we wrote that worked on the POP-like buffer. --- config_src/mct_driver/coupler_indices.F90 | 132 +++++----------------- config_src/mct_driver/ocn_comp_mct.F90 | 20 +--- 2 files changed, 31 insertions(+), 121 deletions(-) diff --git a/config_src/mct_driver/coupler_indices.F90 b/config_src/mct_driver/coupler_indices.F90 index 24e52fa059..dadfdf38e3 100644 --- a/config_src/mct_driver/coupler_indices.F90 +++ b/config_src/mct_driver/coupler_indices.F90 @@ -11,15 +11,14 @@ module coupler_indices use MOM_grid, only : ocean_grid_type ! MOM functions use MOM_domains, only : pass_var - use MOM_variables, only : surface + use ocean_model_mod, only : ocean_public_type implicit none private - public alloc_sbuffer public coupler_indices_init - public time_avg_state + public ocn_export type, public :: cpl_indices @@ -88,9 +87,6 @@ module coupler_indices integer, dimension(:), allocatable :: x2o_fracr_col ! fraction of ocean cell used in radiation computations, per column integer, dimension(:), allocatable :: x2o_qsw_fracr_col ! qsw * fracr, per column - real, dimension(:,:,:),allocatable :: time_avg_sbuffer !< time averages of send buffer - real :: accum_time !< time for accumulation - end type cpl_indices contains @@ -208,79 +204,38 @@ subroutine coupler_indices_init(ind) end subroutine coupler_indices_init + !> Maps outgoing ocean data to MCT buffer + subroutine ocn_export(ind, ocn_public, grid, o2x) + type(cpl_indices), intent(inout) :: ind !< Index + type(ocean_public_type), intent(in) :: ocn_public !< Ocean surface state + type(ocean_grid_type), intent(in) :: grid !< Ocean model grid + real(kind=8), intent(inout) :: o2x(:,:) !< MCT outgoing bugger + ! Local variables + real, dimension(grid%isd:grid%ied,grid%jsd:grid%jed) :: ssh !< Local copy of sea_lev with updated halo + integer :: i, j, n + real :: slp_L, slp_R, slp_C, slope, u_min, u_max - subroutine alloc_sbuffer(ind, grid, nsend) - - ! Parameters - type(cpl_indices), intent(inout) :: ind - type(ocean_grid_type), intent(in) :: grid - integer, intent(in) :: nsend - - allocate(ind%time_avg_sbuffer(grid%isd:grid%ied,grid%jsd:grid%jed,nsend)) - - end subroutine alloc_sbuffer - - - subroutine time_avg_state(ind, grid, surf_state, dt, reset, last) - - type(cpl_indices), intent(inout) :: ind !< module control structure - type(ocean_grid_type), intent(inout) :: grid !< ocean grid (inout in order to do halo update) - type(surface), intent(in) :: surf_state !< ocean surface state - real, intent(in) :: dt !< time interval to accumulate (seconds) - logical, optional, intent(in) :: reset !< if present and true, reset accumulations - logical, optional, intent(in) :: last !< if present and true, divide by accumulated time - - ! local variables - integer :: i,j,nvar - real :: rtime, slp_L, slp_R, slp_C, u_min, u_max, slope - real, dimension(grid%isd:grid%ied, grid%jsd:grid%jed) :: ssh - - if (present(reset)) then - if (reset) then - ind%time_avg_sbuffer(:,:,:) = 0. - ind%accum_time = 0. - end if - end if - - ! sst - nvar = ind%o2x_So_t - do j=grid%jsc, grid%jec ; do i=grid%isc,grid%iec - ind%time_avg_sbuffer(i,j,nvar) = ind%time_avg_sbuffer(i,j,nvar)+dt * surf_state%sst(i,j) - end do; end do - - ! sss - nvar = ind%o2x_So_s - do j=grid%jsc, grid%jec ; do i=grid%isc,grid%iec - ind%time_avg_sbuffer(i,j,nvar) = ind%time_avg_sbuffer(i,j,nvar)+dt * surf_state%sss(i,j) - end do; end do - - - ! u - nvar = ind%o2x_So_u - do j=grid%jsc, grid%jec ; do i=grid%isc,grid%iec - ind%time_avg_sbuffer(i,j,nvar) = ind%time_avg_sbuffer(i,j,nvar)+dt * & - 0.5*(surf_state%u(I,j)+surf_state%u(I-1,j)) - end do; end do - - ! v - nvar = ind%o2x_So_v + n = 0 do j=grid%jsc, grid%jec ; do i=grid%isc,grid%iec - ind%time_avg_sbuffer(i,j,nvar) = ind%time_avg_sbuffer(i,j,nvar)+dt * & - 0.5*(surf_state%v(i,J)+surf_state%v(i,J-1)) + n = n+1 + o2x(ind%o2x_So_t, n) = ocn_public%t_surf(i,j) * grid%mask2dT(i,j) + o2x(ind%o2x_So_s, n) = ocn_public%s_surf(i,j) * grid%mask2dT(i,j) + o2x(ind%o2x_So_u, n) = ocn_public%u_surf(i,j) * grid%mask2dT(i,j) + o2x(ind%o2x_So_v, n) = ocn_public%v_surf(i,j) * grid%mask2dT(i,j) end do; end do - ! ssh + ! ssh (make a copy in order to do a halo update) do j=grid%jsc, grid%jec ; do i=grid%isc,grid%iec - ssh(i,j) = surf_state%sea_lev(i,j) + ssh(i,j) = ocn_public%sea_lev(i,j) end do; end do call pass_var(ssh, grid%domain) ! d/dx ssh - nvar = ind%o2x_So_dhdx + n = 0 do j=grid%jsc, grid%jec ; do i=grid%isc,grid%iec + n = n+1 ! This is a simple second-order difference - ! ind%time_avg_sbuffer(i,j,nvar) = ind%time_avg_sbuffer(i,j,nvar) + dt * & - ! 0.5 * (ssh(i+1,j) + ssh(i-1,j)) * grid%IdxT(i,j) * grid%mask2dT(i,j) + ! o2x(ind%o2x_So_dhdx, n) = 0.5 * (ssh(i+1,j) + ssh(i-1,j)) * grid%IdxT(i,j) * grid%mask2dT(i,j) ! This is a PLM slope which might be less prone to the A-grid null mode slp_L = ssh(i,j) - ssh(i-1,j) slp_R = ssh(i+1,j) - ssh(i,j) @@ -296,15 +251,13 @@ subroutine time_avg_state(ind, grid, surf_state, dt, reset, last) ! larger extreme values. slope = 0.0 end if - ind%time_avg_sbuffer(i,j,nvar) = ind%time_avg_sbuffer(i,j,nvar) + dt * slope * grid%IdxT(i,j) * grid%mask2dT(i,j) + o2x(ind%o2x_So_dhdx, n) = slope * grid%IdxT(i,j) * grid%mask2dT(i,j) end do; end do ! d/dy ssh - nvar = ind%o2x_So_dhdy do j=grid%jsc, grid%jec ; do i=grid%isc,grid%iec ! This is a simple second-order difference - ! ind%time_avg_sbuffer(i,j,nvar) = ind%time_avg_sbuffer(i,j,nvar) + dt * & - ! 0.5 * (ssh(i,j+1) + ssh(i,j-1)) * grid%IdyT(i,j) * grid%mask2dT(i,j) + ! o2x(ind%o2x_So_dhdy, n) = 0.5 * (ssh(i,j+1) + ssh(i,j-1)) * grid%IdyT(i,j) * grid%mask2dT(i,j) ! This is a PLM slope which might be less prone to the A-grid null mode slp_L = ssh(i,j) - ssh(i,j-1) slp_R = ssh(i,j+1) - ssh(i,j) @@ -320,40 +273,7 @@ subroutine time_avg_state(ind, grid, surf_state, dt, reset, last) ! larger extreme values. slope = 0.0 end if - ind%time_avg_sbuffer(i,j,nvar) = ind%time_avg_sbuffer(i,j,nvar) + dt * slope * grid%IdyT(i,j) * grid%mask2dT(i,j) - end do; end do - - ! Divide by total accumulated time - ind%accum_time = ind%accum_time + dt - if (present(last)) then - - !! \todo Do dhdx,dhdy need to be rotated before sending to the coupler? - !! \todo Do u,v need to be rotated before sending to the coupler? - - rtime = 1./ind%accum_time - if (last) ind%time_avg_sbuffer(:,:,:) = ind%time_avg_sbuffer(:,:,:) * rtime - end if - - end subroutine time_avg_state - - - subroutine ocn_export(ind, grid, o2x) - - type(cpl_indices), intent(in) :: ind - type(ocean_grid_type), intent(in) :: grid - real(kind=8), intent(inout) :: o2x(:,:) - - integer :: i, j, n - - n = 0 - do j=grid%jsc, grid%jec ; do i=grid%isc,grid%iec - n = n+1 - o2x(ind%o2x_So_t, n) = ind%time_avg_sbuffer(i,j,ind%o2x_So_t) - o2x(ind%o2x_So_s, n) = ind%time_avg_sbuffer(i,j,ind%o2x_So_s) - o2x(ind%o2x_So_u, n) = ind%time_avg_sbuffer(i,j,ind%o2x_So_u) - o2x(ind%o2x_So_v, n) = ind%time_avg_sbuffer(i,j,ind%o2x_So_v) - o2x(ind%o2x_So_dhdx, n) = ind%time_avg_sbuffer(i,j,ind%o2x_So_dhdx) - o2x(ind%o2x_So_dhdy, n) = ind%time_avg_sbuffer(i,j,ind%o2x_So_dhdy) + o2x(ind%o2x_So_dhdy, n) = slope * grid%IdyT(i,j) * grid%mask2dT(i,j) end do; end do end subroutine ocn_export diff --git a/config_src/mct_driver/ocn_comp_mct.F90 b/config_src/mct_driver/ocn_comp_mct.F90 index ae944a30fc..b98081d914 100644 --- a/config_src/mct_driver/ocn_comp_mct.F90 +++ b/config_src/mct_driver/ocn_comp_mct.F90 @@ -43,8 +43,8 @@ module ocn_comp_mct use MOM_variables, only: surface use MOM_error_handler, only: MOM_error, FATAL, is_root_pe use MOM_time_manager, only: time_type, set_date, set_calendar_type, NOLEAP - use coupler_indices, only: coupler_indices_init, cpl_indices, alloc_sbuffer, time_avg_state - use ocn_import_export, only: ocn_Export + use coupler_indices, only: coupler_indices_init, cpl_indices + use coupler_indices, only: ocn_export ! ! !PUBLIC MEMBER FUNCTIONS: @@ -71,7 +71,6 @@ module ocn_comp_mct type(ocean_state_type), pointer :: ocn_state => NULL() !< Private state of ocean type(ocean_public_type), pointer :: ocn_public => NULL() !< Public state of ocean type(ocean_grid_type), pointer :: grid => NULL() ! A pointer to a grid structure - type(surface), pointer :: ocn_surface => NULL() !< A pointer to the ocean surface state type(seq_infodata_type), pointer :: infodata @@ -229,6 +228,7 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) glb%ocn_public%is_ocean_PE = .true. allocate(glb%ocn_public%pelist(npes)) glb%ocn_public%pelist(:) = (/(i,i=pe0,pe0+npes)/) + ! \todo Set other bits of glb$ocn_public ! Initialize the MOM6 model call ocean_model_init(glb%ocn_public, glb%ocn_state, time_init, time_in) @@ -237,7 +237,7 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) call ocean_model_init_sfc(glb%ocn_state, glb%ocn_public) ! store pointers to components inside MOM - call get_state_pointers(glb%ocn_state, grid=glb%grid, surf=glb%ocn_surface) + call get_state_pointers(glb%ocn_state, grid=glb%grid) call t_stopf('MOM_init') @@ -280,11 +280,6 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) nsend = mct_avect_nRattr(o2x_o) nrecv = mct_avect_nRattr(x2o_o) - if (debug .and. root_pe().eq.pe_here()) print *, "calling alloc_sbuffer()", nsend - - call alloc_sbuffer(glb%ind,glb%grid,nsend) - - ! initialize necessary coupling info if (debug .and. root_pe().eq.pe_here()) print *, "calling seq_timemgr_eclockgetdata" @@ -305,14 +300,9 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) ! call seq_infodata_PutData( infodata, precip_fact=precip_fact) ! end if - if (debug .and. root_pe().eq.pe_here()) print *, "calling momo_sum_buffer" - - ! Reset time average of send buffer - call time_avg_state(glb%ind, glb%grid, glb%ocn_surface, 1., reset=.true., last=.true.) if (debug .and. root_pe().eq.pe_here()) print *, "calling ocn_export" - - call ocn_export(o2x_o%rattr, ldiag_cpl, errorCode) + call ocn_export(glb%ind, glb%ocn_public, glb%grid, o2x_o%rattr) call t_stopf('MOM_mct_init') From c83e23833661bc14b34a8b9f38cfd871ef2c4ac9 Mon Sep 17 00:00:00 2001 From: Alistair Adcroft Date: Tue, 25 Jul 2017 09:32:03 -0600 Subject: [PATCH 21/38] Correct indexing when using ocean_public_type - The ocean_public_type uses global indexing without halos. --- config_src/mct_driver/coupler_indices.F90 | 33 ++++++++++++++--------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/config_src/mct_driver/coupler_indices.F90 b/config_src/mct_driver/coupler_indices.F90 index dadfdf38e3..c0ea1eab44 100644 --- a/config_src/mct_driver/coupler_indices.F90 +++ b/config_src/mct_driver/coupler_indices.F90 @@ -212,22 +212,29 @@ subroutine ocn_export(ind, ocn_public, grid, o2x) real(kind=8), intent(inout) :: o2x(:,:) !< MCT outgoing bugger ! Local variables real, dimension(grid%isd:grid%ied,grid%jsd:grid%jed) :: ssh !< Local copy of sea_lev with updated halo - integer :: i, j, n + integer :: i, j, n, ig, jg real :: slp_L, slp_R, slp_C, slope, u_min, u_max + ! Copy from ocn_public to o2x. ocn_public uses global indexing with no halos. + ! The mask comes from "grid" that uses the usual MOM domain that has halos + ! and does not use global indexing. n = 0 - do j=grid%jsc, grid%jec ; do i=grid%isc,grid%iec - n = n+1 - o2x(ind%o2x_So_t, n) = ocn_public%t_surf(i,j) * grid%mask2dT(i,j) - o2x(ind%o2x_So_s, n) = ocn_public%s_surf(i,j) * grid%mask2dT(i,j) - o2x(ind%o2x_So_u, n) = ocn_public%u_surf(i,j) * grid%mask2dT(i,j) - o2x(ind%o2x_So_v, n) = ocn_public%v_surf(i,j) * grid%mask2dT(i,j) - end do; end do - - ! ssh (make a copy in order to do a halo update) - do j=grid%jsc, grid%jec ; do i=grid%isc,grid%iec - ssh(i,j) = ocn_public%sea_lev(i,j) - end do; end do + do j=grid%jsc, grid%jec + jg = j + grid%jdg_offset + do i=grid%isc,grid%iec + n = n+1 + ig = i + grid%idg_offset + o2x(ind%o2x_So_t, n) = ocn_public%t_surf(ig,jg) * grid%mask2dT(i,j) + o2x(ind%o2x_So_s, n) = ocn_public%s_surf(ig,jg) * grid%mask2dT(i,j) + o2x(ind%o2x_So_u, n) = ocn_public%u_surf(ig,jg) * grid%mask2dT(i,j) + o2x(ind%o2x_So_v, n) = ocn_public%v_surf(ig,jg) * grid%mask2dT(i,j) + ! Make a copy of ssh in order to do a halo update. We use the usual MOM domain + ! in order to update halos. i.e. does not use global indexing. + ssh(i,j) = ocn_public%sea_lev(ig,jg) + end do + end do + + ! Update halo of ssh so we can calculate gradients call pass_var(ssh, grid%domain) ! d/dx ssh From b69ab336021802dbaf6b495bbabe0d21e9c78c10 Mon Sep 17 00:00:00 2001 From: Gustavo Marques Date: Tue, 25 Jul 2017 11:05:47 -0600 Subject: [PATCH 22/38] Filling ice_ocean_bnd - Draft --- config_src/mct_driver/coupler_indices.F90 | 30 ++++++++++++----------- config_src/mct_driver/ocn_comp_mct.F90 | 4 +-- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/config_src/mct_driver/coupler_indices.F90 b/config_src/mct_driver/coupler_indices.F90 index 177da71120..90c20cba34 100644 --- a/config_src/mct_driver/coupler_indices.F90 +++ b/config_src/mct_driver/coupler_indices.F90 @@ -369,7 +369,7 @@ subroutine fill_ice_ocean_bnd(ice_ocean_boundary, grid, x2o_o, ind) type(cpl_indices), intent(inout) :: ind ! local variables - integer :: i, j, k, var + integer :: i, j, k, ig, jg ! variable that are not in ice_ocean_boundary: ! latent (x2o_Foxx_lat) @@ -393,35 +393,37 @@ subroutine fill_ice_ocean_bnd(ice_ocean_boundary, grid, x2o_o, ind) ! need wind_stress_multiplier? - write(*,*) 'max. k is:', (grid%jec-grid%jsc) * (grid%iec-grid%isc) + ! Copy from x2o to ice_ocean_boundary. ice_ocean_boundary uses global indexing with no halos. + write(*,*) 'max. k is:', (grid%jec-grid%jsc+1) * (grid%iec-grid%isc+1) ! zonal wind stress (taux) - var = ind%x2o_Foxx_taux - write(*,*) 'taux', SIZE(x2o_o(:,var)) + write(*,*) 'taux', SIZE(x2o_o(ind%x2o_Foxx_taux,:)) write(*,*) 'ice_ocean_boundary%u_flux', SIZE(ice_ocean_boundary%u_flux(:,:)) k = 0 do j = grid%jsc, grid%jec + jg = j + grid%jdg_offset do i = grid%isc, grid%iec k = k + 1 ! Increment position within gindex + ig = i + grid%idg_offset ! zonal wind stress (taux) - ice_ocean_boundary%u_flux(i,j) = x2o_o(k,ind%x2o_Foxx_taux) + ice_ocean_boundary%u_flux(i,j) = x2o_o(ind%x2o_Foxx_taux,k) ! meridional wind stress (tauy) - ice_ocean_boundary%v_flux(i,j) = x2o_o(k,ind%x2o_Foxx_tauy) + ice_ocean_boundary%v_flux(i,j) = x2o_o(ind%x2o_Foxx_tauy,k) ! sensible heat flux - ice_ocean_boundary%t_flux(i,j) = x2o_o(k,ind%x2o_Foxx_sen) + ice_ocean_boundary%t_flux(i,j) = x2o_o(ind%x2o_Foxx_sen,k) ! salt flux - ice_ocean_boundary%salt_flux(i,j) = x2o_o(k,ind%x2o_Fioi_salt) + ice_ocean_boundary%salt_flux(i,j) = x2o_o(ind%x2o_Fioi_salt,k) ! heat flux from snow & ice melt - ice_ocean_boundary%calving_hflx(i,j) = x2o_o(k,ind%x2o_Fioi_melth) + ice_ocean_boundary%calving_hflx(i,j) = x2o_o(ind%x2o_Fioi_melth,k) ! snow melt flux - ice_ocean_boundary%fprec(i,j) = x2o_o(k,ind%x2o_Fioi_meltw) + ice_ocean_boundary%fprec(i,j) = x2o_o(ind%x2o_Fioi_meltw,k) ! river runoff flux - ice_ocean_boundary%runoff(i,j) = x2o_o(k,ind%x2o_Foxx_rofl) + ice_ocean_boundary%runoff(i,j) = x2o_o(ind%x2o_Foxx_rofl,k) ! ice runoff flux - ice_ocean_boundary%calving(i,j) = x2o_o(k,ind%x2o_Foxx_rofi) + ice_ocean_boundary%calving(i,j) = x2o_o(ind%x2o_Foxx_rofi,k) ! liquid precipitation (rain) - ice_ocean_boundary%lprec(i,j) = x2o_o(k,ind%x2o_Faxa_rain) + ice_ocean_boundary%lprec(i,j) = x2o_o(ind%x2o_Faxa_rain,k) ! froze precipitation (snow) - ice_ocean_boundary%fprec(i,j) = x2o_o(k,ind%x2o_Faxa_snow) + ice_ocean_boundary%fprec(i,j) = x2o_o(ind%x2o_Faxa_snow,k) !!!!!!! LONGWAVE NEEDS TO BE FIXED !!!!!!! ! longwave radiation (up) ice_ocean_boundary%lw_flux(i,j) = x2o_o(k,ind%x2o_Foxx_lwup) diff --git a/config_src/mct_driver/ocn_comp_mct.F90 b/config_src/mct_driver/ocn_comp_mct.F90 index 69deabfce8..08957c032f 100644 --- a/config_src/mct_driver/ocn_comp_mct.F90 +++ b/config_src/mct_driver/ocn_comp_mct.F90 @@ -417,8 +417,8 @@ subroutine ocn_run_mct( EClock, cdata_o, x2o_o, o2x_o) call fill_ice_ocean_bnd(glb%ice_ocean_boundary, glb%grid, x2o_o%rattr, glb%ind) if (debug .and. is_root_pe()) write(6,*) 'fill_ice_ocean_bnd' - !call update_ocean_model(glb%ice_ocean_boundary, glb%ocn_state, glb%ocn_public, & - ! time_start, coupling_timestep) +! call update_ocean_model(glb%ice_ocean_boundary, glb%ocn_state, glb%ocn_public, & +! time_start, coupling_timestep) end subroutine ocn_run_mct From 7ce40e5e006ac25dd5fcc0bbdffd9344a6b2d1d1 Mon Sep 17 00:00:00 2001 From: Gustavo Marques Date: Tue, 25 Jul 2017 11:40:52 -0600 Subject: [PATCH 23/38] Fix undefined reference to fill_ice_ocean_bnd --- config_src/mct_driver/coupler_indices.F90 | 2 +- config_src/mct_driver/ocn_comp_mct.F90 | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/config_src/mct_driver/coupler_indices.F90 b/config_src/mct_driver/coupler_indices.F90 index e69df58b81..b1d9e1175b 100644 --- a/config_src/mct_driver/coupler_indices.F90 +++ b/config_src/mct_driver/coupler_indices.F90 @@ -19,7 +19,6 @@ module coupler_indices private public coupler_indices_init - public time_avg_state public fill_ice_ocean_bnd public ocn_export @@ -364,4 +363,5 @@ subroutine fill_ice_ocean_bnd(ice_ocean_boundary, grid, x2o_o, ind) enddo end subroutine fill_ice_ocean_bnd + end module coupler_indices diff --git a/config_src/mct_driver/ocn_comp_mct.F90 b/config_src/mct_driver/ocn_comp_mct.F90 index be8eb247bf..6ca1b6fed5 100644 --- a/config_src/mct_driver/ocn_comp_mct.F90 +++ b/config_src/mct_driver/ocn_comp_mct.F90 @@ -44,8 +44,7 @@ module ocn_comp_mct use MOM_error_handler, only: MOM_error, FATAL, is_root_pe use MOM_time_manager, only: time_type, set_date, set_calendar_type, NOLEAP use coupler_indices, only: coupler_indices_init, cpl_indices - use coupler_indices, only: ocn_export - + use coupler_indices, only: ocn_export, fill_ice_ocean_bnd ! ! !PUBLIC MEMBER FUNCTIONS: implicit none From 6b6289a6a1c2eafcb3444494d3e056bfbaa4bfdd Mon Sep 17 00:00:00 2001 From: Gustavo Marques Date: Tue, 25 Jul 2017 13:26:33 -0600 Subject: [PATCH 24/38] Remove trailing whitespace --- config_src/mct_driver/coupler_indices.F90 | 16 ++++++++-------- config_src/mct_driver/ocn_comp_mct.F90 | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/config_src/mct_driver/coupler_indices.F90 b/config_src/mct_driver/coupler_indices.F90 index b1d9e1175b..0021439726 100644 --- a/config_src/mct_driver/coupler_indices.F90 +++ b/config_src/mct_driver/coupler_indices.F90 @@ -300,14 +300,14 @@ subroutine fill_ice_ocean_bnd(ice_ocean_boundary, grid, x2o_o, ind) ! variable that are not in ice_ocean_boundary: ! latent (x2o_Foxx_lat) - ! surface Stokes drift, x-comp. (x2o_Sw_ustokes) - ! surface Stokes drift, y-comp. (x2o_Sw_vstokes) + ! surface Stokes drift, x-comp. (x2o_Sw_ustokes) + ! surface Stokes drift, y-comp. (x2o_Sw_vstokes) ! wave model langmuir multiplier (x2o_Sw_lamult) ! biogeochemistry ! Black Carbon hydrophobic release from sea ice component (x2o_Fioi_bcpho) ! Black Carbon hydrophilic release from sea ice component (x2o_Fioi_bcphi) - ! dust release from sea ice component (x2o_Fioi_flxdst) + ! dust release from sea ice component (x2o_Fioi_flxdst) ! Black Carbon hydrophilic dry deposition (x2o_Faxa_bcphidry) ! Black Carbon hydrophobic dry deposition (x2o_Faxa_bcphodry) ! Black Carbon hydrophobic wet deposition (x2o_Faxa_bcphiwet) @@ -316,12 +316,12 @@ subroutine fill_ice_ocean_bnd(ice_ocean_boundary, grid, x2o_o, ind) ! Organic Carbon hydrophilic dry deposition (x2o_Faxa_ocphiwet) ! Sizes 1 to 4 dust - wet deposition (x2o_Faxa_dstwet?) ! Sizes 1 to 4 dust - dry deposition (x2o_Faxa_dstdry?) - + ! need wind_stress_multiplier? ! Copy from x2o to ice_ocean_boundary. ice_ocean_boundary uses global indexing with no halos. - write(*,*) 'max. k is:', (grid%jec-grid%jsc+1) * (grid%iec-grid%isc+1) + write(*,*) 'max. k is:', (grid%jec-grid%jsc+1) * (grid%iec-grid%isc+1) ! zonal wind stress (taux) write(*,*) 'taux', SIZE(x2o_o(ind%x2o_Foxx_taux,:)) write(*,*) 'ice_ocean_boundary%u_flux', SIZE(ice_ocean_boundary%u_flux(:,:)) @@ -336,13 +336,13 @@ subroutine fill_ice_ocean_bnd(ice_ocean_boundary, grid, x2o_o, ind) ! meridional wind stress (tauy) ice_ocean_boundary%v_flux(i,j) = x2o_o(ind%x2o_Foxx_tauy,k) ! sensible heat flux - ice_ocean_boundary%t_flux(i,j) = x2o_o(ind%x2o_Foxx_sen,k) + ice_ocean_boundary%t_flux(i,j) = x2o_o(ind%x2o_Foxx_sen,k) ! salt flux ice_ocean_boundary%salt_flux(i,j) = x2o_o(ind%x2o_Fioi_salt,k) ! heat flux from snow & ice melt ice_ocean_boundary%calving_hflx(i,j) = x2o_o(ind%x2o_Fioi_melth,k) ! snow melt flux - ice_ocean_boundary%fprec(i,j) = x2o_o(ind%x2o_Fioi_meltw,k) + ice_ocean_boundary%fprec(i,j) = x2o_o(ind%x2o_Fioi_meltw,k) ! river runoff flux ice_ocean_boundary%runoff(i,j) = x2o_o(ind%x2o_Foxx_rofl,k) ! ice runoff flux @@ -358,7 +358,7 @@ subroutine fill_ice_ocean_bnd(ice_ocean_boundary, grid, x2o_o, ind) ice_ocean_boundary%lw_flux(i,j) = x2o_o(k,ind%x2o_Faxa_lwdn) !!!!!!! SHORTWAVE NEEDS TO BE COMBINED !!!!!!! ! net short-wave heat flux - ice_ocean_boundary%u_flux(i,j) = x2o_o(k,ind%x2o_Foxx_swnet) + ice_ocean_boundary%u_flux(i,j) = x2o_o(k,ind%x2o_Foxx_swnet) enddo enddo diff --git a/config_src/mct_driver/ocn_comp_mct.F90 b/config_src/mct_driver/ocn_comp_mct.F90 index 6ca1b6fed5..3f4081b945 100644 --- a/config_src/mct_driver/ocn_comp_mct.F90 +++ b/config_src/mct_driver/ocn_comp_mct.F90 @@ -314,8 +314,8 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) call get_global_grid_size(glb%grid, ni, nj) ! allocate ice_ocean_boundary - isc = glb%grid%isc; iec = glb%grid%iec; - jsc = glb%grid%jsc; jec = glb%grid%jec; + isc = glb%grid%isc; iec = glb%grid%iec; + jsc = glb%grid%jsc; jec = glb%grid%jec; allocate(glb%ice_ocean_boundary%u_flux(isc:iec,jsc:jec)); glb%ice_ocean_boundary%u_flux(:,:) = 0.0 allocate(glb%ice_ocean_boundary%v_flux(isc:iec,jsc:jec)); glb%ice_ocean_boundary%v_flux(:,:) = 0.0 allocate(glb%ice_ocean_boundary%t_flux(isc:iec,jsc:jec)); glb%ice_ocean_boundary%t_flux(:,:) = 0.0 @@ -334,8 +334,8 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) allocate(glb%ice_ocean_boundary%calving_hflx(isc:iec,jsc:jec)); glb%ice_ocean_boundary%calving_hflx(:,:) = 0.0 allocate(glb%ice_ocean_boundary%p(isc:iec,jsc:jec)); glb%ice_ocean_boundary%p(:,:) = 0.0 allocate(glb%ice_ocean_boundary%mi(isc:iec,jsc:jec)); glb%ice_ocean_boundary%mi(:,:) = 0.0 - - + + if (debug .and. root_pe().eq.pe_here()) print *, "calling seq_infodata_putdata" call seq_infodata_PutData( glb%infodata, & From 37a53bc2f81612f33f499b1549a826e1ad6bff76 Mon Sep 17 00:00:00 2001 From: alperaltuntas Date: Tue, 25 Jul 2017 15:54:56 -0600 Subject: [PATCH 25/38] reorganize file structure --- config_src/mct_driver/coupler_indices.F90 | 30 ++++++++++++----------- config_src/mct_driver/ocn_comp_mct.F90 | 15 +++++++----- 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/config_src/mct_driver/coupler_indices.F90 b/config_src/mct_driver/coupler_indices.F90 index 0021439726..0d3cbb4f93 100644 --- a/config_src/mct_driver/coupler_indices.F90 +++ b/config_src/mct_driver/coupler_indices.F90 @@ -11,7 +11,7 @@ module coupler_indices use MOM_grid, only : ocean_grid_type use MOM_surface_forcing, only: ice_ocean_boundary_type ! MOM functions - use MOM_domains, only : pass_var + use MOM_domains, only : pass_var, AGRID use ocean_model_mod, only : ocean_public_type implicit none @@ -332,36 +332,38 @@ subroutine fill_ice_ocean_bnd(ice_ocean_boundary, grid, x2o_o, ind) k = k + 1 ! Increment position within gindex ig = i + grid%idg_offset ! zonal wind stress (taux) - ice_ocean_boundary%u_flux(i,j) = x2o_o(ind%x2o_Foxx_taux,k) + ice_ocean_boundary%u_flux(ig,jg) = 0.0 ! x20_o(ind%x2o_Foxx_taux,k) ! meridional wind stress (tauy) - ice_ocean_boundary%v_flux(i,j) = x2o_o(ind%x2o_Foxx_tauy,k) + ice_ocean_boundary%v_flux(ig,jg) = 0.0 ! x20_o(ind%x2o_Foxx_tauy,k) ! sensible heat flux - ice_ocean_boundary%t_flux(i,j) = x2o_o(ind%x2o_Foxx_sen,k) + ice_ocean_boundary%t_flux(ig,jg) = 0.0 ! x20_o(ind%x2o_Foxx_sen,k) ! salt flux - ice_ocean_boundary%salt_flux(i,j) = x2o_o(ind%x2o_Fioi_salt,k) + ice_ocean_boundary%salt_flux(ig,jg) = 0.0 ! x20_o(ind%x2o_Fioi_salt,k) ! heat flux from snow & ice melt - ice_ocean_boundary%calving_hflx(i,j) = x2o_o(ind%x2o_Fioi_melth,k) + ice_ocean_boundary%calving_hflx(ig,jg) = 0.0 ! x20_o(ind%x2o_Fioi_melth,k) ! snow melt flux - ice_ocean_boundary%fprec(i,j) = x2o_o(ind%x2o_Fioi_meltw,k) + ice_ocean_boundary%fprec(ig,jg) = 0.0 ! x20_o(ind%x2o_Fioi_meltw,k) ! river runoff flux - ice_ocean_boundary%runoff(i,j) = x2o_o(ind%x2o_Foxx_rofl,k) + ice_ocean_boundary%runoff(ig,jg) = 0.0 ! x20_o(ind%x2o_Foxx_rofl,k) ! ice runoff flux - ice_ocean_boundary%calving(i,j) = x2o_o(ind%x2o_Foxx_rofi,k) + ice_ocean_boundary%calving(ig,jg) = 0.0 ! x20_o(ind%x2o_Foxx_rofi,k) ! liquid precipitation (rain) - ice_ocean_boundary%lprec(i,j) = x2o_o(ind%x2o_Faxa_rain,k) + ice_ocean_boundary%lprec(ig,jg) = 0.0 ! x20_o(ind%x2o_Faxa_rain,k) ! froze precipitation (snow) - ice_ocean_boundary%fprec(i,j) = x2o_o(ind%x2o_Faxa_snow,k) + ice_ocean_boundary%fprec(ig,jg) = 0.0 ! x20_o(ind%x2o_Faxa_snow,k) !!!!!!! LONGWAVE NEEDS TO BE FIXED !!!!!!! ! longwave radiation (up) - ice_ocean_boundary%lw_flux(i,j) = x2o_o(k,ind%x2o_Foxx_lwup) + ice_ocean_boundary%lw_flux(ig,jg) = 0.0 ! x20_o(k,ind%x2o_Foxx_lwup) ! longwave radiation (down) - ice_ocean_boundary%lw_flux(i,j) = x2o_o(k,ind%x2o_Faxa_lwdn) + ice_ocean_boundary%lw_flux(ig,jg) = 0.0 ! x20_o(k,ind%x2o_Faxa_lwdn) !!!!!!! SHORTWAVE NEEDS TO BE COMBINED !!!!!!! ! net short-wave heat flux - ice_ocean_boundary%u_flux(i,j) = x2o_o(k,ind%x2o_Foxx_swnet) + ice_ocean_boundary%u_flux(ig,jg) = 0.0 ! x20_o(k,ind%x2o_Foxx_swnet) enddo enddo + ice_ocean_boundary%wind_stagger = AGRID + end subroutine fill_ice_ocean_bnd end module coupler_indices diff --git a/config_src/mct_driver/ocn_comp_mct.F90 b/config_src/mct_driver/ocn_comp_mct.F90 index 3f4081b945..a94b015811 100644 --- a/config_src/mct_driver/ocn_comp_mct.F90 +++ b/config_src/mct_driver/ocn_comp_mct.F90 @@ -42,7 +42,7 @@ module ocn_comp_mct use MOM_grid, only: ocean_grid_type, get_global_grid_size use MOM_variables, only: surface use MOM_error_handler, only: MOM_error, FATAL, is_root_pe - use MOM_time_manager, only: time_type, set_date, set_calendar_type, NOLEAP + use MOM_time_manager, only: time_type, set_date, set_time, set_calendar_type, NOLEAP use coupler_indices, only: coupler_indices_init, cpl_indices use coupler_indices, only: ocn_export, fill_ice_ocean_bnd ! @@ -313,9 +313,11 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) ! Size of global domain call get_global_grid_size(glb%grid, ni, nj) - ! allocate ice_ocean_boundary - isc = glb%grid%isc; iec = glb%grid%iec; - jsc = glb%grid%jsc; jec = glb%grid%jec; + ! Allocate ice_ocean_boundary using global indexing without halos + isc = glb%grid%isc + glb%grid%idg_offset + iec = glb%grid%iec + glb%grid%idg_offset + jsc = glb%grid%jsc + glb%grid%jdg_offset + jec = glb%grid%jec + glb%grid%jdg_offset allocate(glb%ice_ocean_boundary%u_flux(isc:iec,jsc:jec)); glb%ice_ocean_boundary%u_flux(:,:) = 0.0 allocate(glb%ice_ocean_boundary%v_flux(isc:iec,jsc:jec)); glb%ice_ocean_boundary%v_flux(:,:) = 0.0 allocate(glb%ice_ocean_boundary%t_flux(isc:iec,jsc:jec)); glb%ice_ocean_boundary%t_flux(:,:) = 0.0 @@ -392,6 +394,7 @@ subroutine ocn_run_mct( EClock, cdata_o, x2o_o, o2x_o) if (debug .and. is_root_pe()) then write(6,*) 'ocn_run_mct, time step: y,m,d-',year,month,day,'s,sn,sd=',seconds,seconds_n,seconds_d endif + coupling_timestep = set_time(seconds, days=day, err_msg=err_msg) ! set (actually, get from mct) the cdata pointers: ! \todo this was done in _init_, is it needed again. Does this infodata need to be in glb%? @@ -406,8 +409,8 @@ subroutine ocn_run_mct( EClock, cdata_o, x2o_o, o2x_o) call fill_ice_ocean_bnd(glb%ice_ocean_boundary, glb%grid, x2o_o%rattr, glb%ind) if (debug .and. is_root_pe()) write(6,*) 'fill_ice_ocean_bnd' -! call update_ocean_model(glb%ice_ocean_boundary, glb%ocn_state, glb%ocn_public, & -! time_start, coupling_timestep) + call update_ocean_model(glb%ice_ocean_boundary, glb%ocn_state, glb%ocn_public, & + time_start, coupling_timestep) end subroutine ocn_run_mct From f7c26a52b6dbde2e2377e71936be141809d8e461 Mon Sep 17 00:00:00 2001 From: Gustavo Marques Date: Tue, 25 Jul 2017 16:23:34 -0600 Subject: [PATCH 26/38] Clean the module and start doxygenizing it --- config_src/mct_driver/ocn_comp_mct.F90 | 345 +++++++++---------------- 1 file changed, 119 insertions(+), 226 deletions(-) diff --git a/config_src/mct_driver/ocn_comp_mct.F90 b/config_src/mct_driver/ocn_comp_mct.F90 index 3f4081b945..63cdbb14e5 100644 --- a/config_src/mct_driver/ocn_comp_mct.F90 +++ b/config_src/mct_driver/ocn_comp_mct.F90 @@ -1,136 +1,98 @@ +!> This is the main driver for MOM6 in CIME module ocn_comp_mct -!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -!BOP -! !MODULE: ocn_comp_mct -! !INTERFACE: - -! !DESCRIPTION: -! This is the main driver for MOM6 in CIME -! -! !REVISION HISTORY: -! -! !USES: - use ESMF, only: ESMF_clock, ESMF_time, ESMF_timeInterval - use ESMF, only: ESMF_ClockGet, ESMF_TimeGet, ESMF_TimeIntervalGet - use seq_cdata_mod, only: seq_cdata - use seq_cdata_mod, only: seq_cdata_setptrs - use mct_mod, only: mct_gsMap, mct_gsmap_init, mct_gsMap_lsize, mct_gsmap_orderedpoints - use mct_mod, only: mct_aVect, mct_aVect_init, mct_aVect_zero, mct_aVect_nRattr - use mct_mod, only: mct_gGrid, mct_gGrid_init, mct_gGrid_importRAttr, mct_gGrid_importIAttr - use seq_flds_mod, only: seq_flds_x2o_fields, & - seq_flds_o2x_fields, & - SEQ_FLDS_DOM_COORD, & - SEQ_FLDS_DOM_other - use seq_infodata_mod, only: seq_infodata_type, & - seq_infodata_GetData, & - seq_infodata_start_type_start, & - seq_infodata_start_type_cont, & - seq_infodata_start_type_brnch, & - seq_infodata_PutData - use seq_comm_mct, only: seq_comm_name, seq_comm_inst, seq_comm_suffix - use seq_timemgr_mod, only: seq_timemgr_EClockGetData, seq_timemgr_RestartAlarmIsOn - use perf_mod, only: t_startf, t_stopf - use shr_kind_mod, only: SHR_KIND_R8 - - - ! From MOM6 - use ocean_model_mod, only: ocean_state_type, ocean_public_type, ocean_model_init_sfc - use ocean_model_mod, only: ocean_model_init, get_state_pointers - use ocean_model_mod, only: ice_ocean_boundary_type, update_ocean_model - use MOM_domains, only: MOM_infra_init, num_pes, root_pe, pe_here - use MOM_grid, only: ocean_grid_type, get_global_grid_size - use MOM_variables, only: surface - use MOM_error_handler, only: MOM_error, FATAL, is_root_pe - use MOM_time_manager, only: time_type, set_date, set_calendar_type, NOLEAP - use coupler_indices, only: coupler_indices_init, cpl_indices - use coupler_indices, only: ocn_export, fill_ice_ocean_bnd -! -! !PUBLIC MEMBER FUNCTIONS: - implicit none +! This file is part of MOM6. See LICENSE.md for the license. + +! mct modules +use ESMF, only: ESMF_clock, ESMF_time, ESMF_timeInterval +use ESMF, only: ESMF_ClockGet, ESMF_TimeGet, ESMF_TimeIntervalGet +use seq_cdata_mod, only: seq_cdata +use seq_cdata_mod, only: seq_cdata_setptrs +use mct_mod, only: mct_gsMap, mct_gsmap_init, mct_gsMap_lsize, & + mct_gsmap_orderedpoints +use mct_mod, only: mct_aVect, mct_aVect_init, mct_aVect_zero, & + mct_aVect_nRattr +use mct_mod, only: mct_gGrid, mct_gGrid_init, mct_gGrid_importRAttr, & + mct_gGrid_importIAttr +use seq_flds_mod, only: seq_flds_x2o_fields, seq_flds_o2x_fields, seq_flds_dom_coord, & + seq_flds_dom_other +use seq_infodata_mod, only: seq_infodata_type, seq_infodata_GetData, & + seq_infodata_start_type_start, seq_infodata_start_type_cont, & + seq_infodata_start_type_brnch, seq_infodata_PutData +use seq_comm_mct, only: seq_comm_name, seq_comm_inst, seq_comm_suffix +use seq_timemgr_mod, only: seq_timemgr_EClockGetData, seq_timemgr_RestartAlarmIsOn +use perf_mod, only: t_startf, t_stopf +use shr_kind_mod, only: shr_kind_r8 + +! MOM6 modules +use ocean_model_mod, only: ocean_state_type, ocean_public_type, ocean_model_init_sfc +use ocean_model_mod, only: ocean_model_init, get_state_pointers +use ocean_model_mod, only: ice_ocean_boundary_type, update_ocean_model +use MOM_domains, only: MOM_infra_init, num_pes, root_pe, pe_here +use MOM_grid, only: ocean_grid_type, get_global_grid_size +use MOM_variables, only: surface +use MOM_error_handler, only: MOM_error, FATAL, is_root_pe +use MOM_time_manager, only: time_type, set_date, set_calendar_type, NOLEAP +use coupler_indices, only: coupler_indices_init, cpl_indices +use coupler_indices, only: ocn_export, fill_ice_ocean_bnd + + +! By default make data private +implicit none; private + ! Public member functions public :: ocn_init_mct public :: ocn_run_mct public :: ocn_final_mct - private ! By default make data private + ! Flag for debugging logical, parameter :: debug=.true. -! -! ! PUBLIC DATA: -! -! !REVISION HISTORY: -! Author: Mariana Vertenstein -! -!EOP -! !PRIVATE MODULE FUNCTIONS: - private :: ocn_SetGSMap_mct - private :: ocn_domain_mct - -! !PRIVATE MODULE VARIABLES + !> Control structure for this module type MCT_MOM_Data - type(ocean_state_type), pointer :: ocn_state => NULL() !< Private state of ocean - type(ocean_public_type), pointer :: ocn_public => NULL() !< Public state of ocean - type(ocean_grid_type), pointer :: grid => NULL() !< A pointer to a grid structure - type(surface), pointer :: ocn_surface => NULL() !< A pointer to the ocean surface state - type(ice_ocean_boundary_type) :: ice_ocean_boundary !< A pointer to the ice ocean boundary type - type(seq_infodata_type), pointer :: infodata + type(ocean_state_type), pointer :: ocn_state => NULL() !< The private state of ocean + type(ocean_public_type), pointer :: ocn_public => NULL() !< The public state of ocean + type(ocean_grid_type), pointer :: grid => NULL() !< The grid structure + type(surface), pointer :: ocn_surface => NULL() !< The ocean surface state + type(ice_ocean_boundary_type) :: ice_ocean_boundary !< The ice ocean boundary type + type(seq_infodata_type), pointer :: infodata !< The input info type + type(cpl_indices), public :: ind !< Variable IDs - type(cpl_indices), public :: ind !< Variable IDs + end type MCT_MOM_Data - end type - type(MCT_MOM_Data) :: glb - -!======================================================================= + type(MCT_MOM_Data) :: glb !< global structure contains -!*********************************************************************** -!BOP -! -! !IROUTINE: ocn_init_mct -! -! !INTERFACE: - subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) -! -! !DESCRIPTION: -! Initialize POP -! -! !INPUT/OUTPUT PARAMETERS: - - type(ESMF_Clock), intent(inout) :: EClock !< Time and time step ? \todo Why must this be intent(inout)? - type(seq_cdata) , intent(inout) :: cdata_o - type(mct_aVect) , intent(inout) :: x2o_o, o2x_o - character(len=*), optional , intent(in) :: NLFilename ! Namelist filename -! -! !REVISION HISTORY: -! Author: Mariana Vertenstein -!EOP -!----------------------------------------------------------------------- -! -! local variables -! -!----------------------------------------------------------------------- - type(time_type) :: time_init ! Start time of coupled model's calendar - type(time_type) :: time_in ! Start time for ocean model at initialization - type(ESMF_time) :: current_time - type(ESMF_timeInterval) :: time_interval +!> Initializes MOM6 +subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) + type(ESMF_Clock), intent(inout) :: EClock !< Time and time step ? \todo Why must this + !! be intent(inout)? + type(seq_cdata) , intent(inout) :: cdata_o !< Input parameters + type(mct_aVect) , intent(inout) :: x2o_o !< Fluxes from coupler to ocean, computed by ocean + type(mct_aVect) , intent(inout) :: o2x_o !< Fluxes from ocean to coupler, computed by ocean + character(len=*), optional , intent(in) :: NLFilename !< Namelist filename + + ! local variables + type(time_type) :: time_init !< Start time of coupled model's calendar + type(time_type) :: time_in !< Start time for ocean model at initialization + type(ESMF_time) :: current_time !< Current time + type(ESMF_timeInterval) :: time_interval !< Time interval integer :: year, month, day, hour, minute, seconds, seconds_n, seconds_d, rc - character(len=384) :: runid - character(len=384) :: runtype - character(len=32) :: starttype ! infodata start type - integer :: mpicom_ocn - integer :: npes, pe0 + character(len=384) :: runid !< Run ID + character(len=384) :: runtype !< Run type + character(len=32) :: starttype !< infodata start type + integer :: mpicom_ocn !< MPI ocn communicator + integer :: npes, pe0 !< # of processors and current processor integer :: i, errorCode integer :: lsize, nsend, nrecv logical :: ldiag_cpl = .false. - integer :: ni, nj - integer :: isc, iec, jsc, jec !< Indices for the start and end of the domain - !! in the x and y dir., respectively. + integer :: isc, iec, jsc, jec, ni, nj !< Indices for the start and end of the domain + !! in the x and y dir., respectively. ! mct variables (these are local for now) integer :: MOM_MCT_ID - type(mct_gsMap), pointer :: MOM_MCT_gsMap => NULL() ! 2d, points to cdata - type(mct_gGrid), pointer :: MOM_MCT_dom => NULL() ! 2d, points to cdata - type(mct_gsMap) :: MOM_MCT_gsMap3d ! for 3d streams, local - type(mct_gGrid) :: MOM_MCT_dom3d ! for 3d streams, local + type(mct_gsMap), pointer :: MOM_MCT_gsMap => NULL() !< 2d, points to cdata + type(mct_gGrid), pointer :: MOM_MCT_dom => NULL() !< 2d, points to cdata + type(mct_gsMap) :: MOM_MCT_gsMap3d !< for 3d streams, local + type(mct_gGrid) :: MOM_MCT_dom3d !< for 3d streams, local ! time management integer :: ocn_cpl_dt @@ -148,24 +110,19 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) character(len=16) :: inst_suffix !!!DANGER!!!: change the following vars with the corresponding MOM6 vars - integer :: km=1 ! number of vertical levels - integer :: nx_block=0, ny_block=0 ! size of block domain in x,y dir including ghost cells - integer :: max_blocks_clinic=0 !max number of blocks per processor in each distribution + integer :: km=1 !< Number of vertical levels + integer :: nx_block=0, ny_block=0 !< Size of block domain in x,y dir including ghost cells + integer :: max_blocks_clinic=0 !< Max. number of blocks per processor in each distribution integer :: ncouple_per_day = 48 - logical :: lsend_precip_fact ! if T,send precip_fact to cpl for use in fw balance - ! (partially-coupled option) - character(len=128) :: err_msg - -!----------------------------------------------------------------------- + logical :: lsend_precip_fact !< If T,send precip_fact to cpl for use in fw balance + !! (partially-coupled option) + character(len=128) :: err_msg !< Error message ! set (actually, get from mct) the cdata pointers: call seq_cdata_setptrs(cdata_o, id=MOM_MCT_ID, mpicom=mpicom_ocn, & gsMap=MOM_MCT_gsMap, dom=MOM_MCT_dom, infodata=glb%infodata) - !--------------------------------------------------------------------- ! Initialize the model run - !--------------------------------------------------------------------- - call coupler_indices_init(glb%ind) call seq_infodata_GetData( glb%infodata, case_name=runid ) @@ -184,24 +141,17 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) end if ! instance control - inst_name = seq_comm_name(MOM_MCT_ID) inst_index = seq_comm_inst(MOM_MCT_ID) inst_suffix = seq_comm_suffix(MOM_MCT_ID) - !--------------------------------------------------------------------- ! Initialize MOM6 - !--------------------------------------------------------------------- - call t_startf('MOM_init') - call MOM_infra_init(mpicom_ocn) - call ESMF_ClockGet(EClock, currTime=current_time, rc=rc) call ESMF_TimeGet(current_time, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc) call set_calendar_type(NOLEAP) !TODO: confirm this - time_init = set_date(year, month, day, hour, minute, seconds, err_msg=err_msg) time_in = set_date(year, month, day, hour, minute, seconds, err_msg=err_msg) @@ -242,11 +192,7 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) call t_stopf('MOM_init') - - !--------------------------------------------------------------------- ! Initialize MCT attribute vectors and indices - !--------------------------------------------------------------------- - call t_startf('MOM_mct_init') if (debug .and. root_pe().eq.pe_here()) print *, "calling ocn_SetGSMap_mct" @@ -346,24 +292,21 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) if (debug .and. root_pe().eq.pe_here()) print *, "leaving ocean_init_mct" -!----------------------------------------------------------------------- -!EOC +end subroutine ocn_init_mct - end subroutine ocn_init_mct - - !> Step forward ocean model for coupling interval - subroutine ocn_run_mct( EClock, cdata_o, x2o_o, o2x_o) +!> Step forward ocean model for coupling interval +subroutine ocn_run_mct( EClock, cdata_o, x2o_o, o2x_o) type(ESMF_Clock), intent(inout) :: EClock !< Time and time step ? \todo Why must this be intent(inout)? - type(seq_cdata), intent(inout) :: cdata_o - type(mct_aVect), intent(inout) :: x2o_o - type(mct_aVect), intent(inout) :: o2x_o + type(seq_cdata), intent(inout) :: cdata_o !< Input parameters + type(mct_aVect), intent(inout) :: x2o_o !< Fluxes from coupler to ocean, computed by ocean + type(mct_aVect), intent(inout) :: o2x_o !< Fluxes from ocean to coupler, computed by ocean ! Local variables type(ESMF_time) :: current_time type(ESMF_timeInterval) :: time_interval integer :: year, month, day, hour, minute, seconds, seconds_n, seconds_d, rc logical :: write_restart_at_eod - type(time_type) :: time_start ! Start of coupled time interval to pass to MOM6 - type(time_type) :: coupling_timestep ! Coupled time interval to pass to MOM6 + type(time_type) :: time_start !< Start of coupled time interval to pass to MOM6 + type(time_type) :: coupling_timestep !< Coupled time interval to pass to MOM6 character(len=128) :: err_msg ! Translate the current time (start of coupling interval) @@ -409,40 +352,21 @@ subroutine ocn_run_mct( EClock, cdata_o, x2o_o, o2x_o) ! call update_ocean_model(glb%ice_ocean_boundary, glb%ocn_state, glb%ocn_public, & ! time_start, coupling_timestep) - end subroutine ocn_run_mct - -!*********************************************************************** -!BOP -! -! !IROUTINE: ocn_final_mct -! -! !INTERFACE: - subroutine ocn_final_mct( EClock, cdata_o, x2o_o, o2x_o) -! -! !DESCRIPTION: -! Finalize POP -! -! !USES: -! !ARGUMENTS: +end subroutine ocn_run_mct + +!> Finalizes MOM6 +!! +!! \todo This needs to be done here. +subroutine ocn_final_mct( EClock, cdata_o, x2o_o, o2x_o) 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 -! -! !REVISION HISTORY: -! Author: Fei Liu -!EOP -!BOC -!----------------------------------------------------------------------- -! -! local variables -! -!----------------------------------------------------------------------- - - end subroutine ocn_final_mct - - -!> This routine mct global seg maps for the MOM decomposition + type(mct_aVect) , intent(inout) :: x2o_o !< Fluxes from coupler to ocean, computed by ocean + type(mct_aVect) , intent(inout) :: o2x_o !< Fluxes from ocean to coupler, computed by ocean + +end subroutine ocn_final_mct + + +!> 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. subroutine ocn_SetGSMap_mct(mpicom_ocn, MOM_MCT_ID, gsMap_ocn, gsMap3d_ocn) @@ -451,12 +375,12 @@ subroutine ocn_SetGSMap_mct(mpicom_ocn, MOM_MCT_ID, gsMap_ocn, gsMap3d_ocn) type(mct_gsMap), intent(inout) :: gsMap_ocn !< MCT global segment map for 2d data type(mct_gsMap), intent(inout) :: gsMap3d_ocn !< MCT global segment map for 3d data ! Local variables - integer :: lsize ! Local size of indirect indexing array - integer :: i, j, k ! Local indices - integer :: ni, nj ! Declared sizes of h-point arrays - integer :: ig, jg ! Global indices - type(ocean_grid_type), pointer :: grid => NULL() ! A pointer to a grid structure - integer, allocatable :: gindex(:) ! Indirect indices + integer :: lsize !< Local size of indirect indexing array + integer :: i, j, k !< Local indices + integer :: ni, nj !< Declared sizes of h-point arrays + integer :: ig, jg !< Global indices + type(ocean_grid_type), pointer :: grid => NULL() !< A pointer to a grid structure + integer, allocatable :: gindex(:) !< Indirect indices grid => glb%grid ! for convenience if (.not. associated(grid)) call MOM_error(FATAL, 'ocn_comp_mct.F90, ocn_SetGSMap_mct():' // & @@ -469,7 +393,7 @@ subroutine ocn_SetGSMap_mct(mpicom_ocn, MOM_MCT_ID, gsMap_ocn, gsMap3d_ocn) call get_global_grid_size(grid, ni, nj) ! Create indirect indices for the computational domain - allocate( gindex( lsize ) ) + allocate(gindex(lsize)) ! Set indirect indices in gindex k = 0 @@ -478,39 +402,24 @@ subroutine ocn_SetGSMap_mct(mpicom_ocn, MOM_MCT_ID, gsMap_ocn, gsMap3d_ocn) do i = grid%isc, grid%iec ig = i + grid%idg_offset ! TODO: check this calculation k = k + 1 ! Increment position within gindex - gindex(k) = ni * ( jg - 1 ) + ig + gindex(k) = ni * (jg - 1) + ig enddo enddo ! Tell MCT how to indirectly index into the 2d buffer - call mct_gsMap_init( gsMap_ocn, gindex, mpicom_ocn, MOM_MCT_ID, lsize, ni * nj) + call mct_gsMap_init(gsMap_ocn, gindex, mpicom_ocn, MOM_MCT_ID, lsize, ni * nj) - deallocate( gindex ) + deallocate(gindex) end subroutine ocn_SetGSMap_mct - -!*********************************************************************** -!BOP -! !IROUTINE: ocn_domain_mct -! !INTERFACE: - +!> Sets MCT global segment maps for the MOM6 decomposition subroutine ocn_domain_mct( lsize, gsMap_ocn, dom_ocn) + integer , intent(in) :: lsize !< Size of attr. vector + type(mct_gsMap), intent(in) :: gsMap_ocn !< MCT global segment map for 2d data + type(mct_ggrid), intent(inout) :: dom_ocn !< WHAT IS THIS? -! !DESCRIPTION: -! This routine mct global seg maps for the pop decomposition -! -! !REVISION HISTORY: -! same as module -! -! !INPUT/OUTPUT PARAMETERS: - - implicit none - integer , intent(in) :: lsize - type(mct_gsMap), intent(in) :: gsMap_ocn - type(mct_ggrid), intent(inout) :: dom_ocn - -! Local Variables + ! Local Variables integer, parameter :: SHR_REAL_R8 = selected_real_kind(12) integer, pointer :: idata(:) integer :: i,j,k @@ -583,22 +492,6 @@ subroutine ocn_domain_mct( lsize, gsMap_ocn, dom_ocn) deallocate(data) deallocate(idata) -!EOP -!BOC -!----------------------------------------------------------------------- -! -! local variables -! -!----------------------------------------------------------------------- - - - -!----------------------------------------------------------------------- -!EOC - - end subroutine ocn_domain_mct - +end subroutine ocn_domain_mct end module ocn_comp_mct - -!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| From d77936e2b528a705bb1c522c2b737e5b5aed2058 Mon Sep 17 00:00:00 2001 From: Gustavo Marques Date: Wed, 26 Jul 2017 11:05:35 -0600 Subject: [PATCH 27/38] Fix intent(inout) in ice_ocean_boundary --- config_src/mct_driver/coupler_indices.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config_src/mct_driver/coupler_indices.F90 b/config_src/mct_driver/coupler_indices.F90 index 0d3cbb4f93..cd7d61bb33 100644 --- a/config_src/mct_driver/coupler_indices.F90 +++ b/config_src/mct_driver/coupler_indices.F90 @@ -289,7 +289,7 @@ end subroutine ocn_export subroutine fill_ice_ocean_bnd(ice_ocean_boundary, grid, x2o_o, ind) - type(ice_ocean_boundary_type), intent(in) :: ice_ocean_boundary !< A type for the ice ocean boundary + type(ice_ocean_boundary_type), intent(inout) :: ice_ocean_boundary !< A type for the ice ocean boundary type(ocean_grid_type), intent(in) :: grid !type(mct_aVect), intent(in) :: x2o_o real(kind=8), intent(in) :: x2o_o(:,:) From 31787c2b4fc2a80c5ad8e1960103e2b906018804 Mon Sep 17 00:00:00 2001 From: Gustavo Marques Date: Wed, 26 Jul 2017 11:11:59 -0600 Subject: [PATCH 28/38] Adds reference to set_time that was lost during a conflict handling --- config_src/mct_driver/ocn_comp_mct.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config_src/mct_driver/ocn_comp_mct.F90 b/config_src/mct_driver/ocn_comp_mct.F90 index 1e1132bc8c..0dce8f407e 100644 --- a/config_src/mct_driver/ocn_comp_mct.F90 +++ b/config_src/mct_driver/ocn_comp_mct.F90 @@ -32,7 +32,7 @@ module ocn_comp_mct use MOM_grid, only: ocean_grid_type, get_global_grid_size use MOM_variables, only: surface use MOM_error_handler, only: MOM_error, FATAL, is_root_pe -use MOM_time_manager, only: time_type, set_date, set_calendar_type, NOLEAP +use MOM_time_manager, only: time_type, set_date, set_time, set_calendar_type, NOLEAP use coupler_indices, only: coupler_indices_init, cpl_indices use coupler_indices, only: ocn_export, fill_ice_ocean_bnd From fccb7ae4e0cc678893d1d1a6cb08f799aead2a85 Mon Sep 17 00:00:00 2001 From: Alistair Adcroft Date: Tue, 25 Jul 2017 15:10:23 -0400 Subject: [PATCH 29/38] Avoids a SEGV when OBC are not in use with bi-harmonic friction - If OBC is not associated, the if expression could lead to a segmentation violation even when apply_OBC is false. - No answer changes. --- src/parameterizations/lateral/MOM_hor_visc.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/parameterizations/lateral/MOM_hor_visc.F90 b/src/parameterizations/lateral/MOM_hor_visc.F90 index 2ad88948d6..708e26babb 100644 --- a/src/parameterizations/lateral/MOM_hor_visc.F90 +++ b/src/parameterizations/lateral/MOM_hor_visc.F90 @@ -529,7 +529,7 @@ subroutine horizontal_viscosity(u, v, h, diffu, diffv, MEKE, VarMix, G, GV, CS, v0(i,J) = CS%IDXDY2v(i,J)*(CS%DY2q(I,J)*sh_xy(I,J) - CS%DY2q(I-1,J)*sh_xy(I-1,J)) - & CS%IDX2dyCv(i,J)*(CS%DX2h(i,j+1)*sh_xx(i,j+1) - CS%DX2h(i,j)*sh_xx(i,j)) enddo ; enddo - if (apply_OBC .and. OBC%zero_biharmonic) then + if (apply_OBC) then; if (OBC%zero_biharmonic) then do n=1,OBC%number_of_segments I = OBC%segment(n)%HI%IsdB ; J = OBC%segment(n)%HI%JsdB if (OBC%segment(n)%is_N_or_S .and. (J >= Jsq-1) .and. (J <= Jeq+1)) then @@ -542,7 +542,7 @@ subroutine horizontal_viscosity(u, v, h, diffu, diffv, MEKE, VarMix, G, GV, CS, enddo endif enddo - endif + endif; endif endif do j=Jsq,Jeq+1 ; do i=Isq,Ieq+1 From be46fee29445425ed471503e675c8ed1468eea24 Mon Sep 17 00:00:00 2001 From: Alistair Adcroft Date: Fri, 28 Jul 2017 00:49:53 -0400 Subject: [PATCH 30/38] (*)Fixes gprime(1) when no layer coordinates are set - The "none" option for COORD_CONFIG literally did nothing which meant that Rlay and gprime were unset (they actually appeared to be zero). This mode was added with the intent that the model should not need these coordinate variables in ALE mode. However, gprime(k=1) is used and should be set to GFS, which this commit now does. - I also added "ALE" as an option for COORD_CONFIG which is equivalent to "none" since "ALE" is bit more intuitive. - We might even use this as a master switch or check that COORD_CONFIG is consistent with USE_REGRIDDING (for later)? - This commit "appears" to changes answers but I don't think it does. What changes is the calculation of energy for some experiments in which Rlay was not set before this commit. A non-zero gprime(1) produces different APEs. Experiments affected are: - CVmix_SCM_tests/cooling_only/EPBL - CVmix_SCM_tests/cooling_only/KPP - CVmix_SCM_tests/mech_only/EPBL - CVmix_SCM_tests/mech_only/KPP - CVmix_SCM_tests/skin_warming_wind/EPBL - CVmix_SCM_tests/skin_warming_wind/KPP - CVmix_SCM_tests/wind_only/EPBL - CVmix_SCM_tests/wind_only/KPP - SCM_idealized_hurricane - single_column/EPBL - single_column/KPP - unit_tests All the above have COORD_CONFIG="none". --- .../MOM_coord_initialization.F90 | 37 ++++++++++++++++++- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/src/initialization/MOM_coord_initialization.F90 b/src/initialization/MOM_coord_initialization.F90 index f5acb96090..094e7617eb 100644 --- a/src/initialization/MOM_coord_initialization.F90 +++ b/src/initialization/MOM_coord_initialization.F90 @@ -58,6 +58,7 @@ subroutine MOM_initialize_coord(GV, PF, write_geom, output_dir, tv, max_depth) ! Set-up the layer densities, GV%Rlay, and reduced gravities, GV%g_prime. call get_param(PF, mod, "COORD_CONFIG", config, & "This specifies how layers are to be defined: \n"//& + " \t ALE or none - used to avoid defining layers in ALE mode \n"//& " \t file - read coordinate information from the file \n"//& " \t\t specified by (COORD_FILE).\n"//& " \t BFB - Custom coords for buoyancy-forced basin case \n"//& @@ -93,7 +94,8 @@ subroutine MOM_initialize_coord(GV, PF, write_geom, output_dir, tv, max_depth) call user_set_coord(GV%Rlay, GV%g_prime, GV, PF, eos) case ("BFB") call BFB_set_coord(GV%Rlay, GV%g_prime, GV, PF, eos) - case ("none") + case ("none", "ALE") + call set_coord_to_none(GV%Rlay, GV%g_prime, GV, PF) case default ; call MOM_error(FATAL,"MOM_initialize_coord: "// & "Unrecognized coordinate setup"//trim(config)) end select @@ -493,7 +495,38 @@ subroutine set_coord_linear(Rlay, g_prime, GV, param_file) call callTree_leave(trim(mod)//'()') end subroutine set_coord_linear -! ----------------------------------------------------------------------------- +!> Sets Rlay to Rho0 and g_prime to zero except for the free surface. +!! This is for use only in ALE mode where Rlay should not be used and g_prime(1) alone +!! might be used. +subroutine set_coord_to_none(Rlay, g_prime, GV, param_file) + real, dimension(:), intent(out) :: Rlay !< The layers' target coordinate values + !! (potential density). + real, dimension(:), intent(out) :: g_prime !< A structure indicating the open file to + !! parse for model parameter values. + type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure. + type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters + real :: g_fs ! Reduced gravity across the free surface, in m s-2. + character(len=40) :: mdl = "set_coord_to_none" ! This subroutine's name. + integer :: k, nz + nz = GV%ke + + call callTree_enter(trim(mdl)//"(), MOM_coord_initialization.F90") + + call get_param(param_file, mdl, "GFS" , g_fs, & + "The reduced gravity at the free surface.", units="m s-2", & + default=GV%g_Earth) + + g_prime(1) = g_fs + do k=2,nz ; g_prime(k) = 0. ; enddo + Rlay(1) = GV%Rho0 + do k=2,nz ; Rlay(k) = Rlay(k-1) + g_prime(k)*(GV%Rho0/GV%g_Earth) ; enddo + + call callTree_leave(trim(mdl)//'()') + +end subroutine set_coord_to_none + +!> This subroutine writes out a file containing any available data related +!! to the vertical grid used by the MOM ocean model. subroutine write_vertgrid_file(GV, param_file, directory) type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters From c04f08118ec63c590327e0da584988e2a2d3ab16 Mon Sep 17 00:00:00 2001 From: Gustavo Marques Date: Fri, 28 Jul 2017 11:15:04 -0600 Subject: [PATCH 31/38] Fix ssh slope calculation --- config_src/mct_driver/coupler_indices.F90 | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/config_src/mct_driver/coupler_indices.F90 b/config_src/mct_driver/coupler_indices.F90 index cd7d61bb33..3a43f5657c 100644 --- a/config_src/mct_driver/coupler_indices.F90 +++ b/config_src/mct_driver/coupler_indices.F90 @@ -244,10 +244,12 @@ subroutine ocn_export(ind, ocn_public, grid, o2x) do j=grid%jsc, grid%jec ; do i=grid%isc,grid%iec n = n+1 ! This is a simple second-order difference - ! o2x(ind%o2x_So_dhdx, n) = 0.5 * (ssh(i+1,j) + ssh(i-1,j)) * grid%IdxT(i,j) * grid%mask2dT(i,j) + ! o2x(ind%o2x_So_dhdx, n) = 0.5 * (ssh(i+1,j) + ssh(i-1,j)) * grid%IdxT(i,j) * grid%mask2dT(i,j) ! This is a PLM slope which might be less prone to the A-grid null mode - slp_L = ssh(i,j) - ssh(i-1,j) - slp_R = ssh(i+1,j) - ssh(i,j) + slp_L = (ssh(i,j) - ssh(i-1,j)) * grid%mask2dCu(I-1,j) + !if (grid%mask2dCu(I-1,j)==0.) slp_L = 0. + slp_R = (ssh(i+1,j) - ssh(i,j)) * grid%mask2dCu(I,j) + !if (grid%mask2dCu(I,j)==0.) slp_R = 0. slp_C = 0.5 * (slp_L + slp_R) if ( (slp_L * slp_R) > 0.0 ) then ! This limits the slope so that the edge values are bounded by the @@ -270,6 +272,8 @@ subroutine ocn_export(ind, ocn_public, grid, o2x) ! This is a PLM slope which might be less prone to the A-grid null mode slp_L = ssh(i,j) - ssh(i,j-1) slp_R = ssh(i,j+1) - ssh(i,j) +slp_L=0. +slp_R=0. slp_C = 0.5 * (slp_L + slp_R) if ( (slp_L * slp_R) > 0.0 ) then ! This limits the slope so that the edge values are bounded by the From fb89b08b6b4c908c24f7cdd4c014e9c0b8419bb8 Mon Sep 17 00:00:00 2001 From: Gustavo Marques Date: Tue, 1 Aug 2017 16:21:33 -0600 Subject: [PATCH 32/38] Adds code that got lost during merge Some code got that I added in MOM_state_initialization.F90 was lost during the merge with dev/master. This PR fixes that. * adds do_not_log=just_read * doxygenizes new variables * passes all MOM-examples/ocean_only tests on Cheyenne --- .../MOM_state_initialization.F90 | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/initialization/MOM_state_initialization.F90 b/src/initialization/MOM_state_initialization.F90 index 5d13bc79d1..3ecf43727e 100644 --- a/src/initialization/MOM_state_initialization.F90 +++ b/src/initialization/MOM_state_initialization.F90 @@ -1795,14 +1795,14 @@ subroutine MOM_temp_salt_initialize_from_Z(h, tv, G, GV, PF, just_read_params) logical, optional, intent(in) :: just_read_params !< If present and true, this call will !! only read parameters without changing h. - character(len=200) :: filename ! The name of an input file containing temperature - ! and salinity in z-space; also used for ice shelf area. - character(len=200) :: tfilename ! The name of an input file containing only temperature - ! in z-space. - character(len=200) :: sfilename ! The name of an input file containing only salinity - ! in z-space. - character(len=200) :: shelf_file ! The name of an input file used for ice shelf area. - character(len=200) :: inputdir ! The directory where NetCDF input filesare. + character(len=200) :: filename !< The name of an input file containing temperature + !! and salinity in z-space; also used for ice shelf area. + character(len=200) :: tfilename !< The name of an input file containing only temperature + !! in z-space. + character(len=200) :: sfilename !< The name of an input file containing only salinity + !! in z-space. + character(len=200) :: shelf_file !< The name of an input file used for ice shelf area. + character(len=200) :: inputdir !! The directory where NetCDF input filesare. character(len=200) :: mesg, area_varname, ice_shelf_file type(EOS_type), pointer :: eos => NULL() @@ -1898,22 +1898,22 @@ subroutine MOM_temp_salt_initialize_from_Z(h, tv, G, GV, PF, just_read_params) "The name of the z-space input file used to initialize \n"//& "temperatures (T) and salinities (S). If T and S are not \n" //& "in the same file, TEMP_Z_INIT_FILE and SALT_Z_INIT_FILE \n" //& - "must be set.",default="temp_salt_z.nc") + "must be set.",default="temp_salt_z.nc",do_not_log=just_read) call get_param(PF, mdl, "TEMP_Z_INIT_FILE",tfilename, & "The name of the z-space input file used to initialize \n"//& - "temperatures, only.", default=trim(filename)) + "temperatures, only.", default=trim(filename),do_not_log=just_read) call get_param(PF, mdl, "SALT_Z_INIT_FILE",sfilename, & "The name of the z-space input file used to initialize \n"//& - "temperatures, only.", default=trim(filename)) + "temperatures, only.", default=trim(filename),do_not_log=just_read) filename = trim(inputdir)//trim(filename) tfilename = trim(inputdir)//trim(tfilename) sfilename = trim(inputdir)//trim(sfilename) call get_param(PF, mdl, "Z_INIT_FILE_PTEMP_VAR", potemp_var, & "The name of the potential temperature variable in \n"//& - "TEMP_Z_INIT_FILE.", default="ptemp") + "TEMP_Z_INIT_FILE.", default="ptemp",do_not_log=just_read) call get_param(PF, mdl, "Z_INIT_FILE_SALT_VAR", salin_var, & "The name of the salinity variable in \n"//& - "SALT_Z_INIT_FILE.", default="salt") + "SALT_Z_INIT_FILE.", default="salt",do_not_log=just_read) call get_param(PF, mdl, "Z_INIT_HOMOGENIZE", homogenize, & "If True, then horizontally homogenize the interpolated \n"//& "initial conditions.", default=.false., do_not_log=just_read) From 06a30abc26d6cb0c74d2c27fd044d569cae5f41f Mon Sep 17 00:00:00 2001 From: alperaltuntas Date: Wed, 9 Aug 2017 18:37:51 -0600 Subject: [PATCH 33/38] Fixed clock and timing --- config_src/mct_driver/ocn_comp_mct.F90 | 62 ++++++++++++++++---------- 1 file changed, 39 insertions(+), 23 deletions(-) diff --git a/config_src/mct_driver/ocn_comp_mct.F90 b/config_src/mct_driver/ocn_comp_mct.F90 index 0dce8f407e..8cb06a841e 100644 --- a/config_src/mct_driver/ocn_comp_mct.F90 +++ b/config_src/mct_driver/ocn_comp_mct.F90 @@ -4,7 +4,7 @@ module ocn_comp_mct ! This file is part of MOM6. See LICENSE.md for the license. ! mct modules -use ESMF, only: ESMF_clock, ESMF_time, ESMF_timeInterval +use ESMF, only: ESMF_clock, ESMF_time, ESMF_timeInterval, ESMF_TimeInc use ESMF, only: ESMF_ClockGet, ESMF_TimeGet, ESMF_TimeIntervalGet use seq_cdata_mod, only: seq_cdata use seq_cdata_mod, only: seq_cdata_setptrs @@ -73,9 +73,10 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) ! local variables type(time_type) :: time_init !< Start time of coupled model's calendar - type(time_type) :: time_in !< Start time for ocean model at initialization + type(time_type) :: time_in !< Time at the beginning of the first ocn coupling interval type(ESMF_time) :: current_time !< Current time - type(ESMF_timeInterval) :: time_interval !< Time interval + type(ESMF_time) :: time_in_ESMF !< Time after first ocean coupling interval (of type ESMF_time) + type(ESMF_timeInterval) :: ocn_cpl_interval !< Ocean coupling interval integer :: year, month, day, hour, minute, seconds, seconds_n, seconds_d, rc character(len=384) :: runid !< Run ID character(len=384) :: runtype !< Run type @@ -95,8 +96,8 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) type(mct_gGrid) :: MOM_MCT_dom3d !< for 3d streams, local ! time management - integer :: ocn_cpl_dt - real (kind=8) :: mom_cpl_dt + integer :: ocn_cpl_dt !< one ocn coupling interval in seconds. (to be received from cesm) + real (kind=8) :: mom_cpl_dt !< one ocn coupling interval in seconds. (internal) real (kind=8), parameter :: & seconds_in_minute = 60.0d0, & seconds_in_hour = 3600.0d0, & @@ -113,7 +114,7 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) integer :: km=1 !< Number of vertical levels integer :: nx_block=0, ny_block=0 !< Size of block domain in x,y dir including ghost cells integer :: max_blocks_clinic=0 !< Max. number of blocks per processor in each distribution - integer :: ncouple_per_day = 48 + integer :: ncouple_per_day logical :: lsend_precip_fact !< If T,send precip_fact to cpl for use in fw balance !! (partially-coupled option) character(len=128) :: err_msg !< Error message @@ -145,14 +146,26 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) inst_index = seq_comm_inst(MOM_MCT_ID) inst_suffix = seq_comm_suffix(MOM_MCT_ID) - ! Initialize MOM6 call t_startf('MOM_init') + + ! Initialize MOM6 comm call MOM_infra_init(mpicom_ocn) - call ESMF_ClockGet(EClock, currTime=current_time, rc=rc) - call ESMF_TimeGet(current_time, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc) + call set_calendar_type(NOLEAP) !TODO: confirm this + ! Get the ESMF clock instance (assigned by CESM for MOM6) + call ESMF_ClockGet(EClock, currTime=current_time, rc=rc) + + ! Get the initial CESM time + call ESMF_TimeGet(current_time, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc) time_init = set_date(year, month, day, hour, minute, seconds, err_msg=err_msg) + + ! Compute time_in: time at the beginning of the first ocn coupling interval + ! (In CESM, ocean component is lagged by one ocean coupling interval, so: + ! time_in = time_init + ocn_cpl_interval ) + call ESMF_ClockGet(EClock, TimeStep=ocn_cpl_interval, rc=rc) + time_in_ESMF = ESMF_TimeInc(current_time, ocn_cpl_interval) + call ESMF_TimeGet(time_in_ESMF, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc) time_in = set_date(year, month, day, hour, minute, seconds, err_msg=err_msg) ! Debugging clocks @@ -167,8 +180,8 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) call ESMF_ClockGet(EClock, PrevTime=current_time, rc=rc) call ESMF_TimeGet(current_time, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc) write(6,*) 'ocn_init_mct, previous time: y,m,d-',year,month,day,'h,m,s=',hour,minute,seconds - call ESMF_ClockGet(EClock, TimeStep=time_interval, rc=rc) - call ESMF_TimeIntervalGet(time_interval, yy=year, mm=month, d=day, s=seconds, sn=seconds_n, sd=seconds_d, rc=rc) + call ESMF_ClockGet(EClock, TimeStep=ocn_cpl_interval, rc=rc) + call ESMF_TimeIntervalGet(ocn_cpl_interval, yy=year, mm=month, d=day, s=seconds, sn=seconds_n, sd=seconds_d, rc=rc) write(6,*) 'ocn_init_mct, time step: y,m,d-',year,month,day,'s,sn,sd=',seconds,seconds_n,seconds_d endif @@ -235,8 +248,9 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) call seq_timemgr_EClockGetData(EClock, dtime=ocn_cpl_dt) ! \todo Need interface to get dt from MOM6 + ncouple_per_day = seconds_in_day / ocn_cpl_dt mom_cpl_dt = seconds_in_day / ncouple_per_day - if (mom_cpl_dt /= ocn_cpl_dt) then + if (mom_cpl_dt /= ocn_cpl_dt) then ! \todo this check is trivial for now. write(*,*) 'ERROR pop_cpl_dt and ocn_cpl_dt must be identical' call exit(0) end if @@ -303,21 +317,24 @@ subroutine ocn_run_mct( EClock, cdata_o, x2o_o, o2x_o) type(mct_aVect), intent(inout) :: x2o_o !< Fluxes from coupler to ocean, computed by ocean type(mct_aVect), intent(inout) :: o2x_o !< Fluxes from ocean to coupler, computed by ocean ! Local variables - type(ESMF_time) :: current_time - type(ESMF_timeInterval) :: time_interval + type(ESMF_time) :: current_time !< Time to be reached at the end of ocean cpl interval + type(ESMF_time) :: time_start_ESMF !< Time at the start of the coupling interval + type(ESMF_timeInterval) :: ocn_cpl_interval !< The length of one ocean coupling interval integer :: year, month, day, hour, minute, seconds, seconds_n, seconds_d, rc logical :: write_restart_at_eod type(time_type) :: time_start !< Start of coupled time interval to pass to MOM6 type(time_type) :: coupling_timestep !< Coupled time interval to pass to MOM6 character(len=128) :: err_msg - ! Translate the current time (start of coupling interval) - call ESMF_ClockGet(EClock, currTime=current_time, rc=rc) - call ESMF_TimeGet(current_time, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc) + ! Compute the time at the start of this coupling interval + call ESMF_ClockGet(EClock, PrevTime=time_start_ESMF, rc=rc) + call ESMF_TimeGet(time_start_ESMF, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc) time_start = set_date(year, month, day, hour, minute, seconds, err_msg=err_msg) ! Debugging clocks if (debug .and. is_root_pe()) then + call ESMF_ClockGet(EClock, CurrTime=current_time, rc=rc) + call ESMF_TimeGet(current_time, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc) write(6,*) 'ocn_run_mct, current time: y,m,d-',year,month,day,'h,m,s=',hour,minute,seconds call ESMF_ClockGet(EClock, StartTime=current_time, rc=rc) call ESMF_TimeGet(current_time, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc) @@ -328,15 +345,14 @@ subroutine ocn_run_mct( EClock, cdata_o, x2o_o, o2x_o) call ESMF_ClockGet(EClock, PrevTime=current_time, rc=rc) call ESMF_TimeGet(current_time, yy=year, mm=month, dd=day, h=hour, m=minute, s=seconds, rc=rc) write(6,*) 'ocn_run_mct, previous time: y,m,d-',year,month,day,'h,m,s=',hour,minute,seconds + call ESMF_ClockGet(EClock, TimeStep=ocn_cpl_interval, rc=rc) + call ESMF_TimeIntervalGet(ocn_cpl_interval, yy=year, mm=month, d=day, s=seconds, sn=seconds_n, sd=seconds_d, rc=rc) + write(6,*) 'ocn_init_mct, time step: y,m,d-',year,month,day,'s,sn,sd=',seconds,seconds_n,seconds_d endif ! Translate the coupling time interval - call ESMF_ClockGet(EClock, TimeStep=time_interval, rc=rc) - call ESMF_TimeIntervalGet(time_interval, yy=year, mm=month, d=day, s=seconds, sn=seconds_n, sd=seconds_d, rc=rc) - time_start = set_date(year, month, day, 0, 0, seconds, err_msg=err_msg) - if (debug .and. is_root_pe()) then - write(6,*) 'ocn_run_mct, time step: y,m,d-',year,month,day,'s,sn,sd=',seconds,seconds_n,seconds_d - endif + call ESMF_ClockGet(EClock, TimeStep=ocn_cpl_interval, rc=rc) + call ESMF_TimeIntervalGet(ocn_cpl_interval, yy=year, mm=month, d=day, s=seconds, sn=seconds_n, sd=seconds_d, rc=rc) coupling_timestep = set_time(seconds, days=day, err_msg=err_msg) ! set (actually, get from mct) the cdata pointers: From 58f78b9db22f0dd02338cc5de8998070e58027b0 Mon Sep 17 00:00:00 2001 From: Gustavo Marques Date: Thu, 10 Aug 2017 08:47:26 -0600 Subject: [PATCH 34/38] Fill IOB, some fluxes still need to be checked --- config_src/mct_driver/coupler_indices.F90 | 95 +++++++++++++---------- 1 file changed, 53 insertions(+), 42 deletions(-) diff --git a/config_src/mct_driver/coupler_indices.F90 b/config_src/mct_driver/coupler_indices.F90 index 3a43f5657c..06a6040307 100644 --- a/config_src/mct_driver/coupler_indices.F90 +++ b/config_src/mct_driver/coupler_indices.F90 @@ -1,19 +1,19 @@ module coupler_indices ! MCT types - use mct_mod, only : mct_aVect + use mct_mod, only : mct_aVect ! MCT fucntions - use mct_mod, only : mct_avect_indexra, mct_aVect_init, mct_aVect_clean - use seq_flds_mod, only : seq_flds_x2o_fields, seq_flds_o2x_fields - use seq_flds_mod, only : seq_flds_i2o_per_cat, ice_ncat + use mct_mod, only : mct_avect_indexra, mct_aVect_init, mct_aVect_clean + use seq_flds_mod, only : seq_flds_x2o_fields, seq_flds_o2x_fields + use seq_flds_mod, only : seq_flds_i2o_per_cat, ice_ncat ! MOM types - use MOM_grid, only : ocean_grid_type + use MOM_grid, only : ocean_grid_type use MOM_surface_forcing, only: ice_ocean_boundary_type ! MOM functions - use MOM_domains, only : pass_var, AGRID - use ocean_model_mod, only : ocean_public_type - + use MOM_domains, only : pass_var, AGRID + use ocean_model_mod, only : ocean_public_type + use MOM_error_handler, only : MOM_error, FATAL implicit none private @@ -116,6 +116,7 @@ subroutine coupler_indices_init(ind) call mct_aVect_init(x2o, rList=seq_flds_x2o_fields, lsize=1) call mct_aVect_init(o2x, rList=seq_flds_o2x_fields, lsize=1) + ! ocean to coupler ind%o2x_So_t = mct_avect_indexra(o2x,'So_t') ind%o2x_So_u = mct_avect_indexra(o2x,'So_u') ind%o2x_So_v = mct_avect_indexra(o2x,'So_v') @@ -127,6 +128,8 @@ subroutine coupler_indices_init(ind) ind%o2x_Fioo_q = mct_avect_indexra(o2x,'Fioo_q') ind%o2x_Faoo_fco2_ocn = mct_avect_indexra(o2x,'Faoo_fco2_ocn',perrWith='quiet') ind%o2x_Faoo_fdms_ocn = mct_avect_indexra(o2x,'Faoo_fdms_ocn',perrWith='quiet') + + ! coupler to ocean ind%x2o_Si_ifrac = mct_avect_indexra(x2o,'Si_ifrac') ind%x2o_Sa_pslv = mct_avect_indexra(x2o,'Sa_pslv') ind%x2o_So_duu10n = mct_avect_indexra(x2o,'So_duu10n') @@ -134,7 +137,6 @@ subroutine coupler_indices_init(ind) ind%x2o_Sw_lamult = mct_avect_indexra(x2o,'Sw_lamult') ind%x2o_Sw_ustokes = mct_avect_indexra(x2o,'Sw_ustokes') ind%x2o_Sw_vstokes = mct_avect_indexra(x2o,'Sw_vstokes') - ind%x2o_Foxx_tauy = mct_avect_indexra(x2o,'Foxx_tauy') ind%x2o_Foxx_taux = mct_avect_indexra(x2o,'Foxx_taux') ind%x2o_Foxx_swnet = mct_avect_indexra(x2o,'Foxx_swnet') @@ -226,7 +228,8 @@ subroutine ocn_export(ind, ocn_public, grid, o2x) do i=grid%isc,grid%iec n = n+1 ig = i + grid%idg_offset - o2x(ind%o2x_So_t, n) = ocn_public%t_surf(ig,jg) * grid%mask2dT(i,j) + ! surface temperature in Kelvin + o2x(ind%o2x_So_t, n) = ocn_public%t_surf(ig,jg) * grid%mask2dT(i,j) o2x(ind%o2x_So_s, n) = ocn_public%s_surf(ig,jg) * grid%mask2dT(i,j) o2x(ind%o2x_So_u, n) = ocn_public%u_surf(ig,jg) * grid%mask2dT(i,j) o2x(ind%o2x_So_v, n) = ocn_public%v_surf(ig,jg) * grid%mask2dT(i,j) @@ -292,15 +295,18 @@ subroutine ocn_export(ind, ocn_public, grid, o2x) end subroutine ocn_export - subroutine fill_ice_ocean_bnd(ice_ocean_boundary, grid, x2o_o, ind) - type(ice_ocean_boundary_type), intent(inout) :: ice_ocean_boundary !< A type for the ice ocean boundary - type(ocean_grid_type), intent(in) :: grid - !type(mct_aVect), intent(in) :: x2o_o - real(kind=8), intent(in) :: x2o_o(:,:) - type(cpl_indices), intent(inout) :: ind + subroutine fill_ice_ocean_bnd(ice_ocean_boundary, grid, x2o_o, ind, sw_decomp, c1, c2, c3, c4) + type(ice_ocean_boundary_type), intent(inout) :: ice_ocean_boundary !< A type for the ice ocean boundary + type(ocean_grid_type), intent(in) :: grid + !type(mct_aVect), intent(in) :: x2o_o + real(kind=8), intent(in) :: x2o_o(:,:) + type(cpl_indices), intent(inout) :: ind + logical, intent(in) :: sw_decomp !< controls if shortwave is decomposed + !! into four components + real(kind=8), intent(in), optional :: c1, c2, c3, c4 !< Coeffs. used in the shortwave decomposition ! local variables - integer :: i, j, k, ig, jg + integer :: i, j, k, ig, jg !< grid indices ! variable that are not in ice_ocean_boundary: ! latent (x2o_Foxx_lat) @@ -324,11 +330,6 @@ subroutine fill_ice_ocean_bnd(ice_ocean_boundary, grid, x2o_o, ind) ! need wind_stress_multiplier? - ! Copy from x2o to ice_ocean_boundary. ice_ocean_boundary uses global indexing with no halos. - write(*,*) 'max. k is:', (grid%jec-grid%jsc+1) * (grid%iec-grid%isc+1) - ! zonal wind stress (taux) - write(*,*) 'taux', SIZE(x2o_o(ind%x2o_Foxx_taux,:)) - write(*,*) 'ice_ocean_boundary%u_flux', SIZE(ice_ocean_boundary%u_flux(:,:)) k = 0 do j = grid%jsc, grid%jec jg = j + grid%jdg_offset @@ -336,33 +337,43 @@ subroutine fill_ice_ocean_bnd(ice_ocean_boundary, grid, x2o_o, ind) k = k + 1 ! Increment position within gindex ig = i + grid%idg_offset ! zonal wind stress (taux) - ice_ocean_boundary%u_flux(ig,jg) = 0.0 ! x20_o(ind%x2o_Foxx_taux,k) + ice_ocean_boundary%u_flux(ig,jg) = x2o_o(ind%x2o_Foxx_taux,k) ! meridional wind stress (tauy) - ice_ocean_boundary%v_flux(ig,jg) = 0.0 ! x20_o(ind%x2o_Foxx_tauy,k) - ! sensible heat flux - ice_ocean_boundary%t_flux(ig,jg) = 0.0 ! x20_o(ind%x2o_Foxx_sen,k) + ice_ocean_boundary%v_flux(ig,jg) = x2o_o(ind%x2o_Foxx_tauy,k) + ! sensible heat flux (W/m2) + ice_ocean_boundary%t_flux(ig,jg) = -x2o_o(ind%x2o_Foxx_sen,k) ! salt flux - ice_ocean_boundary%salt_flux(ig,jg) = 0.0 ! x20_o(ind%x2o_Fioi_salt,k) + ice_ocean_boundary%salt_flux(ig,jg) = x2o_o(ind%x2o_Fioi_salt,k) ! heat flux from snow & ice melt - ice_ocean_boundary%calving_hflx(ig,jg) = 0.0 ! x20_o(ind%x2o_Fioi_melth,k) + ice_ocean_boundary%calving_hflx(ig,jg) = x2o_o(ind%x2o_Fioi_melth,k) ! snow melt flux - ice_ocean_boundary%fprec(ig,jg) = 0.0 ! x20_o(ind%x2o_Fioi_meltw,k) + !ice_ocean_boundary%fprec(ig,jg) = x2o_o(ind%x2o_Fioi_meltw,k) ! river runoff flux - ice_ocean_boundary%runoff(ig,jg) = 0.0 ! x20_o(ind%x2o_Foxx_rofl,k) + ice_ocean_boundary%runoff(ig,jg) = x2o_o(ind%x2o_Foxx_rofl,k) ! ice runoff flux - ice_ocean_boundary%calving(ig,jg) = 0.0 ! x20_o(ind%x2o_Foxx_rofi,k) + ice_ocean_boundary%calving(ig,jg) = x2o_o(ind%x2o_Foxx_rofi,k) ! liquid precipitation (rain) - ice_ocean_boundary%lprec(ig,jg) = 0.0 ! x20_o(ind%x2o_Faxa_rain,k) - ! froze precipitation (snow) - ice_ocean_boundary%fprec(ig,jg) = 0.0 ! x20_o(ind%x2o_Faxa_snow,k) - !!!!!!! LONGWAVE NEEDS TO BE FIXED !!!!!!! - ! longwave radiation (up) - ice_ocean_boundary%lw_flux(ig,jg) = 0.0 ! x20_o(k,ind%x2o_Foxx_lwup) - ! longwave radiation (down) - ice_ocean_boundary%lw_flux(ig,jg) = 0.0 ! x20_o(k,ind%x2o_Faxa_lwdn) - !!!!!!! SHORTWAVE NEEDS TO BE COMBINED !!!!!!! - ! net short-wave heat flux - ice_ocean_boundary%u_flux(ig,jg) = 0.0 ! x20_o(k,ind%x2o_Foxx_swnet) + ice_ocean_boundary%lprec(ig,jg) = x2o_o(ind%x2o_Faxa_rain,k) + ! frozen precipitation (snow) + ice_ocean_boundary%fprec(ig,jg) = x2o_o(ind%x2o_Faxa_snow,k) + ! evaporation flux (kg/m2/s) + ice_ocean_boundary%q_flux(ig,jg) = -x2o_o(ind%x2o_Foxx_evap,k) + ! longwave radiation, sum up and down (W/m2) + ice_ocean_boundary%lw_flux(ig,jg) = x2o_o(ind%x2o_Faxa_lwdn,k) + x2o_o(ind%x2o_Foxx_lwup,k) + if (sw_decomp) then + ! Use runtime coefficients to decompose net short-wave heat flux into 4 components + ! 1) visible, direct shortwave (W/m2) + ice_ocean_boundary%sw_flux_vis_dir(ig,jg) = x2o_o(ind%x2o_Foxx_swnet,k)*c1 + ! 2) visible, diffuse shortwave (W/m2) + ice_ocean_boundary%sw_flux_vis_dif(ig,jg) = x2o_o(ind%x2o_Foxx_swnet,k)*c2 + ! 3) near-IR, direct shortwave (W/m2) + ice_ocean_boundary%sw_flux_nir_dir(ig,jg) = x2o_o(ind%x2o_Foxx_swnet,k)*c3 + ! 4) near-IR, diffuse shortwave (W/m2) + ice_ocean_boundary%sw_flux_nir_dif(ig,jg) = x2o_o(ind%x2o_Foxx_swnet,k)*c4 + else + call MOM_error(FATAL,"fill_ice_ocean_bnd: this option has not been implemented yet."// & + "Shortwave must be decomposed using coeffs. c1, c2, c3, c4."); + endif enddo enddo From 2582e0a9d7ac40efaba60488ffe4bc5699b78513 Mon Sep 17 00:00:00 2001 From: Gustavo Marques Date: Thu, 10 Aug 2017 08:48:43 -0600 Subject: [PATCH 35/38] Adds run paramaters to control SW decomposition --- config_src/mct_driver/ocn_comp_mct.F90 | 46 +++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/config_src/mct_driver/ocn_comp_mct.F90 b/config_src/mct_driver/ocn_comp_mct.F90 index 0dce8f407e..149f1206d7 100644 --- a/config_src/mct_driver/ocn_comp_mct.F90 +++ b/config_src/mct_driver/ocn_comp_mct.F90 @@ -33,6 +33,8 @@ module ocn_comp_mct use MOM_variables, only: surface use MOM_error_handler, only: MOM_error, FATAL, is_root_pe use MOM_time_manager, only: time_type, set_date, set_time, set_calendar_type, NOLEAP +use MOM_file_parser, only: get_param, log_version, param_file_type +use MOM_get_input, only: Get_MOM_Input, directories use coupler_indices, only: coupler_indices_init, cpl_indices use coupler_indices, only: ocn_export, fill_ice_ocean_bnd @@ -54,8 +56,10 @@ module ocn_comp_mct type(surface), pointer :: ocn_surface => NULL() !< The ocean surface state type(ice_ocean_boundary_type) :: ice_ocean_boundary !< The ice ocean boundary type type(seq_infodata_type), pointer :: infodata !< The input info type - type(cpl_indices), public :: ind !< Variable IDs - + type(cpl_indices), public :: ind !< Variable IDs + ! runtime params + logical :: sw_decomp !< Controls whether shortwave is decomposed into four components + real :: c1, c2, c3, c4 !< Coeffs. used in the shortwave decomposition end type MCT_MOM_Data type(MCT_MOM_Data) :: glb !< global structure @@ -87,6 +91,11 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) logical :: ldiag_cpl = .false. integer :: isc, iec, jsc, jec, ni, nj !< Indices for the start and end of the domain !! in the x and y dir., respectively. + ! runi-time params + type(param_file_type) :: param_file !< A structure to parse for run-time parameters + type(directories) :: dirs_tmp !< A structure containing several relevant directory paths + character(len=40) :: mdl = "ocn_comp_mct" !< This module's name. + ! mct variables (these are local for now) integer :: MOM_MCT_ID type(mct_gsMap), pointer :: MOM_MCT_gsMap => NULL() !< 2d, points to cdata @@ -181,6 +190,34 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) glb%ocn_public%pelist(:) = (/(i,i=pe0,pe0+npes)/) ! \todo Set other bits of glb$ocn_public + ! This include declares and sets the variable "version". + ! read useful runtime params + call get_MOM_Input(param_file, dirs_tmp, check_params=.false.) + !call log_version(param_file, mdl, version, "") + call get_param(param_file, mdl, "SW_DECOMP", glb%sw_decomp, & + "If True, read coeffs c1, c2, c3 and c4 and decompose" // & + "the net shortwave radiation (SW) into four components:\n" // & + "visible, direct shortwave = c1 * SW \n" // & + "visible, diffuse shortwave = c2 * SW \n" // & + "near-IR, direct shortwave = c3 * SW \n" // & + "near-IR, diffuse shortwave = c4 * SW", default=.true.) + if (glb%sw_decomp) then + call get_param(param_file, mdl, "SW_c1", glb%c1, & + "Coeff. used to convert net shortwave rad. into \n"//& + "visible, direct shortwave.", units="nondim", default=0.285) + call get_param(param_file, mdl, "SW_c2", glb%c2, & + "Coeff. used to convert net shortwave rad. into \n"//& + "visible, diffuse shortwave.", units="nondim", default=0.285) + call get_param(param_file, mdl, "SW_c3", glb%c3, & + "Coeff. used to convert net shortwave rad. into \n"//& + "near-IR, direct shortwave.", units="nondim", default=0.215) + call get_param(param_file, mdl, "SW_c4", glb%c4, & + "Coeff. used to convert net shortwave rad. into \n"//& + "near-IR, diffuse shortwave.", units="nondim", default=0.215) + else + glb%c1 = 0.0; glb%c2 = 0.0; glb%c3 = 0.0; glb%c4 = 0.0 + endif + ! Initialize the MOM6 model call ocean_model_init(glb%ocn_public, glb%ocn_state, time_init, time_in) @@ -237,7 +274,7 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) ! \todo Need interface to get dt from MOM6 mom_cpl_dt = seconds_in_day / ncouple_per_day if (mom_cpl_dt /= ocn_cpl_dt) then - write(*,*) 'ERROR pop_cpl_dt and ocn_cpl_dt must be identical' + write(*,*) 'ERROR mom_cpl_dt and ocn_cpl_dt must be identical' call exit(0) end if @@ -349,7 +386,8 @@ subroutine ocn_run_mct( EClock, cdata_o, x2o_o, o2x_o) if (debug .and. is_root_pe()) write(6,*) 'ocn_run_mct, write_restart_at_eod=', write_restart_at_eod ! fill ice ocean boundary - call fill_ice_ocean_bnd(glb%ice_ocean_boundary, glb%grid, x2o_o%rattr, glb%ind) + call fill_ice_ocean_bnd(glb%ice_ocean_boundary, glb%grid, x2o_o%rattr, glb%ind, glb%sw_decomp, & + glb%c1, glb%c2, glb%c3, glb%c4) if (debug .and. is_root_pe()) write(6,*) 'fill_ice_ocean_bnd' call update_ocean_model(glb%ice_ocean_boundary, glb%ocn_state, glb%ocn_public, & From 8745b4ba570b68fa5e448659ff948c26a8c6289a Mon Sep 17 00:00:00 2001 From: Gustavo Marques Date: Fri, 11 Aug 2017 14:50:51 -0600 Subject: [PATCH 36/38] Fills additional IOB fluxes --- config_src/mct_driver/coupler_indices.F90 | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/config_src/mct_driver/coupler_indices.F90 b/config_src/mct_driver/coupler_indices.F90 index 06a6040307..6edacac516 100644 --- a/config_src/mct_driver/coupler_indices.F90 +++ b/config_src/mct_driver/coupler_indices.F90 @@ -52,8 +52,8 @@ module coupler_indices integer :: x2o_Foxx_taux ! zonal wind stress (taux) (W/m2 ) integer :: x2o_Foxx_tauy ! meridonal wind stress (tauy) (W/m2 ) integer :: x2o_Foxx_swnet ! net short-wave heat flux (W/m2 ) - integer :: x2o_Foxx_sen ! sensible heat flux (W/m2 ) - integer :: x2o_Foxx_lat + integer :: x2o_Foxx_sen ! sensible heat flux (W/m2) + integer :: x2o_Foxx_lat ! latent heat flux (W/m2) integer :: x2o_Foxx_lwup ! longwave radiation (up) (W/m2 ) integer :: x2o_Faxa_lwdn ! longwave radiation (down) (W/m2 ) integer :: x2o_Fioi_melth ! heat flux from snow & ice melt (W/m2 ) @@ -336,6 +336,8 @@ subroutine fill_ice_ocean_bnd(ice_ocean_boundary, grid, x2o_o, ind, sw_decomp, c do i = grid%isc, grid%iec k = k + 1 ! Increment position within gindex ig = i + grid%idg_offset + ! sea-level pressure (Pa) + ice_ocean_boundary%p(ig,jg) = x2o_o(ind%x2o_Sa_pslv,k) ! zonal wind stress (taux) ice_ocean_boundary%u_flux(ig,jg) = x2o_o(ind%x2o_Foxx_taux,k) ! meridional wind stress (tauy) @@ -343,9 +345,9 @@ subroutine fill_ice_ocean_bnd(ice_ocean_boundary, grid, x2o_o, ind, sw_decomp, c ! sensible heat flux (W/m2) ice_ocean_boundary%t_flux(ig,jg) = -x2o_o(ind%x2o_Foxx_sen,k) ! salt flux - ice_ocean_boundary%salt_flux(ig,jg) = x2o_o(ind%x2o_Fioi_salt,k) - ! heat flux from snow & ice melt - ice_ocean_boundary%calving_hflx(ig,jg) = x2o_o(ind%x2o_Fioi_melth,k) + ice_ocean_boundary%salt_flux(ig,jg) = -x2o_o(ind%x2o_Fioi_salt,k) + ! heat content from frozen runoff + ice_ocean_boundary%calving_hflx(ig,jg) = 0.0 ! snow melt flux !ice_ocean_boundary%fprec(ig,jg) = x2o_o(ind%x2o_Fioi_meltw,k) ! river runoff flux @@ -356,7 +358,7 @@ subroutine fill_ice_ocean_bnd(ice_ocean_boundary, grid, x2o_o, ind, sw_decomp, c ice_ocean_boundary%lprec(ig,jg) = x2o_o(ind%x2o_Faxa_rain,k) ! frozen precipitation (snow) ice_ocean_boundary%fprec(ig,jg) = x2o_o(ind%x2o_Faxa_snow,k) - ! evaporation flux (kg/m2/s) + ! evaporation flux, MOM6 calls q_flux specific humidity (kg/m2/s) ice_ocean_boundary%q_flux(ig,jg) = -x2o_o(ind%x2o_Foxx_evap,k) ! longwave radiation, sum up and down (W/m2) ice_ocean_boundary%lw_flux(ig,jg) = x2o_o(ind%x2o_Faxa_lwdn,k) + x2o_o(ind%x2o_Foxx_lwup,k) From f5a8483584e07052c804314e6d96575046554393 Mon Sep 17 00:00:00 2001 From: Gustavo Marques Date: Fri, 11 Aug 2017 16:27:51 -0600 Subject: [PATCH 37/38] Adds option to write restart files --- config_src/mct_driver/ocn_comp_mct.F90 | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/config_src/mct_driver/ocn_comp_mct.F90 b/config_src/mct_driver/ocn_comp_mct.F90 index d639329bd3..d152e34998 100644 --- a/config_src/mct_driver/ocn_comp_mct.F90 +++ b/config_src/mct_driver/ocn_comp_mct.F90 @@ -26,7 +26,7 @@ module ocn_comp_mct ! MOM6 modules use ocean_model_mod, only: ocean_state_type, ocean_public_type, ocean_model_init_sfc -use ocean_model_mod, only: ocean_model_init, get_state_pointers +use ocean_model_mod, only: ocean_model_init, get_state_pointers, ocean_model_restart use ocean_model_mod, only: ice_ocean_boundary_type, update_ocean_model use MOM_domains, only: MOM_infra_init, num_pes, root_pe, pe_here use MOM_grid, only: ocean_grid_type, get_global_grid_size @@ -38,7 +38,6 @@ module ocn_comp_mct use coupler_indices, only: coupler_indices_init, cpl_indices use coupler_indices, only: ocn_export, fill_ice_ocean_bnd - ! By default make data private implicit none; private ! Public member functions @@ -362,6 +361,7 @@ subroutine ocn_run_mct( EClock, cdata_o, x2o_o, o2x_o) type(time_type) :: time_start !< Start of coupled time interval to pass to MOM6 type(time_type) :: coupling_timestep !< Coupled time interval to pass to MOM6 character(len=128) :: err_msg + character(len=32) :: timestamp !< Name of intermediate restart file ! Compute the time at the start of this coupling interval call ESMF_ClockGet(EClock, PrevTime=time_start_ESMF, rc=rc) @@ -388,7 +388,7 @@ subroutine ocn_run_mct( EClock, cdata_o, x2o_o, o2x_o) endif ! Translate the coupling time interval - call ESMF_ClockGet(EClock, TimeStep=ocn_cpl_interval, rc=rc) + call ESMF_ClockGet(EClock, TimeStep=ocn_cpl_interval, rc=rc) call ESMF_TimeIntervalGet(ocn_cpl_interval, yy=year, mm=month, d=day, s=seconds, sn=seconds_n, sd=seconds_d, rc=rc) coupling_timestep = set_time(seconds, days=day, err_msg=err_msg) @@ -396,11 +396,6 @@ subroutine ocn_run_mct( EClock, cdata_o, x2o_o, o2x_o) ! \todo this was done in _init_, is it needed again. Does this infodata need to be in glb%? call seq_cdata_setptrs(cdata_o, infodata=glb%infodata) - ! Check alarms for flag to write restart at end of day - write_restart_at_eod = seq_timemgr_RestartAlarmIsOn(EClock) - ! \todo Let MOM6 know to write restart... - if (debug .and. is_root_pe()) write(6,*) 'ocn_run_mct, write_restart_at_eod=', write_restart_at_eod - ! fill ice ocean boundary call fill_ice_ocean_bnd(glb%ice_ocean_boundary, glb%grid, x2o_o%rattr, glb%ind, glb%sw_decomp, & glb%c1, glb%c2, glb%c3, glb%c4) @@ -409,6 +404,18 @@ subroutine ocn_run_mct( EClock, cdata_o, x2o_o, o2x_o) call update_ocean_model(glb%ice_ocean_boundary, glb%ocn_state, glb%ocn_public, & time_start, coupling_timestep) + !--- write out intermediate restart file when needed. + ! Check alarms for flag to write restart at end of day + write_restart_at_eod = seq_timemgr_RestartAlarmIsOn(EClock) + if (debug .and. is_root_pe()) write(6,*) 'ocn_run_mct, write_restart_at_eod=', write_restart_at_eod + + if (write_restart_at_eod) then + !timestamp = date_to_string(EClock) + ! \todo add time stamp to ocean_model_restart + !call ocean_model_restart(glb%ocn_state, timestamp) + call ocean_model_restart(glb%ocn_state) + endif + end subroutine ocn_run_mct !> Finalizes MOM6 From a85b7282e0ee10bf6cb2bea9858e361624bc3efb Mon Sep 17 00:00:00 2001 From: Gustavo Marques Date: Tue, 15 Aug 2017 11:48:10 -0600 Subject: [PATCH 38/38] Merge MCT modules --- config_src/mct_driver/coupler_indices.F90 | 386 ------------------- config_src/mct_driver/ocn_comp_mct.F90 | 394 +++++++++++++++++++- config_src/mct_driver/ocn_import_export.F90 | 141 ------- 3 files changed, 389 insertions(+), 532 deletions(-) delete mode 100644 config_src/mct_driver/coupler_indices.F90 delete mode 100644 config_src/mct_driver/ocn_import_export.F90 diff --git a/config_src/mct_driver/coupler_indices.F90 b/config_src/mct_driver/coupler_indices.F90 deleted file mode 100644 index 6edacac516..0000000000 --- a/config_src/mct_driver/coupler_indices.F90 +++ /dev/null @@ -1,386 +0,0 @@ -module coupler_indices - - ! MCT types - use mct_mod, only : mct_aVect - ! MCT fucntions - use mct_mod, only : mct_avect_indexra, mct_aVect_init, mct_aVect_clean - use seq_flds_mod, only : seq_flds_x2o_fields, seq_flds_o2x_fields - use seq_flds_mod, only : seq_flds_i2o_per_cat, ice_ncat - - ! MOM types - use MOM_grid, only : ocean_grid_type - use MOM_surface_forcing, only: ice_ocean_boundary_type - ! MOM functions - use MOM_domains, only : pass_var, AGRID - use ocean_model_mod, only : ocean_public_type - use MOM_error_handler, only : MOM_error, FATAL - implicit none - - private - - public coupler_indices_init - public fill_ice_ocean_bnd - public ocn_export - - type, public :: cpl_indices - - ! ocn -> drv - - integer :: o2x_So_t - integer :: o2x_So_u - integer :: o2x_So_v - integer :: o2x_So_s - integer :: o2x_So_dhdx - integer :: o2x_So_dhdy - ! QL, 150526, to wav, boundary layer depth - integer :: o2x_So_bldepth - integer :: o2x_Fioo_q - integer :: o2x_Faoo_fco2_ocn - integer :: o2x_Faoo_fdms_ocn - - ! drv -> ocn - - integer :: x2o_Si_ifrac ! fractional ice wrt ocean - integer :: x2o_So_duu10n ! 10m wind speed squared (m^2/s^2) - integer :: x2o_Sa_pslv ! sea-level pressure (Pa) - integer :: x2o_Sa_co2prog ! bottom atm level prognostic CO2 - integer :: x2o_Sa_co2diag ! bottom atm level diagnostic CO2 - ! QL, 150526, from wav - integer :: x2o_Sw_lamult ! wave model langmuir multiplier - integer :: x2o_Sw_ustokes ! surface Stokes drift, x-component - integer :: x2o_Sw_vstokes ! surface Stokes drift, y-component - integer :: x2o_Foxx_taux ! zonal wind stress (taux) (W/m2 ) - integer :: x2o_Foxx_tauy ! meridonal wind stress (tauy) (W/m2 ) - integer :: x2o_Foxx_swnet ! net short-wave heat flux (W/m2 ) - integer :: x2o_Foxx_sen ! sensible heat flux (W/m2) - integer :: x2o_Foxx_lat ! latent heat flux (W/m2) - integer :: x2o_Foxx_lwup ! longwave radiation (up) (W/m2 ) - integer :: x2o_Faxa_lwdn ! longwave radiation (down) (W/m2 ) - integer :: x2o_Fioi_melth ! heat flux from snow & ice melt (W/m2 ) - integer :: x2o_Fioi_meltw ! snow melt flux (kg/m2/s) - integer :: x2o_Fioi_bcpho ! flux: Black Carbon hydrophobic release from sea ice component - integer :: x2o_Fioi_bcphi ! flux: Black Carbon hydrophilic release from sea ice component - integer :: x2o_Fioi_flxdst ! flux: dust release from sea ice component - integer :: x2o_Fioi_salt ! salt (kg(salt)/m2/s) - integer :: x2o_Foxx_evap ! evaporation flux (kg/m2/s) - integer :: x2o_Faxa_prec - integer :: x2o_Faxa_snow ! water flux due to snow (kg/m2/s) - integer :: x2o_Faxa_rain ! water flux due to rain (kg/m2/s) - integer :: x2o_Faxa_bcphidry ! flux: Black Carbon hydrophilic dry deposition - integer :: x2o_Faxa_bcphodry ! flux: Black Carbon hydrophobic dry deposition - integer :: x2o_Faxa_bcphiwet ! flux: Black Carbon hydrophilic wet deposition - integer :: x2o_Faxa_ocphidry ! flux: Organic Carbon hydrophilic dry deposition - integer :: x2o_Faxa_ocphodry ! flux: Organic Carbon hydrophobic dry deposition - integer :: x2o_Faxa_ocphiwet ! flux: Organic Carbon hydrophilic dry deposition - integer :: x2o_Faxa_dstwet1 ! flux: Size 1 dust -- wet deposition - integer :: x2o_Faxa_dstwet2 ! flux: Size 2 dust -- wet deposition - integer :: x2o_Faxa_dstwet3 ! flux: Size 3 dust -- wet deposition - integer :: x2o_Faxa_dstwet4 ! flux: Size 4 dust -- wet deposition - integer :: x2o_Faxa_dstdry1 ! flux: Size 1 dust -- dry deposition - integer :: x2o_Faxa_dstdry2 ! flux: Size 2 dust -- dry deposition - integer :: x2o_Faxa_dstdry3 ! flux: Size 3 dust -- dry deposition - integer :: x2o_Faxa_dstdry4 ! flux: Size 4 dust -- dry deposition - integer :: x2o_Foxx_rofl ! river runoff flux (kg/m2/s) - integer :: x2o_Foxx_rofi ! ice runoff flux (kg/m2/s) - - ! optional per thickness category fields - - integer, dimension(:), allocatable :: x2o_frac_col ! fraction of ocean cell, per column - integer, dimension(:), allocatable :: x2o_fracr_col ! fraction of ocean cell used in radiation computations, per column - integer, dimension(:), allocatable :: x2o_qsw_fracr_col ! qsw * fracr, per column - - end type cpl_indices - -contains - - - - subroutine coupler_indices_init(ind) - - type(cpl_indices), intent(inout) :: ind - - ! Local Variables - - type(mct_aVect) :: o2x ! temporary - type(mct_aVect) :: x2o ! temporary - - integer :: ncat ! thickness category index - character(len=2) :: cncat ! character version of ncat - integer :: ncol ! column index - integer :: mcog_ncols - integer :: lmcog_flds_sent - - ! Determine attribute vector indices - - ! create temporary attribute vectors - call mct_aVect_init(x2o, rList=seq_flds_x2o_fields, lsize=1) - call mct_aVect_init(o2x, rList=seq_flds_o2x_fields, lsize=1) - - ! ocean to coupler - ind%o2x_So_t = mct_avect_indexra(o2x,'So_t') - ind%o2x_So_u = mct_avect_indexra(o2x,'So_u') - ind%o2x_So_v = mct_avect_indexra(o2x,'So_v') - ind%o2x_So_s = mct_avect_indexra(o2x,'So_s') - ind%o2x_So_dhdx = mct_avect_indexra(o2x,'So_dhdx') - ind%o2x_So_dhdy = mct_avect_indexra(o2x,'So_dhdy') - ! QL, 150526, to wav, boundary layer depth - ind%o2x_So_bldepth = mct_avect_indexra(o2x,'So_bldepth') - ind%o2x_Fioo_q = mct_avect_indexra(o2x,'Fioo_q') - ind%o2x_Faoo_fco2_ocn = mct_avect_indexra(o2x,'Faoo_fco2_ocn',perrWith='quiet') - ind%o2x_Faoo_fdms_ocn = mct_avect_indexra(o2x,'Faoo_fdms_ocn',perrWith='quiet') - - ! coupler to ocean - ind%x2o_Si_ifrac = mct_avect_indexra(x2o,'Si_ifrac') - ind%x2o_Sa_pslv = mct_avect_indexra(x2o,'Sa_pslv') - ind%x2o_So_duu10n = mct_avect_indexra(x2o,'So_duu10n') - ! QL, 150526, from wav - ind%x2o_Sw_lamult = mct_avect_indexra(x2o,'Sw_lamult') - ind%x2o_Sw_ustokes = mct_avect_indexra(x2o,'Sw_ustokes') - ind%x2o_Sw_vstokes = mct_avect_indexra(x2o,'Sw_vstokes') - ind%x2o_Foxx_tauy = mct_avect_indexra(x2o,'Foxx_tauy') - ind%x2o_Foxx_taux = mct_avect_indexra(x2o,'Foxx_taux') - ind%x2o_Foxx_swnet = mct_avect_indexra(x2o,'Foxx_swnet') - ind%x2o_Foxx_lat = mct_avect_indexra(x2o,'Foxx_lat') - ind%x2o_Foxx_sen = mct_avect_indexra(x2o,'Foxx_sen') - ind%x2o_Foxx_lwup = mct_avect_indexra(x2o,'Foxx_lwup') - ind%x2o_Faxa_lwdn = mct_avect_indexra(x2o,'Faxa_lwdn') - ind%x2o_Fioi_melth = mct_avect_indexra(x2o,'Fioi_melth') - ind%x2o_Fioi_meltw = mct_avect_indexra(x2o,'Fioi_meltw') - ind%x2o_Fioi_salt = mct_avect_indexra(x2o,'Fioi_salt') - ind%x2o_Fioi_bcpho = mct_avect_indexra(x2o,'Fioi_bcpho') - ind%x2o_Fioi_bcphi = mct_avect_indexra(x2o,'Fioi_bcphi') - ind%x2o_Fioi_flxdst = mct_avect_indexra(x2o,'Fioi_flxdst') - ind%x2o_Faxa_prec = mct_avect_indexra(x2o,'Faxa_prec') - ind%x2o_Faxa_snow = mct_avect_indexra(x2o,'Faxa_snow') - ind%x2o_Faxa_rain = mct_avect_indexra(x2o,'Faxa_rain') - ind%x2o_Foxx_evap = mct_avect_indexra(x2o,'Foxx_evap') - ind%x2o_Foxx_rofl = mct_avect_indexra(x2o,'Foxx_rofl') - ind%x2o_Foxx_rofi = mct_avect_indexra(x2o,'Foxx_rofi') - ind%x2o_Faxa_bcphidry = mct_avect_indexra(x2o,'Faxa_bcphidry') - ind%x2o_Faxa_bcphodry = mct_avect_indexra(x2o,'Faxa_bcphodry') - ind%x2o_Faxa_bcphiwet = mct_avect_indexra(x2o,'Faxa_bcphiwet') - ind%x2o_Faxa_ocphidry = mct_avect_indexra(x2o,'Faxa_ocphidry') - ind%x2o_Faxa_ocphodry = mct_avect_indexra(x2o,'Faxa_ocphodry') - ind%x2o_Faxa_ocphiwet = mct_avect_indexra(x2o,'Faxa_ocphiwet') - ind%x2o_Faxa_dstdry1 = mct_avect_indexra(x2o,'Faxa_dstdry1') - ind%x2o_Faxa_dstdry2 = mct_avect_indexra(x2o,'Faxa_dstdry2') - ind%x2o_Faxa_dstdry3 = mct_avect_indexra(x2o,'Faxa_dstdry3') - ind%x2o_Faxa_dstdry4 = mct_avect_indexra(x2o,'Faxa_dstdry4') - ind%x2o_Faxa_dstwet1 = mct_avect_indexra(x2o,'Faxa_dstwet1') - ind%x2o_Faxa_dstwet2 = mct_avect_indexra(x2o,'Faxa_dstwet2') - ind%x2o_Faxa_dstwet3 = mct_avect_indexra(x2o,'Faxa_dstwet3') - ind%x2o_Faxa_dstwet4 = mct_avect_indexra(x2o,'Faxa_dstwet4') - ind%x2o_Sa_co2prog = mct_avect_indexra(x2o,'Sa_co2prog',perrWith='quiet') - ind%x2o_Sa_co2diag = mct_avect_indexra(x2o,'Sa_co2diag',perrWith='quiet') - - ! optional per thickness category fields - - ! convert cpl indices to mcog column indices - ! this implementation only handles columns due to ice thickness categories - - lmcog_flds_sent = seq_flds_i2o_per_cat - - if (seq_flds_i2o_per_cat) then - mcog_ncols = ice_ncat+1 - allocate(ind%x2o_frac_col(mcog_ncols)) - allocate(ind%x2o_fracr_col(mcog_ncols)) - allocate(ind%x2o_qsw_fracr_col(mcog_ncols)) - - ncol = 1 - ind%x2o_frac_col(ncol) = mct_avect_indexra(x2o,'Sf_afrac') - ind%x2o_fracr_col(ncol) = mct_avect_indexra(x2o,'Sf_afracr') - ind%x2o_qsw_fracr_col(ncol) = mct_avect_indexra(x2o,'Foxx_swnet_afracr') - - do ncat = 1, ice_ncat - write(cncat,'(i2.2)') ncat - ncol = ncat+1 - ind%x2o_frac_col(ncol) = mct_avect_indexra(x2o,'Si_ifrac_'//cncat) - ind%x2o_fracr_col(ncol) = ind%x2o_frac_col(ncol) - ind%x2o_qsw_fracr_col(ncol) = mct_avect_indexra(x2o,'PFioi_swpen_ifrac_'//cncat) - enddo - else - mcog_ncols = 1 - endif - - call mct_aVect_clean(x2o) - call mct_aVect_clean(o2x) - - - end subroutine coupler_indices_init - - !> Maps outgoing ocean data to MCT buffer - subroutine ocn_export(ind, ocn_public, grid, o2x) - type(cpl_indices), intent(inout) :: ind !< Index - type(ocean_public_type), intent(in) :: ocn_public !< Ocean surface state - type(ocean_grid_type), intent(in) :: grid !< Ocean model grid - real(kind=8), intent(inout) :: o2x(:,:) !< MCT outgoing bugger - ! Local variables - real, dimension(grid%isd:grid%ied,grid%jsd:grid%jed) :: ssh !< Local copy of sea_lev with updated halo - integer :: i, j, n, ig, jg - real :: slp_L, slp_R, slp_C, slope, u_min, u_max - - ! Copy from ocn_public to o2x. ocn_public uses global indexing with no halos. - ! The mask comes from "grid" that uses the usual MOM domain that has halos - ! and does not use global indexing. - n = 0 - do j=grid%jsc, grid%jec - jg = j + grid%jdg_offset - do i=grid%isc,grid%iec - n = n+1 - ig = i + grid%idg_offset - ! surface temperature in Kelvin - o2x(ind%o2x_So_t, n) = ocn_public%t_surf(ig,jg) * grid%mask2dT(i,j) - o2x(ind%o2x_So_s, n) = ocn_public%s_surf(ig,jg) * grid%mask2dT(i,j) - o2x(ind%o2x_So_u, n) = ocn_public%u_surf(ig,jg) * grid%mask2dT(i,j) - o2x(ind%o2x_So_v, n) = ocn_public%v_surf(ig,jg) * grid%mask2dT(i,j) - ! Make a copy of ssh in order to do a halo update. We use the usual MOM domain - ! in order to update halos. i.e. does not use global indexing. - ssh(i,j) = ocn_public%sea_lev(ig,jg) - end do - end do - - ! Update halo of ssh so we can calculate gradients - call pass_var(ssh, grid%domain) - - ! d/dx ssh - n = 0 - do j=grid%jsc, grid%jec ; do i=grid%isc,grid%iec - n = n+1 - ! This is a simple second-order difference - ! o2x(ind%o2x_So_dhdx, n) = 0.5 * (ssh(i+1,j) + ssh(i-1,j)) * grid%IdxT(i,j) * grid%mask2dT(i,j) - ! This is a PLM slope which might be less prone to the A-grid null mode - slp_L = (ssh(i,j) - ssh(i-1,j)) * grid%mask2dCu(I-1,j) - !if (grid%mask2dCu(I-1,j)==0.) slp_L = 0. - slp_R = (ssh(i+1,j) - ssh(i,j)) * grid%mask2dCu(I,j) - !if (grid%mask2dCu(I,j)==0.) slp_R = 0. - slp_C = 0.5 * (slp_L + slp_R) - if ( (slp_L * slp_R) > 0.0 ) then - ! This limits the slope so that the edge values are bounded by the - ! two cell averages spanning the edge. - u_min = min( ssh(i-1,j), ssh(i,j), ssh(i+1,j) ) - u_max = max( ssh(i-1,j), ssh(i,j), ssh(i+1,j) ) - slope = sign( min( abs(slp_C), 2.*min( ssh(i,j) - u_min, u_max - ssh(i,j) ) ), slp_C ) - else - ! Extrema in the mean values require a PCM reconstruction avoid generating - ! larger extreme values. - slope = 0.0 - end if - o2x(ind%o2x_So_dhdx, n) = slope * grid%IdxT(i,j) * grid%mask2dT(i,j) - end do; end do - - ! d/dy ssh - do j=grid%jsc, grid%jec ; do i=grid%isc,grid%iec - ! This is a simple second-order difference - ! o2x(ind%o2x_So_dhdy, n) = 0.5 * (ssh(i,j+1) + ssh(i,j-1)) * grid%IdyT(i,j) * grid%mask2dT(i,j) - ! This is a PLM slope which might be less prone to the A-grid null mode - slp_L = ssh(i,j) - ssh(i,j-1) - slp_R = ssh(i,j+1) - ssh(i,j) -slp_L=0. -slp_R=0. - slp_C = 0.5 * (slp_L + slp_R) - if ( (slp_L * slp_R) > 0.0 ) then - ! This limits the slope so that the edge values are bounded by the - ! two cell averages spanning the edge. - u_min = min( ssh(i,j-1), ssh(i,j), ssh(i,j+1) ) - u_max = max( ssh(i,j-1), ssh(i,j), ssh(i,j+1) ) - slope = sign( min( abs(slp_C), 2.*min( ssh(i,j) - u_min, u_max - ssh(i,j) ) ), slp_C ) - else - ! Extrema in the mean values require a PCM reconstruction avoid generating - ! larger extreme values. - slope = 0.0 - end if - o2x(ind%o2x_So_dhdy, n) = slope * grid%IdyT(i,j) * grid%mask2dT(i,j) - end do; end do - - end subroutine ocn_export - - - subroutine fill_ice_ocean_bnd(ice_ocean_boundary, grid, x2o_o, ind, sw_decomp, c1, c2, c3, c4) - type(ice_ocean_boundary_type), intent(inout) :: ice_ocean_boundary !< A type for the ice ocean boundary - type(ocean_grid_type), intent(in) :: grid - !type(mct_aVect), intent(in) :: x2o_o - real(kind=8), intent(in) :: x2o_o(:,:) - type(cpl_indices), intent(inout) :: ind - logical, intent(in) :: sw_decomp !< controls if shortwave is decomposed - !! into four components - real(kind=8), intent(in), optional :: c1, c2, c3, c4 !< Coeffs. used in the shortwave decomposition - - ! local variables - integer :: i, j, k, ig, jg !< grid indices - - ! variable that are not in ice_ocean_boundary: - ! latent (x2o_Foxx_lat) - ! surface Stokes drift, x-comp. (x2o_Sw_ustokes) - ! surface Stokes drift, y-comp. (x2o_Sw_vstokes) - ! wave model langmuir multiplier (x2o_Sw_lamult) - - ! biogeochemistry - ! Black Carbon hydrophobic release from sea ice component (x2o_Fioi_bcpho) - ! Black Carbon hydrophilic release from sea ice component (x2o_Fioi_bcphi) - ! dust release from sea ice component (x2o_Fioi_flxdst) - ! Black Carbon hydrophilic dry deposition (x2o_Faxa_bcphidry) - ! Black Carbon hydrophobic dry deposition (x2o_Faxa_bcphodry) - ! Black Carbon hydrophobic wet deposition (x2o_Faxa_bcphiwet) - ! Organic Carbon hydrophilic dry deposition (x2o_Faxa_ocphidry) - ! Organic Carbon hydrophobic dry deposition (x2o_Faxa_ocphodry) - ! Organic Carbon hydrophilic dry deposition (x2o_Faxa_ocphiwet) - ! Sizes 1 to 4 dust - wet deposition (x2o_Faxa_dstwet?) - ! Sizes 1 to 4 dust - dry deposition (x2o_Faxa_dstdry?) - - - ! need wind_stress_multiplier? - - k = 0 - do j = grid%jsc, grid%jec - jg = j + grid%jdg_offset - do i = grid%isc, grid%iec - k = k + 1 ! Increment position within gindex - ig = i + grid%idg_offset - ! sea-level pressure (Pa) - ice_ocean_boundary%p(ig,jg) = x2o_o(ind%x2o_Sa_pslv,k) - ! zonal wind stress (taux) - ice_ocean_boundary%u_flux(ig,jg) = x2o_o(ind%x2o_Foxx_taux,k) - ! meridional wind stress (tauy) - ice_ocean_boundary%v_flux(ig,jg) = x2o_o(ind%x2o_Foxx_tauy,k) - ! sensible heat flux (W/m2) - ice_ocean_boundary%t_flux(ig,jg) = -x2o_o(ind%x2o_Foxx_sen,k) - ! salt flux - ice_ocean_boundary%salt_flux(ig,jg) = -x2o_o(ind%x2o_Fioi_salt,k) - ! heat content from frozen runoff - ice_ocean_boundary%calving_hflx(ig,jg) = 0.0 - ! snow melt flux - !ice_ocean_boundary%fprec(ig,jg) = x2o_o(ind%x2o_Fioi_meltw,k) - ! river runoff flux - ice_ocean_boundary%runoff(ig,jg) = x2o_o(ind%x2o_Foxx_rofl,k) - ! ice runoff flux - ice_ocean_boundary%calving(ig,jg) = x2o_o(ind%x2o_Foxx_rofi,k) - ! liquid precipitation (rain) - ice_ocean_boundary%lprec(ig,jg) = x2o_o(ind%x2o_Faxa_rain,k) - ! frozen precipitation (snow) - ice_ocean_boundary%fprec(ig,jg) = x2o_o(ind%x2o_Faxa_snow,k) - ! evaporation flux, MOM6 calls q_flux specific humidity (kg/m2/s) - ice_ocean_boundary%q_flux(ig,jg) = -x2o_o(ind%x2o_Foxx_evap,k) - ! longwave radiation, sum up and down (W/m2) - ice_ocean_boundary%lw_flux(ig,jg) = x2o_o(ind%x2o_Faxa_lwdn,k) + x2o_o(ind%x2o_Foxx_lwup,k) - if (sw_decomp) then - ! Use runtime coefficients to decompose net short-wave heat flux into 4 components - ! 1) visible, direct shortwave (W/m2) - ice_ocean_boundary%sw_flux_vis_dir(ig,jg) = x2o_o(ind%x2o_Foxx_swnet,k)*c1 - ! 2) visible, diffuse shortwave (W/m2) - ice_ocean_boundary%sw_flux_vis_dif(ig,jg) = x2o_o(ind%x2o_Foxx_swnet,k)*c2 - ! 3) near-IR, direct shortwave (W/m2) - ice_ocean_boundary%sw_flux_nir_dir(ig,jg) = x2o_o(ind%x2o_Foxx_swnet,k)*c3 - ! 4) near-IR, diffuse shortwave (W/m2) - ice_ocean_boundary%sw_flux_nir_dif(ig,jg) = x2o_o(ind%x2o_Foxx_swnet,k)*c4 - else - call MOM_error(FATAL,"fill_ice_ocean_bnd: this option has not been implemented yet."// & - "Shortwave must be decomposed using coeffs. c1, c2, c3, c4."); - endif - enddo - enddo - - ice_ocean_boundary%wind_stagger = AGRID - - end subroutine fill_ice_ocean_bnd - -end module coupler_indices diff --git a/config_src/mct_driver/ocn_comp_mct.F90 b/config_src/mct_driver/ocn_comp_mct.F90 index d152e34998..847c3daba9 100644 --- a/config_src/mct_driver/ocn_comp_mct.F90 +++ b/config_src/mct_driver/ocn_comp_mct.F90 @@ -6,14 +6,15 @@ module ocn_comp_mct ! mct modules use ESMF, only: ESMF_clock, ESMF_time, ESMF_timeInterval, ESMF_TimeInc use ESMF, only: ESMF_ClockGet, ESMF_TimeGet, ESMF_TimeIntervalGet -use seq_cdata_mod, only: seq_cdata -use seq_cdata_mod, only: seq_cdata_setptrs +use seq_cdata_mod, only: seq_cdata, seq_cdata_setptrs +use seq_flds_mod, only: ice_ncat, seq_flds_i2o_per_cat use mct_mod, only: mct_gsMap, mct_gsmap_init, mct_gsMap_lsize, & mct_gsmap_orderedpoints use mct_mod, only: mct_aVect, mct_aVect_init, mct_aVect_zero, & mct_aVect_nRattr use mct_mod, only: mct_gGrid, mct_gGrid_init, mct_gGrid_importRAttr, & mct_gGrid_importIAttr +use mct_mod, only : mct_avect_indexra, mct_aVect_clean use seq_flds_mod, only: seq_flds_x2o_fields, seq_flds_o2x_fields, seq_flds_dom_coord, & seq_flds_dom_other use seq_infodata_mod, only: seq_infodata_type, seq_infodata_GetData, & @@ -29,14 +30,13 @@ module ocn_comp_mct use ocean_model_mod, only: ocean_model_init, get_state_pointers, ocean_model_restart use ocean_model_mod, only: ice_ocean_boundary_type, update_ocean_model use MOM_domains, only: MOM_infra_init, num_pes, root_pe, pe_here +use MOM_domains, only : pass_var, AGRID use MOM_grid, only: ocean_grid_type, get_global_grid_size use MOM_variables, only: surface use MOM_error_handler, only: MOM_error, FATAL, is_root_pe use MOM_time_manager, only: time_type, set_date, set_time, set_calendar_type, NOLEAP use MOM_file_parser, only: get_param, log_version, param_file_type use MOM_get_input, only: Get_MOM_Input, directories -use coupler_indices, only: coupler_indices_init, cpl_indices -use coupler_indices, only: ocn_export, fill_ice_ocean_bnd ! By default make data private implicit none; private @@ -47,8 +47,80 @@ module ocn_comp_mct ! Flag for debugging logical, parameter :: debug=.true. + !> Structure with MCT attribute vectors and indices + type cpl_indices + + ! ocean to coupler + integer :: o2x_So_t !< Surface potential temperature (deg C) + integer :: o2x_So_u !< Surface zonal velocity (m/s) + integer :: o2x_So_v !< Surface meridional velocity (m/s) + integer :: o2x_So_s !< Surface salinity (PSU) + integer :: o2x_So_dhdx !< Zonal slope in the sea surface height + integer :: o2x_So_dhdy !< Meridional lope in the sea surface height + integer :: o2x_So_bldepth !< Boundary layer depth (m) + integer :: o2x_Fioo_q !< Heat flux? + integer :: o2x_Faoo_fco2_ocn!< CO2 flux + integer :: o2x_Faoo_fdms_ocn!< DMS flux + + ! coupler to ocean + integer :: x2o_Si_ifrac !< Fractional ice wrt ocean + integer :: x2o_So_duu10n !< 10m wind speed squared (m^2/s^2) + integer :: x2o_Sa_pslv !< Sea-level pressure (Pa) + integer :: x2o_Sa_co2prog !< Bottom atm level prognostic CO2 + integer :: x2o_Sa_co2diag !< Bottom atm level diagnostic CO2 + integer :: x2o_Sw_lamult !< Wave model langmuir multiplier + integer :: x2o_Sw_ustokes !< Surface Stokes drift, x-component + integer :: x2o_Sw_vstokes !< Surface Stokes drift, y-component + integer :: x2o_Foxx_taux !< Zonal wind stress (W/m2) + integer :: x2o_Foxx_tauy !< Meridonal wind stress (W/m2) + integer :: x2o_Foxx_swnet !< Net short-wave heat flux (W/m2) + integer :: x2o_Foxx_sen !< Sensible heat flux (W/m2) + integer :: x2o_Foxx_lat !< Latent heat flux (W/m2) + integer :: x2o_Foxx_lwup !< Longwave radiation, up (W/m2) + integer :: x2o_Faxa_lwdn !< Longwave radiation, down (W/m2) + integer :: x2o_Fioi_melth !< Heat flux from snow & ice melt (W/m2) + integer :: x2o_Fioi_meltw !< Snow melt flux (kg/m2/s) + integer :: x2o_Fioi_bcpho !< Black Carbon hydrophobic release + !! from sea ice component + integer :: x2o_Fioi_bcphi !< Black Carbon hydrophilic release from + !! sea ice component + integer :: x2o_Fioi_flxdst !< Dust release from sea ice component + integer :: x2o_Fioi_salt !< Salt flux (kg(salt)/m2/s) + integer :: x2o_Foxx_evap !< Evaporation flux (kg/m2/s) + integer :: x2o_Faxa_prec !< Total precipitation flux (kg/m2/s) + integer :: x2o_Faxa_snow !< Water flux due to snow (kg/m2/s) + integer :: x2o_Faxa_rain !< Water flux due to rain (kg/m2/s) + integer :: x2o_Faxa_bcphidry !< Black Carbon hydrophilic dry deposition + integer :: x2o_Faxa_bcphodry !< Black Carbon hydrophobic dry deposition + integer :: x2o_Faxa_bcphiwet !< Black Carbon hydrophilic wet deposition + integer :: x2o_Faxa_ocphidry !< Organic Carbon hydrophilic dry deposition + integer :: x2o_Faxa_ocphodry !< Organic Carbon hydrophobic dry deposition + integer :: x2o_Faxa_ocphiwet !< Organic Carbon hydrophilic dry deposition + integer :: x2o_Faxa_dstwet1 !< Size 1 dust -- wet deposition + integer :: x2o_Faxa_dstwet2 !< Size 2 dust -- wet deposition + integer :: x2o_Faxa_dstwet3 !< Size 3 dust -- wet deposition + integer :: x2o_Faxa_dstwet4 !< Size 4 dust -- wet deposition + integer :: x2o_Faxa_dstdry1 !< Size 1 dust -- dry deposition + integer :: x2o_Faxa_dstdry2 !< Size 2 dust -- dry deposition + integer :: x2o_Faxa_dstdry3 !< Size 3 dust -- dry deposition + integer :: x2o_Faxa_dstdry4 !< Size 4 dust -- dry deposition + integer :: x2o_Foxx_rofl !< River runoff flux (kg/m2/s) + integer :: x2o_Foxx_rofi !< Ice runoff flux (kg/m2/s) + + ! optional per thickness category fields + + integer, dimension(:), allocatable :: x2o_frac_col !< Fraction of ocean cell, + !! per column + integer, dimension(:), allocatable :: x2o_fracr_col!< Fraction of ocean cell used + !! in radiation computations, + !! per column + integer, dimension(:), allocatable :: x2o_qsw_fracr_col !< qsw * fracr, per column + + end type cpl_indices + !> Control structure for this module type MCT_MOM_Data + type(ocean_state_type), pointer :: ocn_state => NULL() !< The private state of ocean type(ocean_public_type), pointer :: ocn_public => NULL() !< The public state of ocean type(ocean_grid_type), pointer :: grid => NULL() !< The grid structure @@ -59,6 +131,7 @@ module ocn_comp_mct ! runtime params logical :: sw_decomp !< Controls whether shortwave is decomposed into four components real :: c1, c2, c3, c4 !< Coeffs. used in the shortwave decomposition + end type MCT_MOM_Data type(MCT_MOM_Data) :: glb !< global structure @@ -131,7 +204,7 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) call seq_cdata_setptrs(cdata_o, id=MOM_MCT_ID, mpicom=mpicom_ocn, & gsMap=MOM_MCT_gsMap, dom=MOM_MCT_dom, infodata=glb%infodata) - ! Initialize the model run + ! Determine attribute vector indices call coupler_indices_init(glb%ind) call seq_infodata_GetData( glb%infodata, case_name=runid ) @@ -346,6 +419,317 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename ) end subroutine ocn_init_mct +!> Determines attribute vector indices +subroutine coupler_indices_init(ind) + + type(cpl_indices), intent(inout) :: ind !< Structure with coupler indices + !! and vectors + + ! Local Variables + type(mct_aVect) :: o2x !< Array with ocean to coupler data + type(mct_aVect) :: x2o !< Array with coupler to ocean data + + integer :: ncat !< Thickness category index + character(len=2) :: cncat !< Character version of ncat + integer :: ncol !< Column index + integer :: mcog_ncols !< Number of ice thickness categories? + integer :: lmcog_flds_sent !< Used to convert per thickness + !! category fields? + + ! create temporary attribute vectors + call mct_aVect_init(x2o, rList=seq_flds_x2o_fields, lsize=1) + call mct_aVect_init(o2x, rList=seq_flds_o2x_fields, lsize=1) + + ! ocean to coupler + ind%o2x_So_t = mct_avect_indexra(o2x,'So_t') + ind%o2x_So_u = mct_avect_indexra(o2x,'So_u') + ind%o2x_So_v = mct_avect_indexra(o2x,'So_v') + ind%o2x_So_s = mct_avect_indexra(o2x,'So_s') + ind%o2x_So_dhdx = mct_avect_indexra(o2x,'So_dhdx') + ind%o2x_So_dhdy = mct_avect_indexra(o2x,'So_dhdy') + ! QL, 150526, to wav, boundary layer depth + ind%o2x_So_bldepth = mct_avect_indexra(o2x,'So_bldepth') + ind%o2x_Fioo_q = mct_avect_indexra(o2x,'Fioo_q') + ind%o2x_Faoo_fco2_ocn = mct_avect_indexra(o2x,'Faoo_fco2_ocn',perrWith='quiet') + ind%o2x_Faoo_fdms_ocn = mct_avect_indexra(o2x,'Faoo_fdms_ocn',perrWith='quiet') + + ! coupler to ocean + ind%x2o_Si_ifrac = mct_avect_indexra(x2o,'Si_ifrac') + ind%x2o_Sa_pslv = mct_avect_indexra(x2o,'Sa_pslv') + ind%x2o_So_duu10n = mct_avect_indexra(x2o,'So_duu10n') + ! QL, 150526, from wav + ind%x2o_Sw_lamult = mct_avect_indexra(x2o,'Sw_lamult') + ind%x2o_Sw_ustokes = mct_avect_indexra(x2o,'Sw_ustokes') + ind%x2o_Sw_vstokes = mct_avect_indexra(x2o,'Sw_vstokes') + ind%x2o_Foxx_tauy = mct_avect_indexra(x2o,'Foxx_tauy') + ind%x2o_Foxx_taux = mct_avect_indexra(x2o,'Foxx_taux') + ind%x2o_Foxx_swnet = mct_avect_indexra(x2o,'Foxx_swnet') + ind%x2o_Foxx_lat = mct_avect_indexra(x2o,'Foxx_lat') + ind%x2o_Foxx_sen = mct_avect_indexra(x2o,'Foxx_sen') + ind%x2o_Foxx_lwup = mct_avect_indexra(x2o,'Foxx_lwup') + ind%x2o_Faxa_lwdn = mct_avect_indexra(x2o,'Faxa_lwdn') + ind%x2o_Fioi_melth = mct_avect_indexra(x2o,'Fioi_melth') + ind%x2o_Fioi_meltw = mct_avect_indexra(x2o,'Fioi_meltw') + ind%x2o_Fioi_salt = mct_avect_indexra(x2o,'Fioi_salt') + ind%x2o_Fioi_bcpho = mct_avect_indexra(x2o,'Fioi_bcpho') + ind%x2o_Fioi_bcphi = mct_avect_indexra(x2o,'Fioi_bcphi') + ind%x2o_Fioi_flxdst = mct_avect_indexra(x2o,'Fioi_flxdst') + ind%x2o_Faxa_prec = mct_avect_indexra(x2o,'Faxa_prec') + ind%x2o_Faxa_snow = mct_avect_indexra(x2o,'Faxa_snow') + ind%x2o_Faxa_rain = mct_avect_indexra(x2o,'Faxa_rain') + ind%x2o_Foxx_evap = mct_avect_indexra(x2o,'Foxx_evap') + ind%x2o_Foxx_rofl = mct_avect_indexra(x2o,'Foxx_rofl') + ind%x2o_Foxx_rofi = mct_avect_indexra(x2o,'Foxx_rofi') + ind%x2o_Faxa_bcphidry = mct_avect_indexra(x2o,'Faxa_bcphidry') + ind%x2o_Faxa_bcphodry = mct_avect_indexra(x2o,'Faxa_bcphodry') + ind%x2o_Faxa_bcphiwet = mct_avect_indexra(x2o,'Faxa_bcphiwet') + ind%x2o_Faxa_ocphidry = mct_avect_indexra(x2o,'Faxa_ocphidry') + ind%x2o_Faxa_ocphodry = mct_avect_indexra(x2o,'Faxa_ocphodry') + ind%x2o_Faxa_ocphiwet = mct_avect_indexra(x2o,'Faxa_ocphiwet') + ind%x2o_Faxa_dstdry1 = mct_avect_indexra(x2o,'Faxa_dstdry1') + ind%x2o_Faxa_dstdry2 = mct_avect_indexra(x2o,'Faxa_dstdry2') + ind%x2o_Faxa_dstdry3 = mct_avect_indexra(x2o,'Faxa_dstdry3') + ind%x2o_Faxa_dstdry4 = mct_avect_indexra(x2o,'Faxa_dstdry4') + ind%x2o_Faxa_dstwet1 = mct_avect_indexra(x2o,'Faxa_dstwet1') + ind%x2o_Faxa_dstwet2 = mct_avect_indexra(x2o,'Faxa_dstwet2') + ind%x2o_Faxa_dstwet3 = mct_avect_indexra(x2o,'Faxa_dstwet3') + ind%x2o_Faxa_dstwet4 = mct_avect_indexra(x2o,'Faxa_dstwet4') + ind%x2o_Sa_co2prog = mct_avect_indexra(x2o,'Sa_co2prog',perrWith='quiet') + ind%x2o_Sa_co2diag = mct_avect_indexra(x2o,'Sa_co2diag',perrWith='quiet') + ! optional per thickness category fields + + ! convert cpl indices to mcog column indices + ! this implementation only handles columns due to ice thickness categories + lmcog_flds_sent = seq_flds_i2o_per_cat + + if (seq_flds_i2o_per_cat) then + mcog_ncols = ice_ncat+1 + allocate(ind%x2o_frac_col(mcog_ncols)) + allocate(ind%x2o_fracr_col(mcog_ncols)) + allocate(ind%x2o_qsw_fracr_col(mcog_ncols)) + ncol = 1 + ind%x2o_frac_col(ncol) = mct_avect_indexra(x2o,'Sf_afrac') + ind%x2o_fracr_col(ncol) = mct_avect_indexra(x2o,'Sf_afracr') + ind%x2o_qsw_fracr_col(ncol) = mct_avect_indexra(x2o,'Foxx_swnet_afracr') + + do ncat = 1, ice_ncat + write(cncat,'(i2.2)') ncat + ncol = ncat+1 + ind%x2o_frac_col(ncol) = mct_avect_indexra(x2o,'Si_ifrac_'//cncat) + ind%x2o_fracr_col(ncol) = ind%x2o_frac_col(ncol) + ind%x2o_qsw_fracr_col(ncol) = mct_avect_indexra(x2o,'PFioi_swpen_ifrac_'//cncat) + enddo + else + mcog_ncols = 1 + endif + + call mct_aVect_clean(x2o) + call mct_aVect_clean(o2x) + +end subroutine coupler_indices_init + +!> Maps outgoing ocean data to MCT buffer +subroutine ocn_export(ind, ocn_public, grid, o2x) + type(cpl_indices), intent(inout) :: ind !< Structure with coupler + !! indices and vectors + type(ocean_public_type), intent(in) :: ocn_public !< Ocean surface state + type(ocean_grid_type), intent(in) :: grid !< Ocean model grid + real(kind=8), intent(inout) :: o2x(:,:) !< MCT outgoing bugger + ! Local variables + real, dimension(grid%isd:grid%ied,grid%jsd:grid%jed) :: ssh !< Local copy of sea_lev with updated halo + integer :: i, j, n, ig, jg !< Grid indices + real :: slp_L, slp_R, slp_C, slope, u_min, u_max + + ! Copy from ocn_public to o2x. ocn_public uses global indexing with no halos. + ! The mask comes from "grid" that uses the usual MOM domain that has halos + ! and does not use global indexing. + n = 0 + do j=grid%jsc, grid%jec + jg = j + grid%jdg_offset + do i=grid%isc,grid%iec + n = n+1 + ig = i + grid%idg_offset + ! surface temperature in Kelvin + o2x(ind%o2x_So_t, n) = ocn_public%t_surf(ig,jg) * grid%mask2dT(i,j) + o2x(ind%o2x_So_s, n) = ocn_public%s_surf(ig,jg) * grid%mask2dT(i,j) + o2x(ind%o2x_So_u, n) = ocn_public%u_surf(ig,jg) * grid%mask2dT(i,j) + o2x(ind%o2x_So_v, n) = ocn_public%v_surf(ig,jg) * grid%mask2dT(i,j) + ! Make a copy of ssh in order to do a halo update. We use the usual MOM domain + ! in order to update halos. i.e. does not use global indexing. + ssh(i,j) = ocn_public%sea_lev(ig,jg) + end do + end do + + ! Update halo of ssh so we can calculate gradients + call pass_var(ssh, grid%domain) + + + ! d/dx ssh + n = 0 + do j=grid%jsc, grid%jec ; do i=grid%isc,grid%iec + n = n+1 + ! This is a simple second-order difference + ! o2x(ind%o2x_So_dhdx, n) = 0.5 * (ssh(i+1,j) + ssh(i-1,j)) * grid%IdxT(i,j) * grid%mask2dT(i,j) + ! This is a PLM slope which might be less prone to the A-grid null mode + slp_L = (ssh(i,j) - ssh(i-1,j)) * grid%mask2dCu(I-1,j) + !if (grid%mask2dCu(I-1,j)==0.) slp_L = 0. + slp_R = (ssh(i+1,j) - ssh(i,j)) * grid%mask2dCu(I,j) + !if (grid%mask2dCu(I,j)==0.) slp_R = 0. + slp_C = 0.5 * (slp_L + slp_R) + if ( (slp_L * slp_R) > 0.0 ) then + ! This limits the slope so that the edge values are bounded by the + ! two cell averages spanning the edge. + u_min = min( ssh(i-1,j), ssh(i,j), ssh(i+1,j) ) + u_max = max( ssh(i-1,j), ssh(i,j), ssh(i+1,j) ) + slope = sign( min( abs(slp_C), 2.*min( ssh(i,j) - u_min, u_max - ssh(i,j) ) ), slp_C ) + else + ! Extrema in the mean values require a PCM reconstruction avoid generating + ! larger extreme values. + slope = 0.0 + end if + o2x(ind%o2x_So_dhdx, n) = slope * grid%IdxT(i,j) * grid%mask2dT(i,j) + end do; end do + + ! d/dy ssh + do j=grid%jsc, grid%jec ; do i=grid%isc,grid%iec + ! This is a simple second-order difference + ! o2x(ind%o2x_So_dhdy, n) = 0.5 * (ssh(i,j+1) + ssh(i,j-1)) * grid%IdyT(i,j) * grid%mask2dT(i,j) + ! This is a PLM slope which might be less prone to the A-grid null mode + slp_L = ssh(i,j) - ssh(i,j-1) + slp_R = ssh(i,j+1) - ssh(i,j) + slp_L=0.; slp_R=0. + slp_C = 0.5 * (slp_L + slp_R) + if ((slp_L * slp_R) > 0.0) then + ! This limits the slope so that the edge values are bounded by the + ! two cell averages spanning the edge. + u_min = min( ssh(i,j-1), ssh(i,j), ssh(i,j+1) ) + u_max = max( ssh(i,j-1), ssh(i,j), ssh(i,j+1) ) + slope = sign( min( abs(slp_C), 2.*min( ssh(i,j) - u_min, u_max - ssh(i,j) ) ), slp_C ) + else + ! Extrema in the mean values require a PCM reconstruction avoid generating + ! larger extreme values. + slope = 0.0 + end if + o2x(ind%o2x_So_dhdy, n) = slope * grid%IdyT(i,j) * grid%mask2dT(i,j) + end do; end do + +end subroutine ocn_export + +!> Fills the ice ocean boundary type +subroutine fill_ice_ocean_bnd(ice_ocean_boundary, grid, x2o_o, ind, & + sw_decomp, c1, c2, c3, c4) + + type(ice_ocean_boundary_type), intent(inout) :: ice_ocean_boundary !< A type for the ice ocean boundary + type(ocean_grid_type), intent(in) :: grid !< + !type(mct_aVect), intent(in) :: x2o_o + real(kind=8), intent(in) :: x2o_o(:,:) + type(cpl_indices), intent(inout) :: ind + logical, intent(in) :: sw_decomp !< controls if shortwave is + !!decomposed into four components + real(kind=8), intent(in), optional :: c1, c2, c3, c4 !< Coeffs. used in the shortwave decomposition + + ! local variables + integer :: i, j, k, ig, jg !< grid indices + + ! /TODO The following comments summarizes the mismatches between MCT and MOM6 in terms + ! of ice ocean fluxes. + + ! Redundancies: + ! x2o_Foxx_lat, x2o_Faxa_prec, x2o_Faxa_evap - **latent from MOM6 and coupler are different** + ! x2o_Faxa_prec = x2o_Faxa_rain + x2o_Faxa_snow + + ! Variables that **could not** be verified so far: + ! x2o_Foxx_rofl + ! x2o_Foxx_rof + + ! Variables in IOB that are **NOT** filled by the coupler: + ! ustar_berg, frictional velocity beneath icebergs (m/s) + ! 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 IOB): + ! x2o_Fioi_melth, heat flux from snow & ice melt (W/m2) + ! x2o_Fioi_meltw, snow melt flux (kg/m2/s) + ! 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 + ! x2o_Foxx_lat, latent heat flux (W/m2) + + ! 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) + + ! 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 depositi + + k = 0 + do j = grid%jsc, grid%jec + jg = j + grid%jdg_offset + do i = grid%isc, grid%iec + k = k + 1 ! Increment position within gindex + ig = i + grid%idg_offset + ! sea-level pressure (Pa) + ice_ocean_boundary%p(ig,jg) = x2o_o(ind%x2o_Sa_pslv,k) + ! zonal wind stress (taux) + ice_ocean_boundary%u_flux(ig,jg) = x2o_o(ind%x2o_Foxx_taux,k) + ! meridional wind stress (tauy) + ice_ocean_boundary%v_flux(ig,jg) = x2o_o(ind%x2o_Foxx_tauy,k) + ! sensible heat flux (W/m2) + ice_ocean_boundary%t_flux(ig,jg) = -x2o_o(ind%x2o_Foxx_sen,k) + ! salt flux + ice_ocean_boundary%salt_flux(ig,jg) = -x2o_o(ind%x2o_Fioi_salt,k) + ! heat content from frozen runoff + ice_ocean_boundary%calving_hflx(ig,jg) = 0.0 + ! snow melt flux + !ice_ocean_boundary%fprec(ig,jg) = x2o_o(ind%x2o_Fioi_meltw,k) + ! river runoff flux + ice_ocean_boundary%runoff(ig,jg) = x2o_o(ind%x2o_Foxx_rofl,k) + ! ice runoff flux + ice_ocean_boundary%calving(ig,jg) = x2o_o(ind%x2o_Foxx_rofi,k) + ! liquid precipitation (rain) + ice_ocean_boundary%lprec(ig,jg) = x2o_o(ind%x2o_Faxa_rain,k) + ! frozen precipitation (snow) + ice_ocean_boundary%fprec(ig,jg) = x2o_o(ind%x2o_Faxa_snow,k) + ! evaporation flux, MOM6 calls q_flux specific humidity (kg/m2/s) + ice_ocean_boundary%q_flux(ig,jg) = -x2o_o(ind%x2o_Foxx_evap,k) + ! longwave radiation, sum up and down (W/m2) + ice_ocean_boundary%lw_flux(ig,jg) = x2o_o(ind%x2o_Faxa_lwdn,k) + x2o_o(ind%x2o_Foxx_lwup,k) + if (sw_decomp) then + ! Use runtime coefficients to decompose net short-wave heat flux into 4 components + ! 1) visible, direct shortwave (W/m2) + ice_ocean_boundary%sw_flux_vis_dir(ig,jg) = x2o_o(ind%x2o_Foxx_swnet,k)*c1 + ! 2) visible, diffuse shortwave (W/m2) + ice_ocean_boundary%sw_flux_vis_dif(ig,jg) = x2o_o(ind%x2o_Foxx_swnet,k)*c2 + ! 3) near-IR, direct shortwave (W/m2) + ice_ocean_boundary%sw_flux_nir_dir(ig,jg) = x2o_o(ind%x2o_Foxx_swnet,k)*c3 + ! 4) near-IR, diffuse shortwave (W/m2) + ice_ocean_boundary%sw_flux_nir_dif(ig,jg) = x2o_o(ind%x2o_Foxx_swnet,k)*c4 + else + call MOM_error(FATAL,"fill_ice_ocean_bnd: this option has not been implemented yet."// & + "Shortwave must be decomposed using coeffs. c1, c2, c3, c4."); + endif + enddo + enddo + + ice_ocean_boundary%wind_stagger = AGRID + +end subroutine fill_ice_ocean_bnd + !> Step forward ocean model for coupling interval subroutine ocn_run_mct( EClock, cdata_o, x2o_o, o2x_o) type(ESMF_Clock), intent(inout) :: EClock !< Time and time step ? \todo Why must this be intent(inout)? diff --git a/config_src/mct_driver/ocn_import_export.F90 b/config_src/mct_driver/ocn_import_export.F90 deleted file mode 100644 index cc7cc37e0b..0000000000 --- a/config_src/mct_driver/ocn_import_export.F90 +++ /dev/null @@ -1,141 +0,0 @@ -module ocn_import_export - - implicit none - public - save - - ! accumulated sum of send buffer quantities for averaging before being sent - !real (r8), dimension(:,:,:,:), allocatable :: SBUFF_SUM - !real (r8) :: tlast_coupled - - !TODO: update the types of following vars - double precision, dimension(:,:,:,:), allocatable :: SBUFF_SUM - double precision :: tlast_coupled -contains - -!*********************************************************************** -!BOP -! !IROUTINE: ocn_import -! !INTERFACE: - - subroutine ocn_import(x2o, ldiag_cpl, errorCode) - -! !DESCRIPTION: -!----------------------------------------------------------------------- -! This routine receives message from cpl7 driver -! -! The following fields are always received from the coupler: -! -! o taux -- zonal wind stress (taux) (W/m2 ) -! o tauy -- meridonal wind stress (tauy) (W/m2 ) -! o snow -- water flux due to snow (kg/m2/s) -! o rain -- water flux due to rain (kg/m2/s) -! o evap -- evaporation flux (kg/m2/s) -! o meltw -- snow melt flux (kg/m2/s) -! o salt -- salt (kg(salt)/m2/s) -! o swnet -- net short-wave heat flux (W/m2 ) -! o sen -- sensible heat flux (W/m2 ) -! o lwup -- longwave radiation (up) (W/m2 ) -! o lwdn -- longwave radiation (down) (W/m2 ) -! o melth -- heat flux from snow&ice melt (W/m2 ) -! o ifrac -- ice fraction -! o rofl -- river runoff flux (kg/m2/s) -! o rofi -- ice runoff flux (kg/m2/s) -! -! The following fields are sometimes received from the coupler, -! depending on model options: -! -! o pslv -- sea-level pressure (Pa) -! o duu10n -- 10m wind speed squared (m^2/s^2) -! o co2prog-- bottom atm level prognostic co2 -! o co2diag-- bottom atm level diagnostic co2 -! -!----------------------------------------------------------------------- -! -! !REVISION HISTORY: -! same as module - -! !INPUT/OUTPUT PARAMETERS: - - !real(r8) , intent(inout) :: x2o(:,:) - !logical (log_kind) , intent(in) :: ldiag_cpl - !integer (POP_i4) , intent(out) :: errorCode ! returned error code - - !TODO: update the types of following params - double precision, intent(inout) :: x2o(:,:) - logical, intent(in) :: ldiag_cpl - integer, intent(out) :: errorCode ! returned error code - -!EOP -!BOC -!----------------------------------------------------------------------- -! -! local variables -! -!----------------------------------------------------------------------- - - - - - - - - - - -!----------------------------------------------------------------------- -!EOC - - end subroutine ocn_import - -!*********************************************************************** -!BOP -! !IROUTINE: ocn_export_mct -! !INTERFACE: - - subroutine ocn_export(o2x, ldiag_cpl, errorCode) - -! !DESCRIPTION: -! This routine calls the routines necessary to send MOM6 fields to -! the CCSM cpl7 driver -! -! !REVISION HISTORY: -! same as module -! -! !INPUT/OUTPUT PARAMETERS: - - !real(r8) , intent(inout) :: o2x(:,:) - !logical (log_kind) , intent(in) :: ldiag_cpl - !integer (POP_i4) , intent(out) :: errorCode ! returned error code - - !TODO: update the types of following params - double precision, intent(inout) :: o2x(:,:) - logical, intent(in) :: ldiag_cpl - integer, intent(out) :: errorCode ! returned error code - -!EOP -!BOC -!----------------------------------------------------------------------- -! -! local variables -! -!----------------------------------------------------------------------- - - - - - - - - -!----------------------------------------------------------------------- -!EOC - - end subroutine ocn_export - -!*********************************************************************** - - - -end module ocn_import_export -