! $Id$ ! ! Earth System Modeling Framework ! Copyright (c) 2002-2023, University Corporation for Atmospheric Research, ! Massachusetts Institute of Technology, Geophysical Fluid Dynamics ! Laboratory, University of Michigan, National Centers for Environmental ! Prediction, Los Alamos National Laboratory, Argonne National Laboratory, ! NASA Goddard Space Flight Center. ! Licensed under the University of Illinois-NCSA License. ! !============================================================================== !============================================================================== !ESMF_EXAMPLE String used by test script to count examples. !============================================================================== !------------------------------------------------------------------------- !BOP ! ! !DESCRIPTION: ! Example of what a main program which uses ESMF might look like, along ! with 2 Gridded Components and a Coupler Component. ! (In a real application each Component would probably be in separate files.) ! !EOP !BOC !------------------------------------------------------------------------- ! ! Example Gridded Component that the main program will call. module PHYS_mod use ESMF public PHYS_SetServices contains ! ! Public subroutine which the main program will call to register the ! ! various user-supplied subroutines which make up this Component. subroutine PHYS_SetServices(gcomp, rc) type(ESMF_GridComp) :: gcomp integer, intent(out) :: rc call ESMF_GridCompSetEntryPoint(gcomp, ESMF_METHOD_INITIALIZE, my_init, rc=rc) call ESMF_GridCompSetEntryPoint(gcomp, ESMF_METHOD_RUN, my_run, rc=rc) call ESMF_GridCompSetEntryPoint(gcomp, ESMF_METHOD_FINALIZE, my_final, rc=rc) end subroutine PHYS_SetServices ! ! User-written Initialization routine subroutine my_init(gcomp, importState, exportState, externalclock, rc) type(ESMF_GridComp) :: gcomp type(ESMF_State) :: importState type(ESMF_State) :: exportState type(ESMF_Clock) :: externalclock integer, intent(out) :: rc print *, "PHYS initialize routine called" rc = ESMF_SUCCESS end subroutine my_init ! ! User-written Run routine subroutine my_run(gcomp, importState, exportState, externalclock, rc) type(ESMF_GridComp) :: gcomp type(ESMF_State) :: importState type(ESMF_State) :: exportState type(ESMF_Clock) :: externalclock integer, intent(out) :: rc print *, "PHYS run routine called" rc = ESMF_SUCCESS end subroutine my_run ! ! User-written Finalization routine subroutine my_final(gcomp, importState, exportState, externalclock, rc) type(ESMF_GridComp) :: gcomp type(ESMF_State) :: importState type(ESMF_State) :: exportState type(ESMF_Clock) :: externalclock integer, intent(out) :: rc print *, "PHYS finalize routine called" rc = ESMF_SUCCESS end subroutine my_final end module ! ! End of Gridded Component module !------------------------------------------------------------------------- !------------------------------------------------------------------------- ! ! Start of a Second Gridded Component module module DYNM_mod use ESMF public DYNM_SetServices contains ! ! Public subroutine which the main program will call to register the ! ! various user-supplied subroutines which make up this Component. subroutine DYNM_SetServices(gcomp, rc) type(ESMF_GridComp) :: gcomp integer, intent(out) :: rc call ESMF_GridCompSetEntryPoint(gcomp, ESMF_METHOD_INITIALIZE, my_init, rc=rc) call ESMF_GridCompSetEntryPoint(gcomp, ESMF_METHOD_RUN, my_run, rc=rc) call ESMF_GridCompSetEntryPoint(gcomp, ESMF_METHOD_FINALIZE, my_final, rc=rc) end subroutine DYNM_SetServices ! ! User-written Initialization routine subroutine my_init(gcomp, importState, exportState, externalclock, rc) type(ESMF_GridComp) :: gcomp type(ESMF_State) :: importState type(ESMF_State) :: exportState type(ESMF_Clock) :: externalclock integer, intent(out) :: rc print *, "DYNM initialize routine called" rc = ESMF_SUCCESS end subroutine my_init ! ! User-written Run routine subroutine my_run(gcomp, importState, exportState, externalclock, rc) type(ESMF_GridComp) :: gcomp type(ESMF_State) :: importState type(ESMF_State) :: exportState type(ESMF_Clock) :: externalclock integer, intent(out) :: rc print *, "DYNM run routine called" rc = ESMF_SUCCESS end subroutine my_run ! ! User-written Finalization routine subroutine my_final(gcomp, importState, exportState, externalclock, rc) type(ESMF_GridComp) :: gcomp type(ESMF_State) :: importState type(ESMF_State) :: exportState type(ESMF_Clock) :: externalclock integer, intent(out) :: rc print *, "DYNM finalize routine called" rc = ESMF_SUCCESS end subroutine my_final end module ! ! End of Second Gridded Component module !------------------------------------------------------------------------- !------------------------------------------------------------------------- ! ! Start of a Coupler Component module module CPLR_mod use ESMF public CPLR_SetServices contains ! ! Public subroutine which the main program will call to register the ! ! various user-supplied subroutines which make up this Component. subroutine CPLR_SetServices(cpl, rc) type(ESMF_CplComp) :: cpl integer, intent(out) :: rc call ESMF_CplCompSetEntryPoint(cpl, ESMF_METHOD_INITIALIZE, my_init, rc=rc) call ESMF_CplCompSetEntryPoint(cpl, ESMF_METHOD_RUN, my_run, rc=rc) call ESMF_CplCompSetEntryPoint(cpl, ESMF_METHOD_FINALIZE, my_final, rc=rc) end subroutine CPLR_SetServices ! ! User-written Initialization routine subroutine my_init(cpl, importStatelist, exportStatelist, externalclock, rc) type(ESMF_CplComp) :: cpl type(ESMF_State) :: importStatelist type(ESMF_State) :: exportStatelist type(ESMF_Clock) :: externalclock integer, intent(out) :: rc print *, "CPLR initialize routine called" rc = ESMF_SUCCESS end subroutine my_init ! ! User-written Run routine subroutine my_run(cpl, importStatelist, exportStatelist, externalclock, rc) type(ESMF_CplComp) :: cpl type(ESMF_State) :: importStatelist type(ESMF_State) :: exportStatelist type(ESMF_Clock) :: externalclock integer, intent(out) :: rc print *, "CPLR run routine called" rc = ESMF_SUCCESS end subroutine my_run ! ! User-written Finalization routine subroutine my_final(cpl, importStatelist, exportStatelist, externalclock, rc) type(ESMF_CplComp) :: cpl type(ESMF_State) :: importStatelist type(ESMF_State) :: exportStatelist type(ESMF_Clock) :: externalclock integer, intent(out) :: rc print *, "CPLR finalize routine called" rc = ESMF_SUCCESS end subroutine my_final end module ! ! End of Gridded Component module !------------------------------------------------------------------------- !------------------------------------------------------------------------- ! ! Start of the main program. program ESMF_AppMainEx #include "ESMF.h" ! ! The ESMF Framework module use ESMF use ESMF_TestMod ! ! User supplied modules, using only the public registration routine. use PHYS_Mod, only: PHYS_SetServices use DYNM_Mod, only: DYNM_SetServices use CPLR_Mod, only: CPLR_SetServices implicit none ! ! Local variables integer :: rc logical :: finished type(ESMF_Clock) :: tclock type(ESMF_Calendar) :: gregorianCalendar type(ESMF_TimeInterval) :: timeStep type(ESMF_Time) :: startTime, stopTime character(ESMF_MAXSTR) :: cname, cname1, cname2 type(ESMF_VM) :: vm type(ESMF_State) :: states(2) type(ESMF_GridComp) :: top type(ESMF_GridComp) :: gcomp1, gcomp2 type(ESMF_CplComp) :: cpl !EOC integer :: finalrc, result character(ESMF_MAXSTR) :: testname character(ESMF_MAXSTR) :: failMsg !------------------------------------------------------------------------- !------------------------------------------------------------------------- write(failMsg, *) "Example failure" write(testname, *) "Example ESMF_AppMainEx" ! ------------------------------------------------------------------------------ ! ------------------------------------------------------------------------------ ! !Set finalrc to success finalrc = ESMF_SUCCESS !BOC !------------------------------------------------------------------------- ! ! Initialize the Framework, and get the default VM call ESMF_Initialize(vm=vm, defaultlogfilename="AppMainEx.Log", & logkindflag=ESMF_LOGKIND_MULTI, rc=rc) if (rc .ne. ESMF_SUCCESS) then print *, "Unable to initialize ESMF Framework" print *, "FAIL: ESMF_AppMainEx.F90" call ESMF_Finalize(endflag=ESMF_END_ABORT) endif !------------------------------------------------------------------------- ! ! ! ! Create, Init, Run, Finalize, Destroy Components. print *, "Application Example 1:" ! Create the top level application component cname = "Top Level Atmosphere Model Component" top = ESMF_GridCompCreate(name=cname, configFile="setup.rc", rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC cname1 = "Atmosphere Physics" gcomp1 = ESMF_GridCompCreate(name=cname1, rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC ! This single user-supplied subroutine must be a public entry point ! and can renamed with the 'use localname => modulename' syntax if ! the name is not unique. call ESMF_GridCompSetServices(gcomp1, userRoutine=PHYS_SetServices, rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC ! (see below for what the SetServices routine will need to do.) print *, "Comp Create returned, name = ", trim(cname1) cname2 = "Atmosphere Dynamics" gcomp2 = ESMF_GridCompCreate(name=cname2, rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC ! This single user-supplied subroutine must be a public entry point. call ESMF_GridCompSetServices(gcomp2, userRoutine=DYNM_SetServices, rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC print *, "Comp Create returned, name = ", trim(cname2) cname = "Atmosphere Coupler" cpl = ESMF_CplCompCreate(name=cname, rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC ! This single user-supplied subroutine must be a public entry point. call ESMF_CplCompSetServices(cpl, userRoutine=CPLR_SetServices, rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC print *, "Comp Create returned, name = ", trim(cname) ! Create the necessary import and export states used to pass data ! between components. states(1) = ESMF_StateCreate(name=cname1, & stateintent=ESMF_STATEINTENT_EXPORT, rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC states(2) = ESMF_StateCreate(name=cname2, & stateintent=ESMF_STATEINTENT_IMPORT, rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC ! See the TimeMgr document for the details on the actual code needed ! to set up a clock. ! initialize calendar to be Gregorian type gregorianCalendar = ESMF_CalendarCreate(ESMF_CALKIND_GREGORIAN, name="Gregorian", rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC ! initialize time interval to 6 hours call ESMF_TimeIntervalSet(timeStep, h=6, rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC ! initialize start time to 5/1/2003 call ESMF_TimeSet(startTime, yy=2003, mm=5, dd=1, & calendar=gregorianCalendar, rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC ! initialize stop time to 5/2/2003 call ESMF_TimeSet(stopTime, yy=2003, mm=5, dd=2, & calendar=gregorianCalendar, rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC ! initialize the clock with the above values tclock = ESMF_ClockCreate(timeStep, startTime, stopTime=stopTime, & name="top clock", rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC ! Call each Init routine in turn. There is an optional index number ! for those components which have multiple entry points. call ESMF_GridCompInitialize(gcomp1, exportState=states(1), clock=tclock, & rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC call ESMF_GridCompInitialize(gcomp2, importState=states(2), clock=tclock, & rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC call ESMF_CplCompInitialize(cpl, importState=states(1), & exportState=states(2), clock=tclock, rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC print *, "Comp Initialize complete" ! Main run loop. finished = .false. do while (.not. finished) call ESMF_GridCompRun(gcomp1, exportState=states(1), clock=tclock, rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC call ESMF_CplCompRun(cpl, importState=states(1), & exportState=states(2), clock=tclock, rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC call ESMF_GridCompRun(gcomp2, importState=states(2), clock=tclock, rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC call ESMF_ClockAdvance(tclock, timeStep=timestep) ! query clock for current time if (ESMF_ClockIsStopTime(tclock)) finished = .true. enddo print *, "Comp Run complete" ! Give each component a chance to write out final results, clean up. ! Call each Finalize routine in turn. There is an optional index number ! for those components which have multiple entry points. call ESMF_GridCompFinalize(gcomp1, exportState=states(1), clock=tclock, rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC call ESMF_GridCompFinalize(gcomp2, importState=states(2), clock=tclock, rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC call ESMF_CplCompFinalize(cpl, importState=states(1), & exportState=states(2), clock=tclock, rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC print *, "Comp Finalize complete" ! Destroy objects call ESMF_StateDestroy(states(1), rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC call ESMF_StateDestroy(states(2), rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC call ESMF_ClockDestroy(tclock, rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC call ESMF_CalendarDestroy(gregorianCalendar, rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC call ESMF_GridCompDestroy(gcomp1, rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC call ESMF_GridCompDestroy(gcomp2, rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC call ESMF_CplCompDestroy(cpl, rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC call ESMF_GridCompDestroy(top, rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC print *, "Comp Destroy returned" print *, "Application Example 1 finished" !EOC ! IMPORTANT: ESMF_STest() prints the PASS string and the # of processors in the log ! file that the scripts grep for. call ESMF_STest((finalrc.eq.ESMF_SUCCESS), testname, failMsg, result, ESMF_SRCLINE) !BOC call ESMF_Finalize(rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE if (finalrc.EQ.ESMF_SUCCESS) then print *, "PASS: ESMF_AppMainEx.F90" else print *, "FAIL: ESMF_AppMainEx.F90" end if !BOC end program ESMF_AppMainEx ! ! End of main program !------------------------------------------------------------------------- ! Each Component must supply a SetServices routine which makes the ! following types of calls: ! !! call ESMF_GridCompSetEntryPoint(gcomp1, ESMF_METHOD_INITIALIZE, PHYS_Init, 1, rc=rc) !! call ESMF_GridCompSetEntryPoint(gcomp1, ESMF_METHOD_INITIALIZE, PHYS_InitPhase2, 2, rc=rc) !! call ESMF_GridCompSetEntryPoint(gcomp1, ESMF_METHOD_RUN, PHYS_Run, 0, rc=rc) !! call ESMF_GridCompSetEntryPoint(gcomp1, ESMF_METHOD_FINALIZE, PHYS_Final, 0, rc=rc) ! ! The arguments are: the component, the type of routine, ! the name of the internal subroutine which contains the user code, ! and a "phase" or index number to support multiple entry points ! of the same type for codes which need to compute part of the process ! and then allow another component to run before completing the function. !EOC