program hycom_cice ! ! --- ESMF driver for HYCOM ocean model and CICE sea-ice model ! use ESMF_Mod use mod_hycom, only : & OCN_put_export => put_export, & OCN_get_import => get_import, & OCN_end_of_run => end_of_run, & OCN_nts_day => nts_day, & OCN_nts_cpl => nts_ice, & OCN_SetServices => HYCOM_SetServices use ice_kinds_mod use CICE_ComponentMod, only : & ICE_SetServices => CICE_SetServices use CICE_InitMod, only : & ICE_nts_day => nts_day use CICE_RunMod, only : & ICE_put_export => put_export, & ICE_get_import => get_import, & ICE_end_of_run => end_of_run use mod_OICPL, only : & CPL_i2o => ice2ocn_phase, & CPL_o2i => ocn2ice_phase, & CPL_SetServices => OICPL_SetServices ! implicit none ! ! --- Local variables ! ! --- Gridded Components type(ESMF_GridComp) :: ocnGridComp, & !HYCOM as an ESMF component iceGridComp ! CICE as an ESMF component ! ! --- Coupler Components type(ESMF_CplComp) :: o2iCplComp ! ! --- States, Virtual Machines, and Layouts type(ESMF_State) :: ocnImpState, & ! HYCOM import state ocnExpState, & ! HYCOM export state iceImpState, & ! CICE import state iceExpState, & ! CICE export state cplImpState, & ! OICPL import state cplExpState ! OICPL export state ! type(ESMF_VM) :: worldVM integer :: petCount, localPet, split ! ! --- Calendars and clocks type(ESMF_Clock) :: worldClock type(ESMF_Clock) :: ocnClock type(ESMF_Clock) :: iceClock ! ! --- Return codes for error checks integer :: rc,rc2 ! ! --- ICE coupling frequency integer :: ice_nts_cpl,ocn_cpl_day ! ! --- Miscellaneous integer :: i,its,its_ocn,its_ice,icpl,iday ! !------------------------------------------------------------------------------- ! Initialize the ESMF Framework !------------------------------------------------------------------------------- ! ! --- Set default calendar and log type; get world VM rc = ESMF_Success call ESMF_Initialize(defaultCalendar=ESMF_CAL_GREGORIAN, & defaultLogType=ESMF_LOG_MULTI, & vm=worldVM, & rc=rc) if (rc .ne. ESMF_SUCCESS) stop 99 ! ! --- Get VM info call ESMF_VMGet(worldVM, petCount=petCount, localPET=localPet, & rc=rc) if (ESMF_LogMsgFoundError(rc, & "ESMF_VMGet failed", rcToReturn=rc2)) & goto 10 ! !------------------------------------------------------------------------------- ! --- Create section !------------------------------------------------------------------------------- ! ! --- Create the OCEAN gridded component ocnGridComp = ESMF_GridCompCreate( & name="OCEAN Gridded Component", & gridCompType=ESMF_OCEAN, & rc=rc) if (ESMF_LogMsgFoundError(rc, & "OCEAN GridCompCreate failed", rcToReturn=rc2)) & goto 10 ! ! --- Create empty OCEAN import/export states ocnImpState = ESMF_StateCreate(stateName="OCEAN Import", & stateType=ESMF_STATE_IMPORT, & rc=rc) if (ESMF_LogMsgFoundError(rc, & "OCEAN ImpState Create failed", rcToReturn=rc2)) & goto 10 ocnExpState = ESMF_StateCreate(stateName="OCEAN Export", & stateType=ESMF_STATE_EXPORT, & rc=rc) if (ESMF_LogMsgFoundError(rc, & "OCEAN ExpState Create failed", rcToReturn=rc2)) & goto 10 ! ! --- Create the SEAICE gridded component iceGridComp = ESMF_GridCompCreate( & name='SEAICE Component', & gridcomptype=ESMF_SEAICE, & rc=rc) if (ESMF_LogMsgFoundError(rc, & "SEAICE GridCompCreate failed", rcToReturn=rc2)) & goto 10 ! ! --- Create empty SEAICE import/export states iceImpState = ESMF_StateCreate(stateName="SEAICE Import", & stateType=ESMF_STATE_IMPORT, & rc=rc) if (ESMF_LogMsgFoundError(rc, & "SEAICE ImpState Create failed", rcToReturn=rc2)) & goto 10 iceExpState = ESMF_StateCreate(stateName="SEAICE Export", & stateType=ESMF_STATE_EXPORT, & rc=rc) if (ESMF_LogMsgFoundError(rc, & "SEAICE ExpState Create failed", rcToReturn=rc2)) & goto 10 ! ! --- Create the OICPL coupler component o2iCplComp = ESMF_CplCompCreate( & name="OICPL Coupler Component", & rc=rc) if (ESMF_LogMsgFoundError(rc, & "OICPLE CplCompCreate failed", rcToReturn=rc2)) & goto 10 ! ! --- Create empty OICPL import/export states cplImpState = ESMF_StateCreate(stateName="OICPL Import", & stateType=ESMF_STATE_IMPORT, & rc=rc) if (ESMF_LogMsgFoundError(rc, & "OICPL ImpState Create failed", rcToReturn=rc2)) & goto 10 cplExpState = ESMF_StateCreate(stateName="OICPL Export", & stateType=ESMF_STATE_EXPORT, & rc=rc) if (ESMF_LogMsgFoundError(rc, & "OICPL ExpState Create failed", rcToReturn=rc2)) & goto 10 ! ! --- Add OCEAN and SEAICE states to OICPL states CALL ESMF_StateAdd(cplImpState, ocnImpState, rc=rc) if (ESMF_LogMsgFoundError(rc, & "OICPL: Add OCEAN impState failed", rcToReturn=rc2)) & goto 10 CALL ESMF_StateAdd(cplImpState, iceImpState, rc=rc) if (ESMF_LogMsgFoundError(rc, & "OICPL: Add SEAICE impState failed", rcToReturn=rc2)) & goto 10 CALL ESMF_StateAdd(cplExpState, ocnExpState, rc=rc) if (ESMF_LogMsgFoundError(rc, & "OICPL: Add OCEAN expState failed", rcToReturn=rc2)) & goto 10 CALL ESMF_StateAdd(cplExpState, iceExpState, rc=rc) if (ESMF_LogMsgFoundError(rc, & "OICPL: Add SEAICE impState failed", rcToReturn=rc2)) & goto 10 ! !------------------------------------------------------------------------------- ! --- Register section !------------------------------------------------------------------------------- ! ! --- Register the OCEAN gridded component call ESMF_GridCompSetServices(ocnGridComp, & OCN_SetServices, rc=rc) if (ESMF_LogMsgFoundError(rc, & "OCEAN Registration failed", rcToReturn=rc2)) & goto 10 ! ! --- Register the SEAICE gridded component call ESMF_GridCompSetServices(iceGridComp, & ICE_SetServices, rc=rc) if (ESMF_LogMsgFoundError(rc, & "SEAICE Registration failed", rcToReturn=rc2)) & goto 10 ! ! --- Register the OICPL coupler component call ESMF_CplCompSetServices(o2iCplComp, & CPL_SetServices,rc=rc) if (ESMF_LogMsgFoundError(rc, & "OICPL Registration failed", rcToReturn=rc2)) & goto 10 ! !------------------------------------------------------------------------------- ! --- Initalize Section !------------------------------------------------------------------------------- ! ! --- Initialize OCEAN gridded component call ESMF_GridCompInitialize( gridComp=ocnGridComp, & importState=ocnImpState, & exportState=ocnExpState, & phase=ESMF_SINGLEPHASE, & blockingflag=ESMF_NONBLOCKING, & rc=rc) if (ESMF_LogMsgFoundError(rc, & "OCEAN Initialize failed", rcToReturn=rc2)) & goto 10 ! ! --- Initialize SEAICE gridded component call ESMF_GridCompInitialize( gridComp=iceGridComp, & importState=iceImpState, & exportState=iceExpState, & phase=ESMF_SINGLEPHASE, & blockingflag=ESMF_NONBLOCKING, & rc=rc) if (ESMF_LogMsgFoundError(rc, & "SEAICE Initialize failed", rcToReturn=rc2)) & goto 10 ! ocn_cpl_day = OCN_nts_day/OCN_nts_cpl ice_nts_cpl = ICE_nts_day/ocn_cpl_day if (localPet.eq.0) then !master write(6,'(a,i5)') 'OCN_nts_day = ',OCN_nts_day write(6,'(a,i5)') 'ICE_nts_day = ',ICE_nts_day write(6,'(a,i5)') 'OCN_nts_cpl = ',OCN_nts_cpl write(6,'(a,i5)') 'ice_nts_cpl = ',ice_nts_cpl endif if (OCN_nts_day.ne.ocn_cpl_day*OCN_nts_cpl) then if (localPet.eq.0) then !master write(6,*) 'ERROR OCN_nts_cpl not a divisor of OCN_nts_day' endif goto 10 endif if (ICE_nts_day.ne.ocn_cpl_day*ice_nts_cpl) then if (localPet.eq.0) then !master write(6,*) 'ERROR ice_nts_cpl not a divisor of ICE_nts_day' endif goto 10 endif ! ! --- Initialize OICPL coupler component call ESMF_CplCompInitialize( cplComp=o2iCplComp, & importState=cplImpState, & exportState=cplExpState, & phase=ESMF_SINGLEPHASE, & blockingflag=ESMF_BLOCKING, & rc=rc) if (ESMF_LogMsgFoundError(rc, & "OICPL Initialize failed", rcToReturn=rc2)) & goto 10 ! ! --- Couple SEAICE to OCEAN call ESMF_CplCompRun( cplComp=o2iCplComp, & importState=cplImpState, & exportState=cplExpState, & phase=CPL_i2o, & blockingflag=ESMF_BLOCKING, & rc=rc) if (ESMF_LogMsgFoundError(rc, & "OICPL I2O Run failed", rcToReturn=rc2)) & goto 10 ! ! --- Couple OCEAN to SEAICE call ESMF_CplCompRun( cplComp=o2iCplComp, & importState=cplImpState, & exportState=cplExpState, & phase=CPL_o2i, & blockingflag=ESMF_BLOCKING, & rc=rc) if (ESMF_LogMsgFoundError(rc, & "OICPL I2O Run failed", rcToReturn=rc2)) & goto 10 ! !------------------------------------------------------------------------------- ! --- Run Section !------------------------------------------------------------------------------- ! ! --- Run Ocean and SeaIce in lockstep, both looking backwards for imports do icpl=1,huge(iday)/2 !until end of run ! --- OCEAN do its= 1,OCN_nts_cpl !couple period, OCEAN if (mod(its,OCN_nts_cpl).le.1 .and. & localPet.eq.0) then !master write(6,'(a,i4,i4)') ' OCEAN run - icpl,its = ',icpl,its endif OCN_get_import = its.eq.1 !import at start of period OCN_put_export = its.eq.OCN_nts_cpl !export at end of period call ESMF_GridCompRun( gridComp=ocnGridComp, & importState=ocnImpState, & exportState=ocnExpState, & phase=ESMF_SINGLEPHASE, & blockingflag=ESMF_NONBLOCKING, & rc=rc) if (ESMF_LogMsgFoundError(rc, & "OCEAN Run failed", rcToReturn=rc2)) & goto 10 enddo !its; OCEAN ! --- SEAICE do its= 1,ice_nts_cpl !couple period, SEAICE if (mod(its,ice_nts_cpl).le.1 .and. & localPet.eq.0) then !master write(6,'(a,i4,i4)') 'SEAICE run - icpl,its = ',icpl,its endif ICE_get_import = its.eq.1 !import at start of period ICE_put_export = its.eq.ice_nts_cpl !export at end of period ! ICE_put_export = .false. !don't export at end of period call ESMF_GridCompRun( gridComp=iceGridComp, & importState=iceImpState, & exportState=iceExpState, & phase=ESMF_SINGLEPHASE, & blockingflag=ESMF_NONBLOCKING, & rc=rc) if (ESMF_LogMsgFoundError(rc, & "SEAICE Run failed (last half day)", rcToReturn=rc2)) & goto 10 enddo !its; SEAICE ! --- use end_of_run, rather than a ESMF Clock if (OCN_end_of_run) then exit !icpl endif !end_of_run ! --- Couple SEAICE to OCEAN call ESMF_CplCompRun( cplComp=o2iCplComp, & importState=cplImpState, & exportState=cplExpState, & phase=CPL_i2o, & blockingflag=ESMF_BLOCKING, & rc=rc) if (ESMF_LogMsgFoundError(rc, & "OICPL I2O Run failed", rcToReturn=rc2)) & goto 10 ! --- Couple OCEAN to SEAICE call ESMF_CplCompRun( cplComp=o2iCplComp, & importState=cplImpState, & exportState=cplExpState, & phase=CPL_o2i, & blockingflag=ESMF_BLOCKING, & rc=rc) if (ESMF_LogMsgFoundError(rc, & "OICPL I2O Run failed", rcToReturn=rc2)) & goto 10 enddo !icpl ! call ESMF_VMBarrier(worldVM) ! !------------------------------------------------------------------------------- ! Finalize Section !------------------------------------------------------------------------------- ! ! --- Finalize OCEAN gridded component call ESMF_GridCompFinalize( gridComp=ocnGridComp, & importState=ocnImpState, & exportState=ocnExpState, & phase=ESMF_SINGLEPHASE, & blockingflag=ESMF_NONBLOCKING, & rc=rc) if (ESMF_LogMsgFoundError(rc, & "OCEAN Finalize failed", rcToReturn=rc2)) & goto 10 ! ! --- Finalize SEAICE gridded component call ESMF_GridCompFinalize( gridComp=iceGridComp, & importState=iceImpState, & exportState=iceExpState, & phase=ESMF_SINGLEPHASE, & blockingflag=ESMF_NONBLOCKING, & rc=rc) if (ESMF_LogMsgFoundError(rc, & "SEAICE Finalize failed", rcToReturn=rc2)) & goto 10 ! ! --- Finalize OACPL coupler component call ESMF_CplCompFinalize( cplComp=o2iCplComp, & importState=cplImpState, & exportState=cplExpState, & phase=ESMF_SINGLEPHASE, & blockingflag=ESMF_BLOCKING, & rc=rc) if (ESMF_LogMsgFoundError(rc, & "OICPL Finalize failed", rcToReturn=rc2)) & goto 10 ! 10 continue call ESMF_VMBarrier(worldVM) call ESMF_Finalize(rc=rc) ! stop end program hycom_cice