22
33module MOM_cap_mod
44
5+ use field_manager_mod, only: field_manager_init, field_manager_end
56use MOM_domains, only: get_domain_extent
6- use MOM_io, only: stdout, io_infra_end
7+ use MOM_io, only: stdout, io_infra_end, slasher
78use mpp_domains_mod, only: mpp_get_compute_domains
89use mpp_domains_mod, only: mpp_get_ntile_count, mpp_get_pelist, mpp_get_global_domain
910use mpp_domains_mod, only: mpp_get_domain_npes
@@ -30,13 +31,23 @@ module MOM_cap_mod
3031use MOM_cap_methods, only: ChkErr
3132use MOM_ensemble_manager, only: ensemble_manager_init
3233use MOM_coms, only: sum_across_PEs
34+ use MOM_coupler_types, only: coupler_1d_bc_type, coupler_2d_bc_type
3335
3436#ifdef CESMCOUPLED
3537use shr_log_mod, only: shr_log_setLogUnit
3638use nuopc_shr_methods, only: get_component_instance
3739#endif
3840use time_utils_mod, only: esmf2fms_time
3941
42+ #ifdef _USE_GENERIC_TRACER
43+ use MOM_coupler_types, only: coupler_type_spawn, coupler_type_destructor
44+ use MOM_coupler_types, only: coupler_type_set_diags, coupler_type_send_data, coupler_type_data_override
45+ use MOM_data_override, only: data_override_init, data_override
46+ use MOM_cap_gtracer_flux, only: gas_exchange_init, gas_fields_restore, gas_fields_restart
47+ use MOM_cap_gtracer_flux, only: get_coupled_field_name, add_gas_fluxes_param, UNKNOWN_CMEPS_FIELD
48+ use MOM_cap_gtracer_flux, only: atmos_ocean_fluxes_calc
49+ #endif
50+
4051use , intrinsic :: iso_fortran_env, only: output_unit
4152
4253use ESMF, only: ESMF_ClockAdvance, ESMF_ClockGet, ESMF_ClockPrint, ESMF_VMget
@@ -100,11 +111,14 @@ module MOM_cap_mod
100111public SetServices
101112public SetVM
102113
103- ! > Internal state type with pointers to three types defined by MOM.
114+ ! > Internal state type with pointers to types defined by MOM.
104115type ocean_internalstate_type
105116 type (ocean_public_type), pointer :: ocean_public_type_ptr
106117 type (ocean_state_type), pointer :: ocean_state_type_ptr
107118 type (ice_ocean_boundary_type), pointer :: ice_ocean_boundary_type_ptr
119+ #ifdef _USE_GENERIC_TRACER
120+ type (coupler_2d_bc_type), pointer :: coupler_2d_bc_type_ptr
121+ #endif
108122end type
109123
110124! > Wrapper-derived type required to associate an internal state instance
@@ -420,6 +434,10 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc)
420434 type (ocean_public_type), pointer :: ocean_public = > NULL ()
421435 type (ocean_state_type), pointer :: ocean_state = > NULL ()
422436 type (ice_ocean_boundary_type), pointer :: Ice_ocean_boundary = > NULL ()
437+ type (coupler_1d_bc_type), pointer :: gas_fields_atm = > NULL ()
438+ type (coupler_1d_bc_type), pointer :: gas_fields_ocn = > NULL ()
439+ type (coupler_1d_bc_type), pointer :: gas_fluxes = > NULL ()
440+ type (coupler_2d_bc_type), pointer :: atm_fields = > NULL ()
423441 type (ocean_internalstate_wrapper) :: ocean_internalstate
424442 type (ocean_grid_type), pointer :: ocean_grid = > NULL ()
425443 type (directories) :: dirs
@@ -452,6 +470,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc)
452470 character (len= 512 ) :: restartfile ! Path/Name of restart file
453471 character (len= 2048 ) :: restartfiles ! Path/Name of restart files
454472 ! (same as restartfile if single restart file)
473+ character (240 ) :: additional_restart_dir
455474 character (len=* ), parameter :: subname= ' (MOM_cap:InitializeAdvertise)'
456475 character (len= 32 ) :: calendar
457476 character (len= 17 ) :: timestamp
@@ -548,6 +567,8 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc)
548567 if (chkerr(rc,__LINE__,u_FILE_u)) return
549568 call MOM_infra_init(mpi_comm_mom)
550569
570+ call field_manager_init
571+
551572 ! determine the calendar
552573 if (cesm_coupled) then
553574 call NUOPC_CompAttributeGet(gcomp, name= " calendar" , value= cvalue, &
@@ -706,13 +727,44 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc)
706727
707728 endif
708729
730+ ! Set NUOPC attribute additional_restart_dir to RESTART/ if not defined
731+ additional_restart_dir = " RESTART/"
732+ call NUOPC_CompAttributeGet(gcomp, name= " additional_restart_dir" , value= cvalue, &
733+ isPresent= isPresent, isSet= isSet, rc= rc)
734+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
735+ if (isPresent .and. isSet) then
736+ additional_restart_dir = slasher(cvalue)
737+ else
738+ call ESMF_LogWrite(' MOM_cap:additional_restart_dir unset. Defaulting to ' // trim (additional_restart_dir), &
739+ ESMF_LOGMSG_INFO)
740+ endif
741+ call NUOPC_CompAttributeSet(gcomp, name= " additional_restart_dir" , value= additional_restart_dir, rc= rc)
742+ if (chkerr(rc,__LINE__,u_FILE_u)) return
743+
709744 ocean_public% is_ocean_pe = .true.
745+ #ifdef _USE_GENERIC_TRACER
746+ ! Initialise structures for extra tracer fluxes
747+ call gas_exchange_init(gas_fields_atm= gas_fields_atm, gas_fields_ocn= gas_fields_ocn, gas_fluxes= gas_fluxes)
748+
749+ if (cesm_coupled .and. len_trim (inst_suffix)>0 ) then
750+ call ocean_model_init(ocean_public, ocean_state, time0, time_start, gas_fields_ocn= gas_fields_ocn, &
751+ input_restart_file= trim (adjustl (restartfiles)), inst_index= inst_index)
752+ else
753+ call ocean_model_init(ocean_public, ocean_state, time0, time_start, gas_fields_ocn= gas_fields_ocn, &
754+ input_restart_file= trim (adjustl (restartfiles)))
755+ endif
756+
757+ ! Enable data override via the data_table using the component name 'OCN'
758+ call get_ocean_grid(ocean_state, ocean_grid)
759+ call data_override_init(ocean_grid% Domain)
760+ #else
710761 if (cesm_coupled .and. len_trim (inst_suffix)>0 ) then
711762 call ocean_model_init(ocean_public, ocean_state, time0, time_start, &
712763 input_restart_file= trim (adjustl (restartfiles)), inst_index= inst_index)
713764 else
714765 call ocean_model_init(ocean_public, ocean_state, time0, time_start, input_restart_file= trim (adjustl (restartfiles)))
715766 endif
767+ #endif
716768
717769 ! GMM, this call is not needed in CESM. Check with EMC if it can be deleted.
718770 call ocean_model_flux_init(ocean_state)
@@ -780,6 +832,31 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc)
780832 endif
781833 endif
782834
835+ #ifdef _USE_GENERIC_TRACER
836+ ! Allocate fields for extra tracer fluxes in Ice_ocean_boundary
837+ ! Annoyingly, spawning doesn't copy param array, so add manually
838+ call coupler_type_spawn(gas_fluxes, Ice_ocean_boundary% fluxes, (/ isc,isc,iec,iec/ ), &
839+ (/ jsc,jsc,jec,jec/ ), suffix= ' _ice_ocn' )
840+ call add_gas_fluxes_param(Ice_ocean_boundary% fluxes)
841+
842+ ! Initialise structure for atmos fields related to extra tracer fluxes
843+ ! This is set in the ESMF Internal State to be accessed elsewhere
844+ ! TODO: should we deallocate atm_fields in a finalise step? Ice_ocean_boundary is handled
845+ ! in a similar way and does not appear to be deallocated.
846+ allocate (atm_fields)
847+ ocean_internalstate% ptr% coupler_2d_bc_type_ptr = > atm_fields
848+ call coupler_type_spawn(gas_fields_atm, atm_fields, (/ isc,isc,iec,iec/ ), &
849+ (/ jsc,jsc,jec,jec/ ), suffix= ' _atm' )
850+
851+ ! Register diagnosics for extra tracer flux structures
852+ call coupler_type_set_diags(Ice_ocean_boundary% fluxes, " ocean_flux" , ocean_public% axes(1 :2 ), time_start)
853+ call coupler_type_set_diags(atm_fields, " atmos_sfc" , ocean_public% axes(1 :2 ), time_start)
854+
855+ ! Restore ocean fields related to extra tracer fluxes from restart files
856+ call get_MOM_input(dirs= dirs)
857+ call gas_fields_restore(ocean_public% fields, ocean_public% domain, dirs% restart_input_dir)
858+ #endif
859+
783860 if (use_waves) then
784861 if (wave_method == " EFACTOR" ) then
785862 allocate ( Ice_ocean_boundary% lamult(isc:iec,jsc:jec), source= 0.0 )
@@ -881,6 +958,15 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc)
881958 endif
882959 endif
883960
961+ #ifdef _USE_GENERIC_TRACER
962+ ! Add import fields required for extra tracer fluxes
963+ do n = 1 , gas_fluxes% num_bcs
964+ stdname = get_coupled_field_name(gas_fluxes% bc(n)% name)
965+ if (stdname /= UNKNOWN_CMEPS_FIELD) &
966+ call fld_list_add(fldsToOcn_num, fldsToOcn, stdname, " will provide" )
967+ enddo
968+ #endif
969+
884970 !- -------- export fields -------------
885971 call fld_list_add(fldsFrOcn_num, fldsFrOcn, " So_omask" , " will provide" )
886972 call fld_list_add(fldsFrOcn_num, fldsFrOcn, " So_t" , " will provide" )
@@ -895,6 +981,8 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc)
895981 call fld_list_add(fldsFrOcn_num, fldsFrOcn, " Faoo_fco2_ocn" , " will provide" )
896982 endif
897983
984+ ! TODO: dts: How to handle export fields from generic tracers?
985+
898986 do n = 1 ,fldsToOcn_num
899987 call NUOPC_Advertise(importState, standardName= fldsToOcn(n)% stdname, name= fldsToOcn(n)% shortname, rc= rc)
900988 if (ChkErr(rc,__LINE__,u_FILE_u)) return
@@ -1706,11 +1794,14 @@ subroutine ModelAdvance(gcomp, rc)
17061794 type (ocean_public_type), pointer :: ocean_public = > NULL ()
17071795 type (ocean_state_type), pointer :: ocean_state = > NULL ()
17081796 type (ice_ocean_boundary_type), pointer :: Ice_ocean_boundary = > NULL ()
1797+ type (coupler_2d_bc_type), pointer :: atm_fields = > NULL ()
17091798 type (ocean_internalstate_wrapper) :: ocean_internalstate
17101799 type (ocean_grid_type) , pointer :: ocean_grid
17111800 type (time_type) :: Time
1801+ type (time_type) :: Time_import
17121802 type (time_type) :: Time_step_coupled
17131803 type (time_type) :: Time_restart_current
1804+ integer :: isc,iec,jsc,jec
17141805 integer :: dth, dtm, dts
17151806 integer :: nc
17161807 type (ESMF_Time) :: MyTime
@@ -1722,13 +1813,14 @@ subroutine ModelAdvance(gcomp, rc)
17221813 integer :: writeunit
17231814 integer :: localPet
17241815 type (ESMF_VM) :: vm
1725- integer :: n, i
1816+ integer :: m, n, i
17261817 character (240 ) :: import_timestr, export_timestr
17271818 character (len= 128 ) :: fldname
17281819 character (len=* ),parameter :: subname= ' (MOM_cap:ModelAdvance)'
17291820 character (len= 8 ) :: suffix
17301821 character (len= :), allocatable :: rpointer_filename
17311822 character (len= 17 ) :: timestamp
1823+ character (240 ) :: additional_restart_dir
17321824 integer :: num_rest_files
17331825 real (8 ) :: MPI_Wtime, timers
17341826 logical :: write_restart, write_restartfh
@@ -1769,6 +1861,7 @@ subroutine ModelAdvance(gcomp, rc)
17691861
17701862 Time_step_coupled = esmf2fms_time(timeStep)
17711863 Time = esmf2fms_time(currTime)
1864+ Time_import = Time
17721865
17731866 !- --------------
17741867 ! Apply ocean lag for startup runs:
@@ -1844,8 +1937,39 @@ subroutine ModelAdvance(gcomp, rc)
18441937 ! Import data
18451938 !- --------------
18461939
1940+ #ifdef _USE_GENERIC_TRACER
1941+ atm_fields = > ocean_internalstate% ptr% coupler_2d_bc_type_ptr
1942+
1943+ call mom_import(ocean_public, ocean_grid, importState, ice_ocean_boundary, atm_fields= atm_fields, rc= rc)
1944+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
1945+
1946+ ! Potentially override atm_fields from data_table.
1947+ call coupler_type_data_override(' OCN' , atm_fields, Time_import)
1948+
1949+ ! Potentially override ice_ocean_boundary%fluxes from data_table.
1950+ ! Doing this before atmos_ocean_fluxes_calc call avoids unnecessary calculation of overridden fluxes.
1951+ ! However, we cannot use coupler_type_data_override here since it does not set the override flag on
1952+ ! overridden fields
1953+ do n = 1 , ice_ocean_boundary% fluxes% num_bcs
1954+ do m = 1 , ice_ocean_boundary% fluxes% bc(n)% num_fields
1955+ call data_override(' OCN' , ice_ocean_boundary% fluxes% bc(n)% field(m)% name, &
1956+ ice_ocean_boundary% fluxes% bc(n)% field(m)% values, Time_import, &
1957+ override= ice_ocean_boundary% fluxes% bc(n)% field(m)% override)
1958+ enddo
1959+ enddo
1960+
1961+ ! Calculate the extra tracer fluxes
1962+ call get_domain_extent(ocean_public% domain, isc, iec, jsc, jec)
1963+ call atmos_ocean_fluxes_calc(atm_fields, ocean_public% fields, ice_ocean_boundary% fluxes, &
1964+ ice_ocean_boundary% ice_fraction, isc, iec, jsc, jec)
1965+
1966+ ! Send diagnostics
1967+ call coupler_type_send_data(atm_fields, Time_import)
1968+ call coupler_type_send_data(ice_ocean_boundary% fluxes, Time_import)
1969+ #else
18471970 call mom_import(ocean_public, ocean_grid, importState, ice_ocean_boundary, rc= rc)
18481971 if (ChkErr(rc,__LINE__,u_FILE_u)) return
1972+ #endif
18491973
18501974 !- --------------
18511975 ! Update MOM6
@@ -1912,7 +2036,7 @@ subroutine ModelAdvance(gcomp, rc)
19122036 ! determine restart filename
19132037 call ESMF_ClockGetNextTime(clock, MyTime, rc= rc)
19142038 if (ChkErr(rc,__LINE__,u_FILE_u)) return
1915- call ESMF_TimeGet (MyTime, yy= year, mm= month, dd= day, h = hour, m = minute, s= seconds, rc= rc )
2039+ call ESMF_TimeGet (MyTime, yy= year, mm= month, dd= day, s= seconds, rc= rc )
19162040 if (ChkErr(rc,__LINE__,u_FILE_u)) return
19172041
19182042 if (cesm_coupled) then
@@ -1975,6 +2099,14 @@ subroutine ModelAdvance(gcomp, rc)
19752099
19762100 endif
19772101
2102+ #ifdef _USE_GENERIC_TRACER
2103+ ! Write fields for extra tracer fluxes to their internally defined ocean restart file
2104+ call NUOPC_CompAttributeGet(gcomp, name= " additional_restart_dir" , value= additional_restart_dir, rc= rc)
2105+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
2106+
2107+ call gas_fields_restart(ocean_public% fields, ocean_public% domain, additional_restart_dir)
2108+ #endif
2109+
19782110 if (is_root_pe()) then
19792111 write (stdout,* ) subname// ' writing restart file ' ,trim (restartname)
19802112 endif
@@ -2213,6 +2345,7 @@ subroutine ocean_model_finalize(gcomp, rc)
22132345 type (ESMF_Alarm), allocatable :: alarmList(:)
22142346 integer :: alarmCount
22152347 logical :: write_restart
2348+ character (240 ) :: additional_restart_dir
22162349 character (len=* ),parameter :: subname= ' (MOM_cap:ocean_model_finalize)'
22172350 real (8 ) :: MPI_Wtime, timefs
22182351
@@ -2246,6 +2379,18 @@ subroutine ocean_model_finalize(gcomp, rc)
22462379
22472380 call ocean_model_end(ocean_public, ocean_State, Time, write_restart= write_restart)
22482381
2382+ #ifdef _USE_GENERIC_TRACER
2383+ if (write_restart) then
2384+ ! Write fields for extra tracer fluxes to their internally defined ocean restart file
2385+ call NUOPC_CompAttributeGet(gcomp, name= " additional_restart_dir" , value= additional_restart_dir, rc= rc)
2386+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
2387+
2388+ call gas_fields_restart(ocean_public% fields, ocean_public% domain, additional_restart_dir)
2389+ endif
2390+ #endif
2391+
2392+ call field_manager_end()
2393+
22492394 call io_infra_end()
22502395 call MOM_infra_end()
22512396
0 commit comments