diff --git a/config_src/nuopc_driver/mom_cap.F90 b/config_src/nuopc_driver/mom_cap.F90 index 3f6dd1348b..e99a1a0a22 100644 --- a/config_src/nuopc_driver/mom_cap.F90 +++ b/config_src/nuopc_driver/mom_cap.F90 @@ -1,903 +1,411 @@ -!> -!! @subpage MOM NUOPC Cap -!! @author Fei Liu (fei.liu@gmail.com) -!! @date 5/10/13 Original documentation -!! @author Rocky Dunlap (rocky.dunlap@noaa.gov) -!! @date 1/12/17 Moved to doxygen -!! @date 2/28/19 Rewrote for unified cap -!! -!! @tableofcontents -!! -!! @section Overview Overview +!> This module contains a set of subroutines that are required by NUOPC. + +module MOM_cap_mod + +use constants_mod, only: constants_init +use diag_manager_mod, only: diag_manager_init, diag_manager_end +use field_manager_mod, only: field_manager_init, field_manager_end +use fms_mod, only: fms_init, fms_end, open_namelist_file, check_nml_error +use fms_mod, only: close_file, file_exist, uppercase +use fms_io_mod, only: fms_io_exit +use mpp_domains_mod, only: domain2d, mpp_get_compute_domain, mpp_get_compute_domains +use mpp_domains_mod, only: mpp_get_ntile_count, mpp_get_pelist, mpp_get_global_domain +use mpp_domains_mod, only: mpp_get_domain_npes +use mpp_io_mod, only: mpp_open, MPP_RDONLY, MPP_ASCII, MPP_OVERWR, MPP_APPEND, mpp_close, MPP_SINGLE +use mpp_mod, only: stdlog, stdout, mpp_root_pe, mpp_clock_id +use mpp_mod, only: mpp_clock_begin, mpp_clock_end, MPP_CLOCK_SYNC +use mpp_mod, only: MPP_CLOCK_DETAILED, CLOCK_COMPONENT, MAXPES +use time_interp_external_mod, only: time_interp_external_init +use time_manager_mod, only: set_calendar_type, time_type, increment_date +use time_manager_mod, only: set_time, set_date, get_time, get_date, month_name +use time_manager_mod, only: GREGORIAN, JULIAN, NOLEAP, THIRTY_DAY_MONTHS, NO_CALENDAR +use time_manager_mod, only: operator( <= ), operator( < ), operator( >= ) +use time_manager_mod, only: operator( + ), operator( - ), operator( / ) +use time_manager_mod, only: operator( * ), operator( /= ), operator( > ) +use time_manager_mod, only: date_to_string +use time_manager_mod, only: fms_get_calendar_type => get_calendar_type +use MOM_domains, only: MOM_infra_init, num_pes, root_pe, pe_here +use MOM_file_parser, only: get_param, log_version, param_file_type, close_param_file +use MOM_get_input, only: Get_MOM_Input, directories +use MOM_domains, only: pass_var +use MOM_error_handler, only: MOM_error, FATAL, is_root_pe +use MOM_ocean_model_nuopc, only: ice_ocean_boundary_type +use MOM_grid, only: ocean_grid_type, get_global_grid_size +use MOM_ocean_model_nuopc, only: ocean_model_restart, ocean_public_type, ocean_state_type +use MOM_ocean_model_nuopc, only: ocean_model_init_sfc +use MOM_ocean_model_nuopc, only: ocean_model_init, update_ocean_model, ocean_model_end +use MOM_ocean_model_nuopc, only: get_ocean_grid, get_eps_omesh +use MOM_cap_time, only: AlarmInit +use MOM_cap_methods, only: mom_import, mom_export, mom_set_geomtype +#ifdef CESMCOUPLED +use shr_file_mod, only: shr_file_setLogUnit, shr_file_getLogUnit +#endif +use time_utils_mod, only: esmf2fms_time + +use, intrinsic :: iso_fortran_env, only: output_unit + +use ESMF, only: ESMF_ClockAdvance, ESMF_ClockGet, ESMF_ClockPrint +use ESMF, only: ESMF_ClockGetAlarm, ESMF_ClockGetNextTime, ESMF_ClockAdvance +use ESMF, only: ESMF_ClockSet, ESMF_Clock, ESMF_GeomType_Flag, ESMF_LOGMSG_INFO +use ESMF, only: ESMF_Grid, ESMF_GridCreate, ESMF_GridAddCoord +use ESMF, only: ESMF_GridGetCoord, ESMF_GridAddItem, ESMF_GridGetItem +use ESMF, only: ESMF_GridComp, ESMF_GridCompSetEntryPoint, ESMF_GridCompGet +use ESMF, only: ESMF_LogFoundError, ESMF_LogWrite, ESMF_LogSetError +use ESMF, only: ESMF_LOGERR_PASSTHRU, ESMF_KIND_R8, ESMF_RC_VAL_WRONG +use ESMF, only: ESMF_GEOMTYPE_MESH, ESMF_GEOMTYPE_GRID, ESMF_SUCCESS +use ESMF, only: ESMF_METHOD_INITIALIZE, ESMF_MethodRemove, ESMF_State +use ESMF, only: ESMF_LOGMSG_INFO, ESMF_RC_ARG_BAD, ESMF_VM, ESMF_Time +use ESMF, only: ESMF_TimeInterval, ESMF_MAXSTR, ESMF_VMGetCurrent +use ESMF, only: ESMF_VMGet, ESMF_TimeGet, ESMF_TimeIntervalGet, ESMF_MeshGet +use ESMF, only: ESMF_MethodExecute, ESMF_Mesh, ESMF_DeLayout, ESMF_Distgrid +use ESMF, only: ESMF_DistGridConnection, ESMF_StateItem_Flag, ESMF_KIND_I4 +use ESMF, only: ESMF_KIND_I8, ESMF_FAILURE, ESMF_DistGridCreate, ESMF_MeshCreate +use ESMF, only: ESMF_FILEFORMAT_ESMFMESH, ESMF_DELayoutCreate, ESMF_DistGridConnectionSet +use ESMF, only: ESMF_DistGridGet, ESMF_STAGGERLOC_CORNER, ESMF_GRIDITEM_MASK +use ESMF, only: ESMF_TYPEKIND_I4, ESMF_TYPEKIND_R8, ESMF_STAGGERLOC_CENTER +use ESMF, only: ESMF_GRIDITEM_AREA, ESMF_Field, ESMF_ALARM, ESMF_VMLogMemInfo +use ESMF, only: ESMF_AlarmIsRinging, ESMF_AlarmRingerOff, ESMF_StateRemove +use ESMF, only: ESMF_FieldCreate, ESMF_LOGMSG_ERROR, ESMF_LOGMSG_WARNING +use ESMF, only: ESMF_COORDSYS_SPH_DEG, ESMF_GridCreate, ESMF_INDEX_DELOCAL +use ESMF, only: ESMF_MESHLOC_ELEMENT, ESMF_RC_VAL_OUTOFRANGE, ESMF_StateGet +use ESMF, only: ESMF_TimePrint, ESMF_AlarmSet, ESMF_FieldGet, ESMF_Array +use ESMF, only: ESMF_ArrayCreate +use ESMF, only: operator(==), operator(/=), operator(+), operator(-) + +! TODO ESMF_GridCompGetInternalState does not have an explicit Fortran interface. +!! Model does not compile with "use ESMF, only: ESMF_GridCompGetInternalState" +!! Is this okay? + +use NUOPC, only: NUOPC_CompDerive, NUOPC_CompSetEntryPoint, NUOPC_CompSpecialize +use NUOPC, only: NUOPC_CompFilterPhaseMap, NUOPC_CompAttributeGet, NUOPC_CompAttributeAdd +use NUOPC, only: NUOPC_Advertise, NUOPC_SetAttribute, NUOPC_IsUpdated, NUOPC_Write +use NUOPC, only: NUOPC_IsConnected, NUOPC_Realize, NUOPC_CompAttributeSet +use NUOPC_Model, only: NUOPC_ModelGet +use NUOPC_Model, & + model_routine_SS => SetServices, & + model_label_Advance => label_Advance, & + model_label_DataInitialize => label_DataInitialize, & + model_label_SetRunClock => label_SetRunClock, & + model_label_Finalize => label_Finalize + +implicit none; private + +public SetServices + +!> Internal state type with pointers to three types defined by MOM. +type ocean_internalstate_type + type(ocean_public_type), pointer :: ocean_public_type_ptr + type(ocean_state_type), pointer :: ocean_state_type_ptr + type(ice_ocean_boundary_type), pointer :: ice_ocean_boundary_type_ptr +end type + +!> Wrapper-derived type required to associate an internal state instance +!! with the ESMF/NUOPC component +type ocean_internalstate_wrapper + type(ocean_internalstate_type), pointer :: ptr +end type + +!> Contains field information +type fld_list_type + character(len=64) :: stdname + character(len=64) :: shortname + character(len=64) :: transferOffer +end type fld_list_type + +integer,parameter :: fldsMax = 100 +integer :: fldsToOcn_num = 0 +type (fld_list_type) :: fldsToOcn(fldsMax) +integer :: fldsFrOcn_num = 0 +type (fld_list_type) :: fldsFrOcn(fldsMax) + +integer :: debug = 0 +integer :: import_slice = 1 +integer :: export_slice = 1 +character(len=256) :: tmpstr +logical :: write_diagnostics = .false. +character(len=32) :: runtype !< run type +integer :: logunit !< stdout logging unit number +logical :: profile_memory = .true. +logical :: grid_attach_area = .false. +character(len=128) :: scalar_field_name = '' +integer :: scalar_field_count = 0 +integer :: scalar_field_idx_grid_nx = 0 +integer :: scalar_field_idx_grid_ny = 0 +character(len=*),parameter :: u_file_u = & + __FILE__ + +#ifdef CESMCOUPLED +logical :: cesm_coupled = .true. +type(ESMF_GeomType_Flag) :: geomtype = ESMF_GEOMTYPE_MESH +#else +logical :: cesm_coupled = .false. +type(ESMF_GeomType_Flag) :: geomtype = ESMF_GEOMTYPE_GRID +#endif + +contains + +!> NUOPC SetService method is the only public entry point. +!! SetServices registers all of the user-provided subroutines +!! in the module with the NUOPC layer. !! -!! **This MOM cap has been tested with MOM6.** +!! @param gcomp an ESMF_GridComp object +!! @param rc return code +subroutine SetServices(gcomp, rc) + + type(ESMF_GridComp) :: gcomp !< an ESMF_GridComp object + integer, intent(out) :: rc !< return code + + ! local variables + character(len=*),parameter :: subname='(MOM_cap:SetServices)' + + rc = ESMF_SUCCESS + + ! the NUOPC model component will register the generic methods + call NUOPC_CompDerive(gcomp, model_routine_SS, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + + ! switching to IPD versions + call ESMF_GridCompSetEntryPoint(gcomp, ESMF_METHOD_INITIALIZE, & + userRoutine=InitializeP0, phase=0, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + + ! set entry point for methods that require specific implementation + call NUOPC_CompSetEntryPoint(gcomp, ESMF_METHOD_INITIALIZE, & + phaseLabelList=(/"IPDv03p1"/), userRoutine=InitializeAdvertise, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + call NUOPC_CompSetEntryPoint(gcomp, ESMF_METHOD_INITIALIZE, & + phaseLabelList=(/"IPDv03p3"/), userRoutine=InitializeRealize, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + + !------------------ + ! attach specializing method(s) + !------------------ + + call NUOPC_CompSpecialize(gcomp, specLabel=model_label_DataInitialize, & + specRoutine=DataInitialize, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + + call NUOPC_CompSpecialize(gcomp, specLabel=model_label_Advance, & + specRoutine=ModelAdvance, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + + call ESMF_MethodRemove(gcomp, label=model_label_SetRunClock, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + call NUOPC_CompSpecialize(gcomp, specLabel=model_label_SetRunClock, & + specRoutine=ModelSetRunClock, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + + call NUOPC_CompSpecialize(gcomp, specLabel=model_label_Finalize, & + specRoutine=ocean_model_finalize, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + +end subroutine SetServices + +!> First initialize subroutine called by NUOPC. The purpose +!! is to set which version of the Initialize Phase Definition (IPD) +!! to use. !! -!! This document describes the MOM NUOPC "cap", which is a light weight software layer that is -!! required when the [MOM ocean model](https://github.com/NOAA-GFDL/MOM6/tree/dev/master) -!! is used in [National Unified Operation Prediction Capability] -!! (http://www.earthsystemcog.org/projects/nuopc) (NUOPC) coupled systems. Also see the -!! [MOM wiki](https://github.com/NOAA-GFDL/MOM6-Examples/wiki) for more documentation. +!! For this MOM cap, we are using IPDv01. !! -!! NUOPC is a software layer built on top of the [Earth System Modeling -!! Framework] (https://www.earthsystemcog.org/projects/esmf) (ESMF). -!! ESMF is a high-performance modeling framework that provides -!! data structures, interfaces, and operations suited for building coupled models -!! from a set of components. NUOPC refines the capabilities of ESMF by providing -!! a more precise definition of what it means for a model to be a component and -!! how components should interact and share data in a coupled system. The NUOPC -!! Layer software is designed to work with typical high-performance models in the -!! Earth sciences domain, most of which are written in Fortran and are based on a -!! distributed memory model of parallelism (MPI). -!! -!! A NUOPC "cap" is a Fortran module that serves as the interface to a model -!! when it's used in a NUOPC-based coupled system. -!! The term "cap" is used because it is a light weight software layer that sits on top -!! of model code, making calls into it and exposing model data structures in a -!! standard way. -!! -!! The MOM cap package includes the cap code itself (MOM_cap.F90, MOM_cap_methods.F90 -!! and MOM_cap_time.F90), a set of time utilities (time_utils.F90) for converting between ESMF and FMS -!! time type and two modules MOM_ocean_model_nuopc.F90 and MOM_surface_forcing_nuopc.F90. MOM_surface_forcing_nuopc.F90 -!! converts the input ESMF data (import data) to a MOM-specific data type (surface_forcing_CS). -!! MOM_ocean_model_nuopc.F90 contains routines for initialization, update and finalization of the ocean model state. -!! -!! @subsection CapSubroutines Cap Subroutines -!! -!! The MOM cap modules contains a set of subroutines that are required -!! by NUOPC. These subroutines are called by the NUOPC infrastructure according -!! to a predefined calling sequence. Some subroutines are called during -!! initialization of the coupled system, some during the run of the coupled -!! system, and some during finalization of the coupled system. -!! -!! The initialization sequence is the most complex and is governed by the NUOPC technical rules. -!! Details about the initialization sequence can be found in the [NUOPC Reference Manual] -!! (http://www.earthsystemmodeling.org/esmf_releases/last_built/NUOPC_refdoc/). -!! The cap requires beta snapshot ESMF v8.0.0bs16 or later. -!! -!! The following table summarizes the NUOPC-required subroutines that appear in the -!! MOM cap. The "Phase" column says whether the subroutine is called during the -!! initialization, run, or finalize part of the coupled system run. -!! -!! Phase | MOM Cap Subroutine | Description -!! ---------|--------------------------------------------------------------------|-------------------------------------- -!! Init | [InitializeP0] (@ref MOM_cap_mod::initializep0) | Sets the Initialize Phase Definition -!! | (IPD) version to use -!! Init | [InitializeAdvertise] (@ref MOM_cap_mod::initializeadvertise) | Advertises standard names of import -!! | and export fields -!! Init | [InitializeRealize] (@ref MOM_cap_mod::initializerealize) | Creates an ESMF_Grid or ESMF_Mesh -!! | as well as ESMF_Fields for import -!! | and export fields -!! Run | [ModelAdvance] (@ref MOM_cap_mod::modeladvance) | Advances the model by a timestep -!! Final | [Finalize] (@ref MOM_cap_mod::ocean_model_finalize) | Cleans up -!! -!! @section UnderlyingModelInterfaces Underlying Model Interfaces -!! -!! -!! @subsection DomainCreation Domain Creation -!! -!! The cap can accomodate a MOM tripolar grid which is represented either as a 2D `ESMF_Grid` or -!! as a 1D `ESMF_Mesh`. Other MOM grids (e.g. a bipolar grid) can be represented as a 1d `ESMF_Mesh` only. -!! Coupling fields are placed on either the `ESMF_Grid` or `ESMF_Mesh`. -!! Note that for either the `ESMF_Grid` or `ESMF_Mesh` representation, the fields are translated into -!! a 2D MOM specific surface boundary type and the distinction between the two is no longer there. -!! Calls related to creating the grid are located in the [InitializeRealize] -!! (@ref MOM_cap_mod::initializerealize) subroutine, which is called by the NUOPC infrastructure -!! during the intialization sequence. -!! -!! The cap determines parameters for setting up the grid by calling subroutines in the -!! `mpp_domains_mod` module. The global domain size is determined by calling `mpp_get_global_domain()`. -!! A check is in place to ensure that there is only a single tile in the domain (the -!! cap is currently limited to one tile; multi-tile mosaics are not supported). The -!! decomposition across processors is determined via calls to `mpp_get_compute_domains()` -!! (to retrieve decomposition block indices) and `mpp_get_pelist()` (to determine how -!! blocks are assigned to processors). -!! -!! The `ESMF_Grid` is created in several steps: -!! - an `ESMF_DELayout` is created based on the pelist from MOM -!! - an `ESMF_DistGrid` is created over the global index space. Connections are set -!! up so that the index space is periodic in the first dimension and has a -!! fold at the top for the bipole. The decompostion blocks are also passed in -!! along with the `ESMF_DELayout` mentioned above. -!! - an `ESMF_Grid` is then created by passing in the above `ESMF_DistGrid`. -!! - masks, areas, center (tlat, tlon), and corner (ulat, ulon) coordinates are then added to the `ESMF_Grid` -!! by retrieving those fields from the MOM datatype `ocean_grid` elements. -!! -!! The `ESMF_Mesh` is also created in several steps: -!! - the target mesh is generated offline. -!! - a temporary mesh is created from an input file specified by the config variable `mesh_ocn`. -!! the mesh has a distribution that is automatically generated by ESMF when reading in the mesh -!! - an `ESMF_DistGrid` is created from the global index space for the computational domain. -!! - the final `ESMF_Mesh` is then created by distributing the temporary mesh using the created `ESMF_DistGrid`. -!! -!! -!! @subsection Initialization Initialization -!! -!! During the [InitializeAdvertise] (@ref MOM_cap_mod::initializeadvertise) phase, calls are -!! made to MOM's native initialization subroutines, including `fms_init()`, `constants_init()`, -!! `field_manager_init()`, `diag_manager_init()`, and `set_calendar_type()`. The MPI communicator -!! is pulled in through the ESMF VM object for the MOM component. The dt and start time are set -!! from parameters from the incoming ESMF clock with calls to `set_time()` and `set_date().` -!! -!! -!! @subsection Run Run -!! -!! The [ModelAdvance] (@ref MOM_cap_mod::modeladvance) subroutine is called by the NUOPC -!! infrastructure when it's time for MOM to advance in time. During this subroutine, there is a -!! call into the MOM update routine: -!! -!! call update_ocean_model(Ice_ocean_boundary, Ocean_state, Ocean_public, Time, Time_step_coupled) -!! -!! Priori to the call to `update_ocean_model()`, the cap performs these steps -!! - the `Time` and `Time_step_coupled` parameters, based on FMS types, are derived from the incoming ESMF clock -!! - diagnostics are optionally written to files `field_ocn_import_*`, one for each import field -!! - mom_import is called and translates to the ESMF input data to a MOM specific data type -!! - momentum flux vectors are rotated to internal grid -!! -!! After the call to `update_ocean_model()`, the cap performs these steps: -!! - mom_export is called -!! - the `ocean_mask` export is set to match that of the internal MOM mask -!! - the `freezing_melting_potential` export is converted from J m-2 to W m-2 by dividing by the coupling interval -!! - vector rotations are applied to the `ocean_current_zonal` and `ocean_current_merid` exports, back to lat-lon grid -!! - diagnostics are optionally written to files `field_ocn_export_*`, one for each export field -!! - optionally, a call is made to `ocean_model_restart()` at the interval `restart_interval` -!! -!! @subsubsection VectorRotations Vector Rotations -!! -!! Vector rotations are applied to incoming momentum fluxes (from regular lat-lon to tripolar grid) and -!! outgoing ocean currents (from tripolar to regular lat-lon). The rotation angles are provided -!! from the native MOM grid by a call to `get_ocean_grid(Ocean_grid)`. -!! The cosine and sine of the rotation angle are: -!! -!! ocean_grid%cos_rot(i,j) -!! ocean_grid%sin_rot(i,j) -!! -!! The rotation of momentum flux from regular lat-lon to tripolar is: -!! \f[ -!! \begin{bmatrix} -!! \tau_x' \\ -!! \tau_y' -!! \end{bmatrix} = -!! \begin{bmatrix} -!! cos \theta & sin \theta \\ -!! -sin \theta & cos \theta -!! \end{bmatrix} * -!! \begin{bmatrix} -!! \tau_x \\ -!! \tau_y -!! \end{bmatrix} -!! \f] -!! -!! The rotation of ocean current from tripolar to regular lat-lon is: -!! \f[ -!! \begin{bmatrix} -!! u' \\ -!! v' -!! \end{bmatrix} = -!! \begin{bmatrix} -!! cos \theta & -sin \theta \\ -!! sin \theta & cos \theta -!! \end{bmatrix} * -!! \begin{bmatrix} -!! u \\ -!! v -!! \end{bmatrix} -!! \f] -!! @subsection Finalization Finalization -!! -!! NUOPC infrastructure calls [ocean_model_finalize] (@ref MOM_cap_mod::ocean_model_finalize) -!! at the end of the run. This subroutine is a hook to call into MOM's native shutdown -!! procedures: -!! -!! call ocean_model_end (ocean_public, ocean_State, Time) -!! call diag_manager_end(Time ) -!! call field_manager_end -!! call fms_io_exit -!! call fms_end -!! -!! @section ModelFields Model Fields -!! -!! The following tables list the import and export fields currently set up in the MOM cap. -!! -!! @subsection ImportFields Import Fields -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!!
Standard NameUnitsModel VariableDescriptionNotes
inst_pres_height_surfacePappressure of overlying sea ice and atmosphere
mass_of_overlying_sea_icekgmimass of overlying sea ice
seaice_melt_heatW m-2seaice_melt_heatsea ice and snow melt heat flux
seaice_meltkg m-2 s-1seaice_meltwater flux due to sea ice and snow melting
mean_calving_heat_flxW m-2calving_hflxheat flux, relative to 0C, of frozen land water into ocean
mean_calving_ratekg m-2 s-1calvingmass flux of frozen runoff
mean_evap_ratekg m-2 s-1q_fluxspecific humidity flux
mean_fprec_ratekg m-2 s-1fprecmass flux of frozen precip
mean_merid_moment_flxPav_fluxj-directed wind stress into ocean[vector rotation] (@ref VectorRotations) applied - lat-lon to tripolar
mean_net_lw_flxW m-2lw_fluxlong wave radiation
mean_net_sw_ir_dif_flxW m-2sw_flux_nir_difdiffuse near IR shortwave radiation
mean_net_sw_ir_dir_flxW m-2sw_flux_nir_dirdirect near IR shortwave radiation
mean_net_sw_vis_dif_flxW m-2sw_flux_vis_difdiffuse visible shortware radiation
mean_net_sw_vis_dir_flxW m-2sw_flux_vis_dirdirect visible shortware radiation
mean_prec_ratekg m-2 s-1lprecmass flux of liquid precip
mean_runoff_heat_flxW m-2runoff_hflxheat flux, relative to 0C, of liquid land water into ocean
mean_runoff_ratekg m-2 s-1runoffmass flux of liquid runoff
mean_salt_ratekg m-2 s-1salt_fluxsalt flux
mean_sensi_heat_flxW m-2t_fluxsensible heat flux into ocean
mean_zonal_moment_flxPau_fluxi-directed wind stress into ocean[vector rotation] (@ref VectorRotations) applied - lat-lon to tripolar
-!! -!! @subsection ExportField Export Fields -!! -!! Export fields are populated from the `ocean_public` parameter (type `ocean_public_type`) -!! after the call to `update_ocean_model()`. -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!! -!!
Standard NameUnitsModel VariableDescriptionNotes
freezing_melting_potentialW m-2combination of frazil and melt_potentialcap converts model units (J m-2) to (W m-2) for export
ocean_maskocean mask
ocn_current_meridm s-1v_surfj-directed surface velocity on u-cell[vector rotation] (@ref VectorRotations) applied - tripolar to lat-lon
ocn_current_zonalm s-1u_surfi-directed surface velocity on u-cell[vector rotation] (@ref VectorRotations) applied - tripolar to lat-lon
s_surfpsus_surfsea surface salinity on t-cell
sea_surface_temperatureKt_surfsea surface temperature on t-cell
sea_surface_slope_zonalunitlesscreated from sshsea surface zonal slope
sea_surface_slope_meridunitlesscreated from sshsea surface meridional slope
so_bldepthmobldocean surface boundary layer depth
-!! -!! @subsection MemoryManagement Memory Management -!! -!! The MOM cap has an internal state type with pointers to three -!! types defined by MOM. There is also a small wrapper derived type -!! required to associate an internal state instance -!! with the ESMF/NUOPC component: -!! -!! type ocean_internalstate_type -!! type(ocean_public_type), pointer :: ocean_public_type_ptr -!! type(ocean_state_type), pointer :: ocean_state_type_ptr -!! type(ice_ocean_boundary_type), pointer :: ice_ocean_boundary_type_ptr -!! end type -!! -!! type ocean_internalstate_wrapper -!! type(ocean_internalstate_type), pointer :: ptr -!! end type -!! -!! The member of type `ocean_public_type` stores ocean surface fields used during the coupling. -!! The member of type `ocean_state_type` is required by the ocean driver, -!! although its internals are private (not to be used by the coupling directly). -!! This type is passed to the ocean init and update routines -!! so that it can maintain state there if desired. -!! The member of type `ice_ocean_boundary_type` is populated by this cap -!! with incoming coupling fields from other components. These three derived types are allocated during the -!! [InitializeAdvertise] (@ref MOM_cap_mod::initializeadvertise) phase. Also during that -!! phase, the `ice_ocean_boundary` type members are all allocated using bounds retrieved -!! from `mpp_get_compute_domain()`. -!! -!! During the [InitializeRealize] (@ref MOM_cap_mod::initializerealize) phase, -!! `ESMF_Field`s are created for each of the coupling fields in the `ice_ocean_boundary` -!! and `ocean_public_type` members of the internal state. These fields directly reference into the members of -!! the `ice_ocean_boundary` and `ocean_public_type` so that memory-to-memory copies are not required to move -!! data from the cap's import and export states to the memory areas used internally -!! by MOM. -!! -!! @subsection IO I/O -!! -!! The cap can optionally output coupling fields for diagnostic purposes if the ESMF attribute -!! "DumpFields" has been set to "true". In this case the cap will write out NetCDF files -!! with names "field_ocn_import_.nc" and "field_ocn_export_.nc". -!! Additionally, calls will be made to the cap subroutine [dumpMomInternal] -!! (@ref MOM_cap_mod::dumpmominternal) to write out model internal fields to files -!! named "field_ocn_internal_.nc". In all cases these NetCDF files will -!! contain a time series of field data. -!! -!! @section RuntimeConfiguration Runtime Configuration -!! -!! At runtime, the MOM cap can be configured with several options provided -!! as ESMF attributes. Attributes can be set in the cap by the NUOPC Driver -!! above this cap, or in some systems ESMF attributes are set by -!! reading in from a configuration file. The available attributes are: -!! -!! * `DumpFields` - when set to "true", write out diagnostic NetCDF files for import/export/internal fields -!! * `ProfileMemory` - when set to "true", write out memory usage information to the ESMF log files; this -!! information is written when entering and leaving the [ModelAdvance] -!! (@ref MOM_cap_mod::modeladvance) subroutine and before and after the call to -!! `update_ocean_model()`. -!! * `restart_interval` - integer number of seconds indicating the interval at -!! which to call `ocean_model_restart()`; no restarts written if set to 0 -!! -!! - -!> This module contains a set of subroutines that are required by NUOPC. -module MOM_cap_mod -use constants_mod, only: constants_init -use diag_manager_mod, only: diag_manager_init, diag_manager_end -use field_manager_mod, only: field_manager_init, field_manager_end -use fms_mod, only: fms_init, fms_end, open_namelist_file, check_nml_error -use fms_mod, only: close_file, file_exist, uppercase -use fms_io_mod, only: fms_io_exit -use mpp_domains_mod, only: domain2d, mpp_get_compute_domain, mpp_get_compute_domains -use mpp_domains_mod, only: mpp_get_ntile_count, mpp_get_pelist, mpp_get_global_domain -use mpp_domains_mod, only: mpp_get_domain_npes -use mpp_io_mod, only: mpp_open, MPP_RDONLY, MPP_ASCII, MPP_OVERWR, MPP_APPEND, mpp_close, MPP_SINGLE -use mpp_mod, only: stdlog, stdout, mpp_root_pe, mpp_clock_id -use mpp_mod, only: mpp_clock_begin, mpp_clock_end, MPP_CLOCK_SYNC -use mpp_mod, only: MPP_CLOCK_DETAILED, CLOCK_COMPONENT, MAXPES -use time_interp_external_mod, only: time_interp_external_init -use time_manager_mod, only: set_calendar_type, time_type, increment_date -use time_manager_mod, only: set_time, set_date, get_time, get_date, month_name -use time_manager_mod, only: GREGORIAN, JULIAN, NOLEAP, THIRTY_DAY_MONTHS, NO_CALENDAR -use time_manager_mod, only: operator( <= ), operator( < ), operator( >= ) -use time_manager_mod, only: operator( + ), operator( - ), operator( / ) -use time_manager_mod, only: operator( * ), operator( /= ), operator( > ) -use time_manager_mod, only: date_to_string -use time_manager_mod, only: fms_get_calendar_type => get_calendar_type -use MOM_domains, only: MOM_infra_init, num_pes, root_pe, pe_here -use MOM_file_parser, only: get_param, log_version, param_file_type, close_param_file -use MOM_get_input, only: Get_MOM_Input, directories -use MOM_domains, only: pass_var -use MOM_error_handler, only: MOM_error, FATAL, is_root_pe -use MOM_ocean_model_nuopc, only: ice_ocean_boundary_type -use MOM_grid, only: ocean_grid_type, get_global_grid_size -use MOM_ocean_model_nuopc, only: ocean_model_restart, ocean_public_type, ocean_state_type -use MOM_ocean_model_nuopc, only: ocean_model_init_sfc -use MOM_ocean_model_nuopc, only: ocean_model_init, update_ocean_model, ocean_model_end -use MOM_ocean_model_nuopc, only: get_ocean_grid, get_eps_omesh -use MOM_cap_time, only: AlarmInit -use MOM_cap_methods, only: mom_import, mom_export, mom_set_geomtype -#ifdef CESMCOUPLED -use shr_file_mod, only: shr_file_setLogUnit, shr_file_getLogUnit -#endif -use time_utils_mod, only: esmf2fms_time - -use, intrinsic :: iso_fortran_env, only: output_unit - -use ESMF, only: ESMF_ClockAdvance, ESMF_ClockGet, ESMF_ClockPrint -use ESMF, only: ESMF_ClockGetAlarm, ESMF_ClockGetNextTime, ESMF_ClockAdvance -use ESMF, only: ESMF_ClockSet, ESMF_Clock, ESMF_GeomType_Flag, ESMF_LOGMSG_INFO -use ESMF, only: ESMF_Grid, ESMF_GridCreate, ESMF_GridAddCoord -use ESMF, only: ESMF_GridGetCoord, ESMF_GridAddItem, ESMF_GridGetItem -use ESMF, only: ESMF_GridComp, ESMF_GridCompSetEntryPoint, ESMF_GridCompGet -use ESMF, only: ESMF_LogFoundError, ESMF_LogWrite, ESMF_LogSetError -use ESMF, only: ESMF_LOGERR_PASSTHRU, ESMF_KIND_R8, ESMF_RC_VAL_WRONG -use ESMF, only: ESMF_GEOMTYPE_MESH, ESMF_GEOMTYPE_GRID, ESMF_SUCCESS -use ESMF, only: ESMF_METHOD_INITIALIZE, ESMF_MethodRemove, ESMF_State -use ESMF, only: ESMF_LOGMSG_INFO, ESMF_RC_ARG_BAD, ESMF_VM, ESMF_Time -use ESMF, only: ESMF_TimeInterval, ESMF_MAXSTR, ESMF_VMGetCurrent -use ESMF, only: ESMF_VMGet, ESMF_TimeGet, ESMF_TimeIntervalGet, ESMF_MeshGet -use ESMF, only: ESMF_MethodExecute, ESMF_Mesh, ESMF_DeLayout, ESMF_Distgrid -use ESMF, only: ESMF_DistGridConnection, ESMF_StateItem_Flag, ESMF_KIND_I4 -use ESMF, only: ESMF_KIND_I8, ESMF_FAILURE, ESMF_DistGridCreate, ESMF_MeshCreate -use ESMF, only: ESMF_FILEFORMAT_ESMFMESH, ESMF_DELayoutCreate, ESMF_DistGridConnectionSet -use ESMF, only: ESMF_DistGridGet, ESMF_STAGGERLOC_CORNER, ESMF_GRIDITEM_MASK -use ESMF, only: ESMF_TYPEKIND_I4, ESMF_TYPEKIND_R8, ESMF_STAGGERLOC_CENTER -use ESMF, only: ESMF_GRIDITEM_AREA, ESMF_Field, ESMF_ALARM, ESMF_VMLogMemInfo -use ESMF, only: ESMF_AlarmIsRinging, ESMF_AlarmRingerOff, ESMF_StateRemove -use ESMF, only: ESMF_FieldCreate, ESMF_LOGMSG_ERROR, ESMF_LOGMSG_WARNING -use ESMF, only: ESMF_COORDSYS_SPH_DEG, ESMF_GridCreate, ESMF_INDEX_DELOCAL -use ESMF, only: ESMF_MESHLOC_ELEMENT, ESMF_RC_VAL_OUTOFRANGE, ESMF_StateGet -use ESMF, only: ESMF_TimePrint, ESMF_AlarmSet, ESMF_FieldGet, ESMF_Array -use ESMF, only: ESMF_ArrayCreate -use ESMF, only: operator(==), operator(/=), operator(+), operator(-) - -! TODO ESMF_GridCompGetInternalState does not have an explicit Fortran interface. -!! Model does not compile with "use ESMF, only: ESMF_GridCompGetInternalState" -!! Is this okay? - -use NUOPC, only: NUOPC_CompDerive, NUOPC_CompSetEntryPoint, NUOPC_CompSpecialize -use NUOPC, only: NUOPC_CompFilterPhaseMap, NUOPC_CompAttributeGet, NUOPC_CompAttributeAdd -use NUOPC, only: NUOPC_Advertise, NUOPC_SetAttribute, NUOPC_IsUpdated, NUOPC_Write -use NUOPC, only: NUOPC_IsConnected, NUOPC_Realize, NUOPC_CompAttributeSet -use NUOPC_Model, only: NUOPC_ModelGet -use NUOPC_Model, & - model_routine_SS => SetServices, & - model_label_Advance => label_Advance, & - model_label_DataInitialize => label_DataInitialize, & - model_label_SetRunClock => label_SetRunClock, & - model_label_Finalize => label_Finalize - -implicit none; private - -public SetServices - -!> Internal state type with pointers to three types defined by MOM. -type ocean_internalstate_type - type(ocean_public_type), pointer :: ocean_public_type_ptr - type(ocean_state_type), pointer :: ocean_state_type_ptr - type(ice_ocean_boundary_type), pointer :: ice_ocean_boundary_type_ptr -end type - -!> Wrapper-derived type required to associate an internal state instance -!! with the ESMF/NUOPC component -type ocean_internalstate_wrapper - type(ocean_internalstate_type), pointer :: ptr -end type - -!> Contains field information -type fld_list_type - character(len=64) :: stdname - character(len=64) :: shortname - character(len=64) :: transferOffer -end type fld_list_type - -integer,parameter :: fldsMax = 100 -integer :: fldsToOcn_num = 0 -type (fld_list_type) :: fldsToOcn(fldsMax) -integer :: fldsFrOcn_num = 0 -type (fld_list_type) :: fldsFrOcn(fldsMax) - -integer :: debug = 0 -integer :: import_slice = 1 -integer :: export_slice = 1 -character(len=256) :: tmpstr -logical :: write_diagnostics = .false. -character(len=32) :: runtype !< run type -integer :: logunit !< stdout logging unit number -logical :: profile_memory = .true. -logical :: grid_attach_area = .false. -character(len=128) :: scalar_field_name = '' -integer :: scalar_field_count = 0 -integer :: scalar_field_idx_grid_nx = 0 -integer :: scalar_field_idx_grid_ny = 0 -character(len=*),parameter :: u_file_u = & - __FILE__ - -#ifdef CESMCOUPLED -logical :: cesm_coupled = .true. -type(ESMF_GeomType_Flag) :: geomtype = ESMF_GEOMTYPE_MESH -#else -logical :: cesm_coupled = .false. -type(ESMF_GeomType_Flag) :: geomtype = ESMF_GEOMTYPE_GRID -#endif - -contains - -!> NUOPC SetService method is the only public entry point. -!! SetServices registers all of the user-provided subroutines -!! in the module with the NUOPC layer. -!! -!! @param gcomp an ESMF_GridComp object -!! @param rc return code -subroutine SetServices(gcomp, rc) - - type(ESMF_GridComp) :: gcomp !< an ESMF_GridComp object - integer, intent(out) :: rc !< return code - - ! local variables - character(len=*),parameter :: subname='(MOM_cap:SetServices)' - - rc = ESMF_SUCCESS - - ! the NUOPC model component will register the generic methods - call NUOPC_CompDerive(gcomp, model_routine_SS, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=__FILE__)) & - return ! bail out - - ! switching to IPD versions - call ESMF_GridCompSetEntryPoint(gcomp, ESMF_METHOD_INITIALIZE, & - userRoutine=InitializeP0, phase=0, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=__FILE__)) & - return ! bail out - - ! set entry point for methods that require specific implementation - call NUOPC_CompSetEntryPoint(gcomp, ESMF_METHOD_INITIALIZE, & - phaseLabelList=(/"IPDv03p1"/), userRoutine=InitializeAdvertise, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=__FILE__)) & - return ! bail out - call NUOPC_CompSetEntryPoint(gcomp, ESMF_METHOD_INITIALIZE, & - phaseLabelList=(/"IPDv03p3"/), userRoutine=InitializeRealize, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=__FILE__)) & - return ! bail out - - !------------------ - ! attach specializing method(s) - !------------------ - - call NUOPC_CompSpecialize(gcomp, specLabel=model_label_DataInitialize, & - specRoutine=DataInitialize, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=__FILE__)) & - return ! bail out - - call NUOPC_CompSpecialize(gcomp, specLabel=model_label_Advance, & - specRoutine=ModelAdvance, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=__FILE__)) & - return ! bail out - - call ESMF_MethodRemove(gcomp, label=model_label_SetRunClock, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=__FILE__)) & - return ! bail out - call NUOPC_CompSpecialize(gcomp, specLabel=model_label_SetRunClock, & - specRoutine=ModelSetRunClock, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=__FILE__)) & - return ! bail out - - call NUOPC_CompSpecialize(gcomp, specLabel=model_label_Finalize, & - specRoutine=ocean_model_finalize, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=__FILE__)) & - return ! bail out - -end subroutine SetServices - -!> First initialize subroutine called by NUOPC. The purpose -!! is to set which version of the Initialize Phase Definition (IPD) -!! to use. -!! -!! For this MOM cap, we are using IPDv01. -!! -!! @param gcomp an ESMF_GridComp object -!! @param importState an ESMF_State object for import fields -!! @param exportState an ESMF_State object for export fields -!! @param clock an ESMF_Clock object -!! @param rc return code -subroutine InitializeP0(gcomp, importState, exportState, clock, rc) - type(ESMF_GridComp) :: gcomp !< ESMF_GridComp object - type(ESMF_State) :: importState, exportState !< ESMF_State object for - !! import/export fields - type(ESMF_Clock) :: clock !< ESMF_Clock object - integer, intent(out) :: rc !< return code - - ! local variables - logical :: isPresent, isSet - integer :: iostat - character(len=64) :: value, logmsg - character(len=*),parameter :: subname='(MOM_cap:InitializeP0)' - - rc = ESMF_SUCCESS - - ! Switch to IPDv03 by filtering all other phaseMap entries - call NUOPC_CompFilterPhaseMap(gcomp, ESMF_METHOD_INITIALIZE, & - acceptStringList=(/"IPDv03p"/), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=__FILE__)) & - return - - write_diagnostics = .false. - call NUOPC_CompAttributeGet(gcomp, name="DumpFields", value=value, & - isPresent=isPresent, isSet=isSet, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=__FILE__)) & - return - if (isPresent .and. isSet) write_diagnostics=(trim(value)=="true") - - write(logmsg,*) write_diagnostics - call ESMF_LogWrite('MOM_cap:DumpFields = '//trim(logmsg), ESMF_LOGMSG_INFO, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=__FILE__)) & - return - - profile_memory = .false. - call NUOPC_CompAttributeGet(gcomp, name="ProfileMemory", value=value, & - isPresent=isPresent, isSet=isSet, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=__FILE__)) & - return - if (isPresent .and. isSet) profile_memory=(trim(value)=="true") - write(logmsg,*) profile_memory - call ESMF_LogWrite('MOM_cap:ProfileMemory = '//trim(logmsg), ESMF_LOGMSG_INFO, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=__FILE__)) & - return - - grid_attach_area = .false. - call NUOPC_CompAttributeGet(gcomp, name="GridAttachArea", value=value, & - isPresent=isPresent, isSet=isSet, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=__FILE__)) & - return - if (isPresent .and. isSet) grid_attach_area=(trim(value)=="true") - write(logmsg,*) grid_attach_area - call ESMF_LogWrite('MOM_cap:GridAttachArea = '//trim(logmsg), ESMF_LOGMSG_INFO, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=__FILE__)) & - return - - scalar_field_name = "" - call NUOPC_CompAttributeGet(gcomp, name="ScalarFieldName", value=value, & - isPresent=isPresent, isSet=isSet, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=__FILE__)) & - return - if (isPresent .and. isSet) then - scalar_field_name = trim(value) - call ESMF_LogWrite('MOM_cap:ScalarFieldName = '//trim(scalar_field_name), ESMF_LOGMSG_INFO, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=__FILE__)) & - return - endif - - scalar_field_count = 0 - call NUOPC_CompAttributeGet(gcomp, name="ScalarFieldCount", value=value, & - isPresent=isPresent, isSet=isSet, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=__FILE__)) & - return - if (isPresent .and. isSet) then - read(value, '(i)', iostat=iostat) scalar_field_count - if (iostat /= 0) then - call ESMF_LogSetError(ESMF_RC_ARG_BAD, & - msg=subname//": ScalarFieldCount not an integer: "//trim(value), & - line=__LINE__, file=__FILE__, rcToReturn=rc) - return - endif - write(logmsg,*) scalar_field_count - call ESMF_LogWrite('MOM_cap:ScalarFieldCount = '//trim(logmsg), ESMF_LOGMSG_INFO, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=__FILE__)) & - return - endif - - scalar_field_idx_grid_nx = 0 - call NUOPC_CompAttributeGet(gcomp, name="ScalarFieldIdxGridNX", value=value, & - isPresent=isPresent, isSet=isSet, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=__FILE__)) & - return - if (isPresent .and. isSet) then - read(value, '(i)', iostat=iostat) scalar_field_idx_grid_nx - if (iostat /= 0) then - call ESMF_LogSetError(ESMF_RC_ARG_BAD, & - msg=subname//": ScalarFieldIdxGridNX not an integer: "//trim(value), & - line=__LINE__, file=__FILE__, rcToReturn=rc) - return - endif - write(logmsg,*) scalar_field_idx_grid_nx - call ESMF_LogWrite('MOM_cap:ScalarFieldIdxGridNX = '//trim(logmsg), ESMF_LOGMSG_INFO, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=__FILE__)) & - return - endif - - scalar_field_idx_grid_ny = 0 - call NUOPC_CompAttributeGet(gcomp, name="ScalarFieldIdxGridNY", value=value, & - isPresent=isPresent, isSet=isSet, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=__FILE__)) & - return - if (isPresent .and. isSet) then - read(value, '(i)', iostat=iostat) scalar_field_idx_grid_ny - if (iostat /= 0) then - call ESMF_LogSetError(ESMF_RC_ARG_BAD, & - msg=subname//": ScalarFieldIdxGridNY not an integer: "//trim(value), & - line=__LINE__, file=__FILE__, rcToReturn=rc) - return - endif - write(logmsg,*) scalar_field_idx_grid_ny - call ESMF_LogWrite('MOM_cap:ScalarFieldIdxGridNY = '//trim(logmsg), ESMF_LOGMSG_INFO, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=__FILE__)) & - return - endif - - call NUOPC_CompAttributeAdd(gcomp, & - attrList=(/'RestartFileToRead', 'RestartFileToWrite'/), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=__FILE__)) & - return - -end subroutine - -!> Called by NUOPC to advertise import and export fields. "Advertise" -!! simply means that the standard names of all import and export -!! fields are supplied. The NUOPC layer uses these to match fields -!! between components in the coupled system. +!! @param gcomp an ESMF_GridComp object +!! @param importState an ESMF_State object for import fields +!! @param exportState an ESMF_State object for export fields +!! @param clock an ESMF_Clock object +!! @param rc return code +subroutine InitializeP0(gcomp, importState, exportState, clock, rc) + type(ESMF_GridComp) :: gcomp !< ESMF_GridComp object + type(ESMF_State) :: importState, exportState !< ESMF_State object for + !! import/export fields + type(ESMF_Clock) :: clock !< ESMF_Clock object + integer, intent(out) :: rc !< return code + + ! local variables + logical :: isPresent, isSet + integer :: iostat + character(len=64) :: value, logmsg + character(len=*),parameter :: subname='(MOM_cap:InitializeP0)' + + rc = ESMF_SUCCESS + + ! Switch to IPDv03 by filtering all other phaseMap entries + call NUOPC_CompFilterPhaseMap(gcomp, ESMF_METHOD_INITIALIZE, & + acceptStringList=(/"IPDv03p"/), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return + + write_diagnostics = .false. + call NUOPC_CompAttributeGet(gcomp, name="DumpFields", value=value, & + isPresent=isPresent, isSet=isSet, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return + if (isPresent .and. isSet) write_diagnostics=(trim(value)=="true") + + write(logmsg,*) write_diagnostics + call ESMF_LogWrite('MOM_cap:DumpFields = '//trim(logmsg), ESMF_LOGMSG_INFO, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return + + profile_memory = .false. + call NUOPC_CompAttributeGet(gcomp, name="ProfileMemory", value=value, & + isPresent=isPresent, isSet=isSet, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return + if (isPresent .and. isSet) profile_memory=(trim(value)=="true") + write(logmsg,*) profile_memory + call ESMF_LogWrite('MOM_cap:ProfileMemory = '//trim(logmsg), ESMF_LOGMSG_INFO, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return + + grid_attach_area = .false. + call NUOPC_CompAttributeGet(gcomp, name="GridAttachArea", value=value, & + isPresent=isPresent, isSet=isSet, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return + if (isPresent .and. isSet) grid_attach_area=(trim(value)=="true") + write(logmsg,*) grid_attach_area + call ESMF_LogWrite('MOM_cap:GridAttachArea = '//trim(logmsg), ESMF_LOGMSG_INFO, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return + + scalar_field_name = "" + call NUOPC_CompAttributeGet(gcomp, name="ScalarFieldName", value=value, & + isPresent=isPresent, isSet=isSet, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return + if (isPresent .and. isSet) then + scalar_field_name = trim(value) + call ESMF_LogWrite('MOM_cap:ScalarFieldName = '//trim(scalar_field_name), ESMF_LOGMSG_INFO, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return + endif + + scalar_field_count = 0 + call NUOPC_CompAttributeGet(gcomp, name="ScalarFieldCount", value=value, & + isPresent=isPresent, isSet=isSet, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return + if (isPresent .and. isSet) then + read(value, '(i)', iostat=iostat) scalar_field_count + if (iostat /= 0) then + call ESMF_LogSetError(ESMF_RC_ARG_BAD, & + msg=subname//": ScalarFieldCount not an integer: "//trim(value), & + line=__LINE__, file=__FILE__, rcToReturn=rc) + return + endif + write(logmsg,*) scalar_field_count + call ESMF_LogWrite('MOM_cap:ScalarFieldCount = '//trim(logmsg), ESMF_LOGMSG_INFO, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return + endif + + scalar_field_idx_grid_nx = 0 + call NUOPC_CompAttributeGet(gcomp, name="ScalarFieldIdxGridNX", value=value, & + isPresent=isPresent, isSet=isSet, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return + if (isPresent .and. isSet) then + read(value, '(i)', iostat=iostat) scalar_field_idx_grid_nx + if (iostat /= 0) then + call ESMF_LogSetError(ESMF_RC_ARG_BAD, & + msg=subname//": ScalarFieldIdxGridNX not an integer: "//trim(value), & + line=__LINE__, file=__FILE__, rcToReturn=rc) + return + endif + write(logmsg,*) scalar_field_idx_grid_nx + call ESMF_LogWrite('MOM_cap:ScalarFieldIdxGridNX = '//trim(logmsg), ESMF_LOGMSG_INFO, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return + endif + + scalar_field_idx_grid_ny = 0 + call NUOPC_CompAttributeGet(gcomp, name="ScalarFieldIdxGridNY", value=value, & + isPresent=isPresent, isSet=isSet, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return + if (isPresent .and. isSet) then + read(value, '(i)', iostat=iostat) scalar_field_idx_grid_ny + if (iostat /= 0) then + call ESMF_LogSetError(ESMF_RC_ARG_BAD, & + msg=subname//": ScalarFieldIdxGridNY not an integer: "//trim(value), & + line=__LINE__, file=__FILE__, rcToReturn=rc) + return + endif + write(logmsg,*) scalar_field_idx_grid_ny + call ESMF_LogWrite('MOM_cap:ScalarFieldIdxGridNY = '//trim(logmsg), ESMF_LOGMSG_INFO, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return + endif + + call NUOPC_CompAttributeAdd(gcomp, & + attrList=(/'RestartFileToRead', 'RestartFileToWrite'/), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return + +end subroutine + +!> Called by NUOPC to advertise import and export fields. "Advertise" +!! simply means that the standard names of all import and export +!! fields are supplied. The NUOPC layer uses these to match fields +!! between components in the coupled system. !! !! @param gcomp an ESMF_GridComp object !! @param importState an ESMF_State object for import fields @@ -2816,4 +2324,496 @@ subroutine shr_file_getLogUnit(nunit) end subroutine shr_file_getLogUnit #endif +!> +!! @subpage MOM NUOPC Cap +!! @author Fei Liu (fei.liu@gmail.com) +!! @date 5/10/13 Original documentation +!! @author Rocky Dunlap (rocky.dunlap@noaa.gov) +!! @date 1/12/17 Moved to doxygen +!! @date 2/28/19 Rewrote for unified cap +!! +!! @tableofcontents +!! +!! @section Overview Overview +!! +!! **This MOM cap has been tested with MOM6.** +!! +!! This document describes the MOM NUOPC "cap", which is a light weight software layer that is +!! required when the [MOM ocean model](https://github.com/NOAA-GFDL/MOM6/tree/dev/master) +!! is used in [National Unified Operation Prediction Capability] +!! (http://www.earthsystemcog.org/projects/nuopc) (NUOPC) coupled systems. Also see the +!! [MOM wiki](https://github.com/NOAA-GFDL/MOM6-Examples/wiki) for more documentation. +!! +!! NUOPC is a software layer built on top of the [Earth System Modeling +!! Framework] (https://www.earthsystemcog.org/projects/esmf) (ESMF). +!! ESMF is a high-performance modeling framework that provides +!! data structures, interfaces, and operations suited for building coupled models +!! from a set of components. NUOPC refines the capabilities of ESMF by providing +!! a more precise definition of what it means for a model to be a component and +!! how components should interact and share data in a coupled system. The NUOPC +!! Layer software is designed to work with typical high-performance models in the +!! Earth sciences domain, most of which are written in Fortran and are based on a +!! distributed memory model of parallelism (MPI). +!! +!! A NUOPC "cap" is a Fortran module that serves as the interface to a model +!! when it's used in a NUOPC-based coupled system. +!! The term "cap" is used because it is a light weight software layer that sits on top +!! of model code, making calls into it and exposing model data structures in a +!! standard way. +!! +!! The MOM cap package includes the cap code itself (MOM_cap.F90, MOM_cap_methods.F90 +!! and MOM_cap_time.F90), a set of time utilities (time_utils.F90) for converting between ESMF and FMS +!! time type and two modules MOM_ocean_model_nuopc.F90 and MOM_surface_forcing_nuopc.F90. MOM_surface_forcing_nuopc.F90 +!! converts the input ESMF data (import data) to a MOM-specific data type (surface_forcing_CS). +!! MOM_ocean_model_nuopc.F90 contains routines for initialization, update and finalization of the ocean model state. +!! +!! @subsection CapSubroutines Cap Subroutines +!! +!! The MOM cap modules contains a set of subroutines that are required +!! by NUOPC. These subroutines are called by the NUOPC infrastructure according +!! to a predefined calling sequence. Some subroutines are called during +!! initialization of the coupled system, some during the run of the coupled +!! system, and some during finalization of the coupled system. +!! +!! The initialization sequence is the most complex and is governed by the NUOPC technical rules. +!! Details about the initialization sequence can be found in the [NUOPC Reference Manual] +!! (http://www.earthsystemmodeling.org/esmf_releases/last_built/NUOPC_refdoc/). +!! The cap requires beta snapshot ESMF v8.0.0bs16 or later. +!! +!! The following table summarizes the NUOPC-required subroutines that appear in the +!! MOM cap. The "Phase" column says whether the subroutine is called during the +!! initialization, run, or finalize part of the coupled system run. +!! +!! Phase | MOM Cap Subroutine | Description +!! ---------|--------------------------------------------------------------------|-------------------------------------- +!! Init | [InitializeP0] (@ref MOM_cap_mod::initializep0) | Sets the Initialize Phase Definition +!! | (IPD) version to use +!! Init | [InitializeAdvertise] (@ref MOM_cap_mod::initializeadvertise) | Advertises standard names of import +!! | and export fields +!! Init | [InitializeRealize] (@ref MOM_cap_mod::initializerealize) | Creates an ESMF_Grid or ESMF_Mesh +!! | as well as ESMF_Fields for import +!! | and export fields +!! Run | [ModelAdvance] (@ref MOM_cap_mod::modeladvance) | Advances the model by a timestep +!! Final | [Finalize] (@ref MOM_cap_mod::ocean_model_finalize) | Cleans up +!! +!! @section UnderlyingModelInterfaces Underlying Model Interfaces +!! +!! +!! @subsection DomainCreation Domain Creation +!! +!! The cap can accomodate a MOM tripolar grid which is represented either as a 2D `ESMF_Grid` or +!! as a 1D `ESMF_Mesh`. Other MOM grids (e.g. a bipolar grid) can be represented as a 1d `ESMF_Mesh` only. +!! Coupling fields are placed on either the `ESMF_Grid` or `ESMF_Mesh`. +!! Note that for either the `ESMF_Grid` or `ESMF_Mesh` representation, the fields are translated into +!! a 2D MOM specific surface boundary type and the distinction between the two is no longer there. +!! Calls related to creating the grid are located in the [InitializeRealize] +!! (@ref MOM_cap_mod::initializerealize) subroutine, which is called by the NUOPC infrastructure +!! during the intialization sequence. +!! +!! The cap determines parameters for setting up the grid by calling subroutines in the +!! `mpp_domains_mod` module. The global domain size is determined by calling `mpp_get_global_domain()`. +!! A check is in place to ensure that there is only a single tile in the domain (the +!! cap is currently limited to one tile; multi-tile mosaics are not supported). The +!! decomposition across processors is determined via calls to `mpp_get_compute_domains()` +!! (to retrieve decomposition block indices) and `mpp_get_pelist()` (to determine how +!! blocks are assigned to processors). +!! +!! The `ESMF_Grid` is created in several steps: +!! - an `ESMF_DELayout` is created based on the pelist from MOM +!! - an `ESMF_DistGrid` is created over the global index space. Connections are set +!! up so that the index space is periodic in the first dimension and has a +!! fold at the top for the bipole. The decompostion blocks are also passed in +!! along with the `ESMF_DELayout` mentioned above. +!! - an `ESMF_Grid` is then created by passing in the above `ESMF_DistGrid`. +!! - masks, areas, center (tlat, tlon), and corner (ulat, ulon) coordinates are then added to the `ESMF_Grid` +!! by retrieving those fields from the MOM datatype `ocean_grid` elements. +!! +!! The `ESMF_Mesh` is also created in several steps: +!! - the target mesh is generated offline. +!! - a temporary mesh is created from an input file specified by the config variable `mesh_ocn`. +!! the mesh has a distribution that is automatically generated by ESMF when reading in the mesh +!! - an `ESMF_DistGrid` is created from the global index space for the computational domain. +!! - the final `ESMF_Mesh` is then created by distributing the temporary mesh using the created `ESMF_DistGrid`. +!! +!! +!! @subsection Initialization Initialization +!! +!! During the [InitializeAdvertise] (@ref MOM_cap_mod::initializeadvertise) phase, calls are +!! made to MOM's native initialization subroutines, including `fms_init()`, `constants_init()`, +!! `field_manager_init()`, `diag_manager_init()`, and `set_calendar_type()`. The MPI communicator +!! is pulled in through the ESMF VM object for the MOM component. The dt and start time are set +!! from parameters from the incoming ESMF clock with calls to `set_time()` and `set_date().` +!! +!! +!! @subsection Run Run +!! +!! The [ModelAdvance] (@ref MOM_cap_mod::modeladvance) subroutine is called by the NUOPC +!! infrastructure when it's time for MOM to advance in time. During this subroutine, there is a +!! call into the MOM update routine: +!! +!! call update_ocean_model(Ice_ocean_boundary, Ocean_state, Ocean_public, Time, Time_step_coupled) +!! +!! Priori to the call to `update_ocean_model()`, the cap performs these steps +!! - the `Time` and `Time_step_coupled` parameters, based on FMS types, are derived from the incoming ESMF clock +!! - diagnostics are optionally written to files `field_ocn_import_*`, one for each import field +!! - mom_import is called and translates to the ESMF input data to a MOM specific data type +!! - momentum flux vectors are rotated to internal grid +!! +!! After the call to `update_ocean_model()`, the cap performs these steps: +!! - mom_export is called +!! - the `ocean_mask` export is set to match that of the internal MOM mask +!! - the `freezing_melting_potential` export is converted from J m-2 to W m-2 by dividing by the coupling interval +!! - vector rotations are applied to the `ocean_current_zonal` and `ocean_current_merid` exports, back to lat-lon grid +!! - diagnostics are optionally written to files `field_ocn_export_*`, one for each export field +!! - optionally, a call is made to `ocean_model_restart()` at the interval `restart_interval` +!! +!! @subsubsection VectorRotations Vector Rotations +!! +!! Vector rotations are applied to incoming momentum fluxes (from regular lat-lon to tripolar grid) and +!! outgoing ocean currents (from tripolar to regular lat-lon). The rotation angles are provided +!! from the native MOM grid by a call to `get_ocean_grid(Ocean_grid)`. +!! The cosine and sine of the rotation angle are: +!! +!! ocean_grid%cos_rot(i,j) +!! ocean_grid%sin_rot(i,j) +!! +!! The rotation of momentum flux from regular lat-lon to tripolar is: +!! \f[ +!! \begin{bmatrix} +!! \tau_x' \\ +!! \tau_y' +!! \end{bmatrix} = +!! \begin{bmatrix} +!! cos \theta & sin \theta \\ +!! -sin \theta & cos \theta +!! \end{bmatrix} * +!! \begin{bmatrix} +!! \tau_x \\ +!! \tau_y +!! \end{bmatrix} +!! \f] +!! +!! The rotation of ocean current from tripolar to regular lat-lon is: +!! \f[ +!! \begin{bmatrix} +!! u' \\ +!! v' +!! \end{bmatrix} = +!! \begin{bmatrix} +!! cos \theta & -sin \theta \\ +!! sin \theta & cos \theta +!! \end{bmatrix} * +!! \begin{bmatrix} +!! u \\ +!! v +!! \end{bmatrix} +!! \f] +!! @subsection Finalization Finalization +!! +!! NUOPC infrastructure calls [ocean_model_finalize] (@ref MOM_cap_mod::ocean_model_finalize) +!! at the end of the run. This subroutine is a hook to call into MOM's native shutdown +!! procedures: +!! +!! call ocean_model_end (ocean_public, ocean_State, Time) +!! call diag_manager_end(Time ) +!! call field_manager_end +!! call fms_io_exit +!! call fms_end +!! +!! @section ModelFields Model Fields +!! +!! The following tables list the import and export fields currently set up in the MOM cap. +!! +!! @subsection ImportFields Import Fields +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!!
Standard NameUnitsModel VariableDescriptionNotes
inst_pres_height_surfacePappressure of overlying sea ice and atmosphere
mass_of_overlying_sea_icekgmimass of overlying sea ice
seaice_melt_heatW m-2seaice_melt_heatsea ice and snow melt heat flux
seaice_meltkg m-2 s-1seaice_meltwater flux due to sea ice and snow melting
mean_calving_heat_flxW m-2calving_hflxheat flux, relative to 0C, of frozen land water into ocean
mean_calving_ratekg m-2 s-1calvingmass flux of frozen runoff
mean_evap_ratekg m-2 s-1q_fluxspecific humidity flux
mean_fprec_ratekg m-2 s-1fprecmass flux of frozen precip
mean_merid_moment_flxPav_fluxj-directed wind stress into ocean[vector rotation] (@ref VectorRotations) applied - lat-lon to tripolar
mean_net_lw_flxW m-2lw_fluxlong wave radiation
mean_net_sw_ir_dif_flxW m-2sw_flux_nir_difdiffuse near IR shortwave radiation
mean_net_sw_ir_dir_flxW m-2sw_flux_nir_dirdirect near IR shortwave radiation
mean_net_sw_vis_dif_flxW m-2sw_flux_vis_difdiffuse visible shortware radiation
mean_net_sw_vis_dir_flxW m-2sw_flux_vis_dirdirect visible shortware radiation
mean_prec_ratekg m-2 s-1lprecmass flux of liquid precip
mean_runoff_heat_flxW m-2runoff_hflxheat flux, relative to 0C, of liquid land water into ocean
mean_runoff_ratekg m-2 s-1runoffmass flux of liquid runoff
mean_salt_ratekg m-2 s-1salt_fluxsalt flux
mean_sensi_heat_flxW m-2t_fluxsensible heat flux into ocean
mean_zonal_moment_flxPau_fluxi-directed wind stress into ocean[vector rotation] (@ref VectorRotations) applied - lat-lon to tripolar
+!! +!! @subsection ExportField Export Fields +!! +!! Export fields are populated from the `ocean_public` parameter (type `ocean_public_type`) +!! after the call to `update_ocean_model()`. +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!! +!!
Standard NameUnitsModel VariableDescriptionNotes
freezing_melting_potentialW m-2combination of frazil and melt_potentialcap converts model units (J m-2) to (W m-2) for export
ocean_maskocean mask
ocn_current_meridm s-1v_surfj-directed surface velocity on u-cell[vector rotation] (@ref VectorRotations) applied - tripolar to lat-lon
ocn_current_zonalm s-1u_surfi-directed surface velocity on u-cell[vector rotation] (@ref VectorRotations) applied - tripolar to lat-lon
s_surfpsus_surfsea surface salinity on t-cell
sea_surface_temperatureKt_surfsea surface temperature on t-cell
sea_surface_slope_zonalunitlesscreated from sshsea surface zonal slope
sea_surface_slope_meridunitlesscreated from sshsea surface meridional slope
so_bldepthmobldocean surface boundary layer depth
+!! +!! @subsection MemoryManagement Memory Management +!! +!! The MOM cap has an internal state type with pointers to three +!! types defined by MOM. There is also a small wrapper derived type +!! required to associate an internal state instance +!! with the ESMF/NUOPC component: +!! +!! type ocean_internalstate_type +!! type(ocean_public_type), pointer :: ocean_public_type_ptr +!! type(ocean_state_type), pointer :: ocean_state_type_ptr +!! type(ice_ocean_boundary_type), pointer :: ice_ocean_boundary_type_ptr +!! end type +!! +!! type ocean_internalstate_wrapper +!! type(ocean_internalstate_type), pointer :: ptr +!! end type +!! +!! The member of type `ocean_public_type` stores ocean surface fields used during the coupling. +!! The member of type `ocean_state_type` is required by the ocean driver, +!! although its internals are private (not to be used by the coupling directly). +!! This type is passed to the ocean init and update routines +!! so that it can maintain state there if desired. +!! The member of type `ice_ocean_boundary_type` is populated by this cap +!! with incoming coupling fields from other components. These three derived types are allocated during the +!! [InitializeAdvertise] (@ref MOM_cap_mod::initializeadvertise) phase. Also during that +!! phase, the `ice_ocean_boundary` type members are all allocated using bounds retrieved +!! from `mpp_get_compute_domain()`. +!! +!! During the [InitializeRealize] (@ref MOM_cap_mod::initializerealize) phase, +!! `ESMF_Field`s are created for each of the coupling fields in the `ice_ocean_boundary` +!! and `ocean_public_type` members of the internal state. These fields directly reference into the members of +!! the `ice_ocean_boundary` and `ocean_public_type` so that memory-to-memory copies are not required to move +!! data from the cap's import and export states to the memory areas used internally +!! by MOM. +!! +!! @subsection IO I/O +!! +!! The cap can optionally output coupling fields for diagnostic purposes if the ESMF attribute +!! "DumpFields" has been set to "true". In this case the cap will write out NetCDF files +!! with names "field_ocn_import_.nc" and "field_ocn_export_.nc". +!! Additionally, calls will be made to the cap subroutine [dumpMomInternal] +!! (@ref MOM_cap_mod::dumpmominternal) to write out model internal fields to files +!! named "field_ocn_internal_.nc". In all cases these NetCDF files will +!! contain a time series of field data. +!! +!! @section RuntimeConfiguration Runtime Configuration +!! +!! At runtime, the MOM cap can be configured with several options provided +!! as ESMF attributes. Attributes can be set in the cap by the NUOPC Driver +!! above this cap, or in some systems ESMF attributes are set by +!! reading in from a configuration file. The available attributes are: +!! +!! * `DumpFields` - when set to "true", write out diagnostic NetCDF files for import/export/internal fields +!! * `ProfileMemory` - when set to "true", write out memory usage information to the ESMF log files; this +!! information is written when entering and leaving the [ModelAdvance] +!! (@ref MOM_cap_mod::modeladvance) subroutine and before and after the call to +!! `update_ocean_model()`. +!! * `restart_interval` - integer number of seconds indicating the interval at +!! which to call `ocean_model_restart()`; no restarts written if set to 0 + end module MOM_cap_mod