! +-======-+ ! Copyright (c) 2003-2007 United States Government as represented by ! the Admistrator of the National Aeronautics and Space Administration. ! All Rights Reserved. ! ! THIS OPEN SOURCE AGREEMENT ("AGREEMENT") DEFINES THE RIGHTS OF USE, ! REPRODUCTION, DISTRIBUTION, MODIFICATION AND REDISTRIBUTION OF CERTAIN ! COMPUTER SOFTWARE ORIGINALLY RELEASED BY THE UNITED STATES GOVERNMENT AS ! REPRESENTED BY THE GOVERNMENT AGENCY LISTED BELOW ("GOVERNMENT AGENCY"). ! THE UNITED STATES GOVERNMENT, AS REPRESENTED BY GOVERNMENT AGENCY, IS AN ! INTENDED THIRD-PARTY BENEFICIARY OF ALL SUBSEQUENT DISTRIBUTIONS OR ! REDISTRIBUTIONS OF THE SUBJECT SOFTWARE. ANYONE WHO USES, REPRODUCES, ! DISTRIBUTES, MODIFIES OR REDISTRIBUTES THE SUBJECT SOFTWARE, AS DEFINED ! HEREIN, OR ANY PART THEREOF, IS, BY THAT ACTION, ACCEPTING IN FULL THE ! RESPONSIBILITIES AND OBLIGATIONS CONTAINED IN THIS AGREEMENT. ! ! Government Agency: National Aeronautics and Space Administration ! Government Agency Original Software Designation: GSC-15354-1 ! Government Agency Original Software Title: GEOS-5 GCM Modeling Software ! User Registration Requested. Please Visit http://opensource.gsfc.nasa.gov ! Government Agency Point of Contact for Original Software: ! Dale Hithon, SRA Assistant, (301) 286-2691 ! ! +-======-+ ! $Id: MAPL_Cap.F90,v 1.33.4.2 2010-08-10 17:45:37 atrayano Exp $ #include "MAPL_Generic.h" module MAPL_CapMod !BOP ! !MODULE: MAPL_CapMod --- Implements the top entry point for MAPL components ! !USES: use ESMF_Mod use MAPL_BaseMod use MAPL_ConstantsMod use MAPL_ProfMod use MAPL_MemUtilsMod use MAPL_IOMod use MAPL_CommsMod use MAPL_GenericMod use MAPL_LocStreamMod use ESMFL_Mod use MAPL_HistoryGridCompMod, only : Hist_SetServices => SetServices use MAPL_HistoryGridCompMod, only : HISTORY_ExchangeListWrap implicit none private ! !PUBLIC MEMBER FUNCTIONS: public MAPL_Cap ! !DESCRIPTION: ! \input{TeX/MAPL_CapIntro.tex} !EOP contains !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !BOPI ! !IROUTINE: MAPL_Cap -- Implements generic Cap functionality ! !INTERFACE: subroutine MAPL_CAP(ROOT_SetServices, Name, RC) ! !ARGUMENTS: external :: ROOT_SetServices character*(*), optional, intent(IN ) :: Name integer, optional, intent(OUT) :: rc !EOPI ! Handles to the CAP's Gridded Components GCs ! ------------------------------------------- integer :: ROOT integer :: HIST character(len=ESMF_MAXSTR) :: ROOT_NAME ! A MAPL object for the cap !-------------------------- type(MAPL_MetaComp) :: MAPLOBJ ! The children's GCs and IM/Ex states !------------------------------------ type(ESMF_GridComp), pointer :: GCS(:) type(ESMF_State), pointer :: IMPORTS(:) type(ESMF_State), pointer :: EXPORTS(:) ! ESMF stuff !----------- type(ESMF_VM) :: VM type(ESMF_Config) :: config type(ESMF_Config) :: cf type(ESMF_Clock) :: clock ! ErrLog variables !----------------- integer :: STATUS character(len=ESMF_MAXSTR) :: Iam="MAPL_Cap" ! Misc locals !------------ character(len=ESMF_MAXSTR) :: ROOT_CF character(len=ESMF_MAXSTR) :: HIST_CF character(len=ESMF_MAXSTR) :: enableTimers character(len=ESMF_MAXSTR) :: enableMemUtils logical :: done integer :: printSpec integer :: HEARTBEAT_DT integer :: RUN_DT integer*8, pointer :: LSADDR(:) => null() type(HISTORY_ExchangeListWrap) :: lswrap ! Begin !------ ! Initialize ESMF !----------------- #if defined(ENABLE_ESMF_ERR_LOGGING) call ESMF_Initialize (vm=vm, rc=status) #else call ESMF_Initialize (vm=vm, defaultLogType=ESMF_LOG_NONE, rc=status) #endif VERIFY_(STATUS) ! Open the CAP's configuration from CAP.rc !------------------------------------------ config = ESMF_ConfigCreate ( rc=STATUS ) VERIFY_(STATUS) call ESMF_ConfigLoadFile ( config, 'CAP.rc', rc=STATUS ) VERIFY_(STATUS) ! CAP's MAPL MetaComp !--------------------- if(present(Name)) then call MAPL_Set (MAPLOBJ, name= Name, cf=CONFIG, rc=STATUS ) VERIFY_(STATUS) else call MAPL_Set (MAPLOBJ, name='CAP', cf=CONFIG, rc=STATUS ) VERIFY_(STATUS) end if ! Create Clock. This is a private routine that sets the start and ! end times and the time interval of the clock from the configuration. ! The start time is temporarily set to 1 interval before the time in the ! configuration. Once the Alarms are set in intialize, the clock will ! be advanced to guarantee it and its alarms are in the same state as they ! were after the last advance before the previous Finalize. !--------------------------------------------------------------------------- call MAPL_ClockInit ( MAPLOBJ, clock, rc=STATUS ) VERIFY_(STATUS) ! Get configurable info to create HIST ! and the ROOT of the computational hierarchy !--------------------------------------------- !BOR ! !xRESOURCE_ITEM: string :: Name of ROOT's config file call MAPL_GetResource(MAPLOBJ, ROOT_CF, "ROOT_CF:", & default="ROOT.rc", RC=STATUS ) VERIFY_(STATUS) ! !xRESOURCE_ITEM: string :: Name to assign to the ROOT component call MAPL_GetResource(MAPLOBJ, ROOT_NAME, "ROOT_NAME:", & default="ROOT", RC=STATUS ) VERIFY_(STATUS) ! !xRESOURCE_ITEM: string :: Name of HISTORY's config file call MAPL_GetResource(MAPLOBJ, HIST_CF, "HIST_CF:", & default="HIST.rc", RC=STATUS ) VERIFY_(STATUS) ! !xRESOURCE_ITEM: string :: Control Timers call MAPL_GetResource(MAPLOBJ, enableTimers, "MAPL_ENABLE_TIMERS:", & default='NO', RC=STATUS ) VERIFY_(STATUS) ! !xRESOURCE_ITEM: string :: Control Memory Diagnostic Utility call MAPL_GetResource(MAPLOBJ, enableMemUtils, "MAPL_ENABLE_MEMUTILS:", & default='NO', RC=STATUS ) VERIFY_(STATUS) if (enableTimers /= 'YES' .and. enableTimers /= 'yes') then call MAPL_ProfDisable( rc=STATUS ) VERIFY_(STATUS) end if if (enableMemUtils /= 'YES' .and. enableMemUtils /= 'yes') then call MAPL_MemUtilsDisable( rc=STATUS ) VERIFY_(STATUS) else call MAPL_MemUtilsInit( rc=STATUS ) VERIFY_(STATUS) end if call MAPL_GetResource( MAPLOBJ, printSpec, label='PRINTSPEC:', default = 0, rc=STATUS ) VERIFY_(STATUS) ! Handle RUN_DT in ROOT_CF !------------------------- call ESMF_ConfigGetAttribute(config, value=HEARTBEAT_DT, & Label="HEARTBEAT_DT:", rc=status) VERIFY_(STATUS) cf = ESMF_ConfigCreate(rc=STATUS ) VERIFY_(STATUS) call ESMF_ConfigLoadFile(cf, ROOT_CF, rc=STATUS ) VERIFY_(STATUS) call ESMF_ConfigGetAttribute(cf, value=RUN_DT, Label="RUN_DT:", rc=status) if (STATUS == ESMF_SUCCESS) then if (heartbeat_dt /= run_dt) then if (MAPL_AM_I_Root(VM)) then print *, "ERROR: inconsistent values of HEATBEAT_DT and RUN_DT" end if call ESMF_VMBarrier(VM) RETURN_(ESMF_FAILURE) end if else call ESMF_ConfigSetAttribute(cf, value=heartbeat_dt, Label="RUN_DT:", rc=status) !ALT: it is VERY important NOT to check the status ! if the label is not in the config the above calls behaves correctly ! but returns a non-zero exit code endif ! Register the children with MAPL !-------------------------------- ! Create Root child !------------------- call MAPL_Set(MAPLOBJ, CF=CF, RC=STATUS) VERIFY_(STATUS) ROOT = MAPL_AddChild ( MAPLOBJ, & name = ROOT_NAME, & SS = ROOT_SetServices, & rc=STATUS ) VERIFY_(STATUS) ! Create History child !---------------------- HIST = MAPL_AddChild ( MAPLOBJ, & name = 'HIST', & configfile = HIST_CF, & SS = HIST_SetServices, & rc=STATUS ) VERIFY_(STATUS) ! Query MAPL for the the children's for GCS, IMPORTS, EXPORTS !------------------------------------------------------------- call MAPL_Get ( MAPLOBJ, GCS=GCS, GIM=IMPORTS, GEX=EXPORTS, RC=STATUS ) VERIFY_(STATUS) ! Run as usual unless PRINTSPEC> 0 as set in CAP.rc. If set then ! model will not run completely and instead it will simply run MAPL_SetServices ! and print out the IM/EX specs. This step uses MAPL_StatePrintSpecCSV found ! in MAPL_Generic.F90. if (printSpec>0) then call MAPL_StatePrintSpecCSV(GCS(ROOT), printSpec, RC=status) VERIFY_(STATUS) call ESMF_VMBarrier ( VM, RC=STATUS ) VERIFY_(STATUS) else ! Initialize the Computational Hierarchy !---------------------------------------- call ESMF_GridCompInitialize ( GCS(ROOT), IMPORTS(ROOT), EXPORTS(ROOT), & CLOCK, userRC=STATUS ) VERIFY_(STATUS) ! All the EXPORTS of the Hierachy are made IMPORTS of History !------------------------------------------------------------ call ESMF_StateAdd ( IMPORTS(HIST), EXPORTS(ROOT), RC=STATUS ) VERIFY_(STATUS) allocate(lswrap%ptr, stat=status) VERIFY_(STATUS) call ESMF_UserCompSetInternalState(GCS(HIST), 'MAPL_LocStreamList', & lswrap, STATUS) VERIFY_(STATUS) call MAPL_GetAllExchangeGrids(GCS(ROOT), LSADDR, RC=STATUS) VERIFY_(STATUS) lswrap%ptr%LSADDR_PTR => LSADDR ! Initialize the History !------------------------ call ESMF_GridCompInitialize ( GCS(HIST), IMPORTS(HIST), EXPORTS(HIST), & CLOCK, userRC=STATUS ) VERIFY_(STATUS) ! Time Loop starts by checking for Segment Ending Time !----------------------------------------------------- TIME_LOOP: do call MAPL_MemUtilsWrite(vm, 'MAPL_Cap:TimeLoop', RC=STATUS ) VERIFY_(STATUS) DONE = ESMF_ClockIsStopTime( CLOCK, RC=STATUS ) VERIFY_(STATUS) if ( DONE ) exit ! Call Record for intermediate checkpoint (if desired) ! This is currently implemented as a phase of Finalize ! rather than as a separate registered method. Note that ! we are not doing a Record for History. ! ------------------------------------------------------ call ESMF_GridCompWriteRestart( GCS(ROOT), IMPORTS(ROOT), EXPORTS(ROOT), & CLOCK, RC=STATUS ) VERIFY_(STATUS) ! Run the Gridded Component ! -------------------------- call ESMF_GridCompRun ( GCS(ROOT), IMPORTS(ROOT), EXPORTS(ROOT), & CLOCK, userRC=STATUS ) VERIFY_(STATUS) ! Synchronize for Next TimeStep ! ----------------------------- call ESMF_VMBarrier ( VM, RC=STATUS ) VERIFY_(STATUS) ! Advance the Clock before running History and Record ! --------------------------------------------------- call ESMF_ClockAdvance ( CLOCK, RC=STATUS ) VERIFY_(STATUS) ! Call History Run for Output ! --------------------------- call ESMF_GridCompRun ( GCS(HIST), IMPORTS(HIST), EXPORTS(HIST), & CLOCK, userRC=STATUS ) VERIFY_(STATUS) enddo TIME_LOOP ! end of time loop ! Finalize ! -------- call ESMF_GridCompFinalize( GCS(ROOT),IMPORTS(ROOT),EXPORTS(ROOT),CLOCK,userRC=STATUS ) VERIFY_(STATUS) call ESMF_GridCompFinalize( GCS(HIST),IMPORTS(HIST),EXPORTS(HIST),CLOCK,userRC=STATUS ) ! Finalize itselt ! ---------------- call CAP_Finalize(CLOCK, "cap_restart", rc=STATUS) VERIFY_(STATUS) end if ! PRINTSPEC ! Finalize framework ! ------------------ call ESMF_Finalize (RC=status) VERIFY_(STATUS) RETURN_(ESMF_SUCCESS) end subroutine MAPL_CAP subroutine CAP_FINALIZE ( clock,filen, rc ) type(ESMF_Clock), intent(in ) :: clock character(len=*), optional :: filen integer, optional, intent( out) :: rc integer :: UNIT integer :: datetime(2) integer :: YY, MM, DD, H, M, S integer :: status character(len=ESMF_MAXSTR), parameter :: IAm="CAP_FINALIZE" character(len=ESMF_MAXSTR) :: filen_ type(ESMF_Time) :: CurrentTime filen_ = "cap_restart" if (present(filen)) filen_ = trim(filen ) ! Retrieve Current Time for Cap Restart ! ------------------------------------- call ESMF_ClockGet ( clock, currTime=currentTime, rc=status ) VERIFY_(STATUS) call ESMF_TimeGet ( CurrentTime, YY = YY, & MM = MM, & DD = DD, & H = H , & M = M , & S = S, rc=status ) VERIFY_(STATUS) CALL MAPL_PackDateTime(DATETIME, YY, MM, DD, H, M, S) ! Write CAP Restart File and Ending Time for Current Segment ! ---------------------------------------------------------- if( MAPL_AM_I_ROOT() ) then UNIT = GETFILE( filen_, form="formatted" ) write(unit,100) datetime 100 format(i8.8,1x,i6.6) call FREE_FILE (UNIT) endif RETURN_(ESMF_SUCCESS) end subroutine CAP_FINALIZE !BOPI ! !IROUTINE: MAPL_ClockInit -- Sets the clock ! !INTERFACE: subroutine MAPL_ClockInit ( MAPLOBJ, Clock, rc) ! !ARGUMENTS: type(MAPL_MetaComp), intent(inout) :: MAPLOBJ type(ESMF_Clock), intent( out) :: Clock integer, optional, intent( out) :: rc ! !DESCRIPTION: ! This is a private routine that sets the start and ! end times and the time interval of the application clock from the configuration. ! This time interal is the ``heartbeat'' of the application. ! The Calendar is set to Gregorian by default. ! The start time is temporarily set to 1 interval before the time in the ! configuration. Once the Alarms are set in intialize, the clock will ! be advanced to guarantee it and its alarms are in the same state as they ! were after the last advance before the previous Finalize. ! !EOPI type(ESMF_Time) :: StartTime ! Initial Begin Time of Experiment type(ESMF_Time) :: EndTime ! Final Ending Time of Experiment type(ESMF_Time) :: StopTime ! Final Ending Time of Experiment type(ESMF_Time) :: CurrTime ! Current Current Time of Experiment type(ESMF_TimeInterval) :: timeStep ! HEARTBEAT type(ESMF_TimeInterval) :: duration type(ESMF_Calendar) :: cal character(ESMF_MAXSTR) :: CALENDAR integer :: STATUS character(ESMF_MAXSTR) :: IAM="MAPL_ClockInit" integer :: BEG_YY integer :: BEG_MM integer :: BEG_DD integer :: BEG_H integer :: BEG_M integer :: BEG_S integer :: CUR_YY integer :: CUR_MM integer :: CUR_DD integer :: CUR_H integer :: CUR_M integer :: CUR_S integer :: END_YY integer :: END_MM integer :: END_DD integer :: END_H integer :: END_M integer :: END_S integer :: DUR_YY integer :: DUR_MM integer :: DUR_DD integer :: DUR_H integer :: DUR_M integer :: DUR_S integer :: HEARTBEAT_DT integer :: NUM_DT integer :: DEN_DT integer :: UNIT integer :: datetime(2) ! Begin !------ ! Read Times From Config ! ---------------------- !BOR call MAPL_GetResource( MAPLOBJ, datetime, label='BEG_DATE:', rc=STATUS ) if(STATUS==ESMF_SUCCESS) then CALL MAPL_UnpackDateTime(DATETIME, BEG_YY, BEG_MM, BEG_DD, BEG_H, BEG_M, BEG_S) else ! !xRESOURCE_ITEM: year :: Beginning year (integer) call MAPL_GetResource( MAPLOBJ, BEG_YY, label='BEG_YY:', DEFAULT=1, rc=STATUS ) VERIFY_(STATUS) ! !xRESOURCE_ITEM: month :: Beginning month (integer 1-12) call MAPL_GetResource( MAPLOBJ, BEG_MM, label='BEG_MM:', default=1, rc=STATUS ) VERIFY_(STATUS) ! !xRESOURCE_ITEM: day :: Beginning day of month (integer 1-31) call MAPL_GetResource( MAPLOBJ, BEG_DD, label='BEG_DD:', default=1, rc=STATUS ) VERIFY_(STATUS) ! !xRESOURCE_ITEM: hour :: Beginning hour of day (integer 0-23) call MAPL_GetResource( MAPLOBJ, BEG_H , label='BEG_H:' , default=0, rc=STATUS ) VERIFY_(STATUS) ! !xRESOURCE_ITEM: minute :: Beginning minute (integer 0-59) call MAPL_GetResource( MAPLOBJ, BEG_M , label='BEG_M:' , default=0, rc=STATUS ) VERIFY_(STATUS) ! !xRESOURCE_ITEM: second :: Beginning second (integer 0-59) call MAPL_GetResource( MAPLOBJ, BEG_S , label='BEG_S:' , default=0, rc=STATUS ) VERIFY_(STATUS) end if call MAPL_GetResource( MAPLOBJ, datetime, label='END_DATE:', rc=STATUS ) if(STATUS==ESMF_SUCCESS) then CALL MAPL_UnpackDateTime(DATETIME, END_YY, END_MM, END_DD, END_H, END_M, END_S) else ! !xRESOURCE_ITEM: year :: Ending year (integer) call MAPL_GetResource( MAPLOBJ, END_YY, label='END_YY:', DEFAULT=1, rc=STATUS ) VERIFY_(STATUS) ! !xRESOURCE_ITEM: month :: Ending month (integer 1-12) call MAPL_GetResource( MAPLOBJ, END_MM, label='END_MM:', default=1, rc=STATUS ) VERIFY_(STATUS) ! !xRESOURCE_ITEM: day :: Ending day of month (integer 1-31) call MAPL_GetResource( MAPLOBJ, END_DD, label='END_DD:', default=1, rc=STATUS ) VERIFY_(STATUS) ! !xRESOURCE_ITEM: hour :: Ending hour of day (integer 0-23) call MAPL_GetResource( MAPLOBJ, END_H , label='END_H:' , default=0, rc=STATUS ) VERIFY_(STATUS) ! !xRESOURCE_ITEM: minute :: Ending minute (integer 0-59) call MAPL_GetResource( MAPLOBJ, END_M , label='END_M:' , default=0, rc=STATUS ) VERIFY_(STATUS) ! !xRESOURCE_ITEM: second :: Ending second (integer 0-59) call MAPL_GetResource( MAPLOBJ, END_S , label='END_S:' , default=0, rc=STATUS ) VERIFY_(STATUS) end if ! Replace JOB_DURATION with JOB_SGMT as prefered RC parameter ! ----------------------------------------------------------- call MAPL_GetResource( MAPLOBJ, datetime, label='JOB_SGMT:', rc=STATUS ) if(STATUS/=ESMF_SUCCESS) then call MAPL_GetResource( MAPLOBJ, datetime, label='JOB_DURATION:', rc=STATUS ) end if if(STATUS==ESMF_SUCCESS) then CALL MAPL_UnpackDateTime(DATETIME, DUR_YY, DUR_MM, DUR_DD, DUR_H, DUR_M, DUR_S) else ! !xRESOURCE_ITEM: year :: Ending year (integer) call MAPL_GetResource( MAPLOBJ, DUR_YY, label='DUR_YY:', DEFAULT=0, rc=STATUS ) VERIFY_(STATUS) ! !xRESOURCE_ITEM: month :: Ending month (integer 1-12) call MAPL_GetResource( MAPLOBJ, DUR_MM, label='DUR_MM:', default=0, rc=STATUS ) VERIFY_(STATUS) ! !xRESOURCE_ITEM: day :: Ending day of month (integer 1-31) call MAPL_GetResource( MAPLOBJ, DUR_DD, label='DUR_DD:', default=1, rc=STATUS ) VERIFY_(STATUS) ! !xRESOURCE_ITEM: hour :: Ending hour of day (integer 0-23) call MAPL_GetResource( MAPLOBJ, DUR_H , label='DUR_H:' , default=0, rc=STATUS ) VERIFY_(STATUS) ! !xRESOURCE_ITEM: minute :: Ending minute (integer 0-59) call MAPL_GetResource( MAPLOBJ, DUR_M , label='DUR_M:' , default=0, rc=STATUS ) VERIFY_(STATUS) ! !xRESOURCE_ITEM: second :: Ending second (integer 0-59) call MAPL_GetResource( MAPLOBJ, DUR_S , label='DUR_S:' , default=0, rc=STATUS ) VERIFY_(STATUS) end if ! !xRESOURCE_ITEM: seconds :: Interval of the application clock (the Heartbeat) call MAPL_GetResource( MAPLOBJ, HEARTBEAT_DT, label='HEARTBEAT_DT:', rc=STATUS ) VERIFY_(STATUS) ! !xRESOURCE_ITEM: 1 :: numerator of decimal fraction of time step call MAPL_GetResource( MAPLOBJ, NUM_DT, label='NUM_DT:', default=0, rc=STATUS ) VERIFY_(STATUS) ! !xRESOURCE_ITEM: 1 :: denominator of decimal fraction of time step call MAPL_GetResource( MAPLOBJ, DEN_DT, label='DEN_DT:', default=1, rc=STATUS ) VERIFY_(STATUS) ! !xRESOURCE_ITEM: string :: Calendar type call MAPL_GetResource( MAPLOBJ, CALENDAR, label='CALENDAR:', default="GREGORIAN", rc=STATUS ) VERIFY_(STATUS) !EOR ASSERT_(NUM_DT>=0) ASSERT_(DEN_DT> 0) ASSERT_(HEARTBEAT_DT>=0) ! ASSERT_(NUM_DT*HEARTBEAT_DT>0) ASSERT_(NUM_DT