! $Id: CoupledFlowDemo.F90,v 1.20 2011/07/20 18:56:19 theurich Exp $ ! !------------------------------------------------------------------------------ !BOE ! ! \subsection{Top level Gridded Component source CoupledFlowDemo.F90} ! ! !DESCRIPTION: ! ESMF XDuneXBeach - A Gridded Component which can be called either ! directly from an Application Driver or nested in a larger application. ! It contains 2 nested subcomponents and 1 Coupler Component which does ! two-way coupling between the subcomponents. ! !EOE !------------------------------------------------------------------------------ ! ! ! include configuration #ifdef HAVE_CONFIG_H #include "config.h" #endif module XduneXbeachMod ! ESMF module, defines all ESMF data types and procedures use ESMF ! User Component registration routines #if (HAVE_LIBDUNE) use XduneMod, only : Xdune_register #endif #if (HAVE_LIBXBEACH) use XbeachMod, only : Xbeach_register #endif use XduneXbeachCouplerMod, only : XduneXbeachCoupler_register implicit none private ! Subcomponents type(ESMF_GridComp), save :: XDcomp, XBcomp type(ESMF_CplComp), save :: XDXBcpl ! States type(ESMF_State), save :: XDimp, XDexp, XBimp, XBexp ! Public entry point public XduneXbeach_register !------------------------------------------------------------------------------ contains !------------------------------------------------------------------------------ !------------------------------------------------------------------------------ !BOPI ! !IROUTINE: XduneXbeach_register - Externally visible registration routine ! !INTERFACE: subroutine XduneXbeach_register(comp, rc) ! ! !ARGUMENTS: type(ESMF_GridComp) :: comp integer, intent(out) :: rc ! ! !DESCRIPTION: ! User-supplied setservices routine. ! The register routine sets the subroutines to be called ! as the init, run, and finalize routines. Note that these are ! private to the module. ! ! The arguments are: ! \begin{description} ! \item[comp] ! Component. Which ocmponent is this??? XduneXbeachComp ! \item[{[rc]}] ! Return code; equals {\tt ESMF\_SUCCESS} if there are no errors, ! otherwise {\tt ESMF\_FAILURE}. ! \end{description} ! !EOPI rc = ESMF_SUCCESS ! initialize !BOE ! !DESCRIPTION: ! \subsubsection{Example of Set Services Usage} ! ! The following code registers with ESMF ! the subroutines to be called to Init, Run, and Finalize this component. !BOC ! Register the callback routines. call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_INITIALIZE, & userRoutine=xdunexbeach_init, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_RUN, & userRoutine=xdunexbeach_run, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_FINALIZE, & userRoutine=xdunexbeach_final, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out !EOC !EOE ! print *, "XDune-XBeach module: Registered Initialize, Run, and Finalize routines" end subroutine XduneXbeach_register !------------------------------------------------------------------------------ !BOPI ! !IROUTINE: xdunexbeach_init - initialization routine ! !INTERFACE: subroutine xdunexbeach_init(gcomp, importState, exportState, clock, rc) ! ! !ARGUMENTS: type(ESMF_GridComp) :: gcomp ! Do we make this? I think so.... type(ESMF_State) :: importState, exportState type(ESMF_Clock) :: clock integer, intent(out) :: rc ! ! !DESCRIPTION: ! User-supplied init routine. ! ! The arguments are: ! \begin{description} ! \item[comp] ! Component. ! \item[importState] ! Importstate. ! \item[exportState] ! Exportstate. ! \item[clock] ! External clock. ! \item[rc] ! Return code; equals {\tt ESMF\_SUCCESS} if there are no errors, ! otherwise {\tt ESMF\_FAILURE}. ! \end{description} ! !EOPI integer :: localrc, urc ! return codes from models ! Is this where the grids should reside? type(ESMF_Grid) :: gridBeach, gridDune, gridCouple rc = ESMF_SUCCESS ! initialize !BOE ! ! \subsubsection{Example of Component Creation} ! ! The following code creates 2 Gridded Components but each ! of the Grids useds by these Components will have a different connectivity. ! Each gridded component has a Grid attached internally. (Dunegrid and Beachgrid) ! !BOC XDcomp = ESMF_GridCompCreate(name="XDune model", rc=localrc) if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__, & rcToReturn=rc)) return ! bail out XBcomp = ESMF_GridCompCreate(name="XBeach model", rc=localrc) if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__, & rcToReturn=rc)) return ! bail out XDXBcpl = ESMF_CplCompCreate(name="XDune-XBeach coupler", rc=localrc) if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__, & rcToReturn=rc)) return ! bail out ! ! \subsubsection{XDune and XBeach state creation} ! ! The following code creates Import and Export States for the ! Injection subcomponent. All information being passed between ! subcomponents will be described by these States. ! !BOC XDimp = ESMF_StateCreate(name="XDune Import", stateintent=ESMF_STATEINTENT_IMPORT, & rc=localrc) if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__, & rcToReturn=rc)) return ! bail out XDexp = ESMF_StateCreate(name="XDune Export", stateintent=ESMF_STATEINTENT_EXPORT, & rc=localrc) if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__, & rcToReturn=rc)) return ! bail out XBimp = ESMF_StateCreate(name="XBeach Import", stateintent=ESMF_STATEINTENT_IMPORT, & rc=localrc) if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__, & rcToReturn=rc)) return ! bail out XBexp = ESMF_StateCreate(name="XBeach Export", stateintent=ESMF_STATEINTENT_EXPORT, & rc=localrc) if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__, & rcToReturn=rc)) return ! bail out !EOC !EOE !EOC !EOE ! print *, "XDune and XBeach components creation finished" !------------------------------------------------------------------------------ !------------------------------------------------------------------------------ ! Register section for subcomponents !------------------------------------------------------------------------------ !------------------------------------------------------------------------------ #if (HAVE_LIBDUNE) call ESMF_GridCompSetServices(XDcomp, xdune_register, userRc=urc, & rc=localrc) if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__, & rcToReturn=rc)) return ! bail out #endif #if (HAVE_LIBXBEACH) call ESMF_GridCompSetServices(XBcomp, xbeach_register, userRc=urc, & rc=localrc) if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__, & rcToReturn=rc)) return ! bail out #endif call ESMF_CplCompSetServices(XDXBcpl, xdunexbeachcoupler_register, userRc=urc, & rc=localrc) if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__, & rcToReturn=rc)) return ! bail out !------------------------------------------------------------------------------ !------------------------------------------------------------------------------ ! Init section for subcomponents. !------------------------------------------------------------------------------ !------------------------------------------------------------------------------ ! Get grid from the component call ESMF_GridCompGet(gcomp, grid=gridCouple, rc=localrc) if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__, & rcToReturn=rc)) return ! bail out ! ! Create and attach subgrids to the subcomponents. ! ! Dune Flow Grid ! Beach Grid !BOE ! Create the Beach Grid !BOC gridBeach = ESMF_GridEmptyCreate(rc=localrc) ! name="Beach grid", if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__, & rcToReturn=rc)) return ! bail out !EOC !EOE !BOE ! Set the Beach Grid in the Beach Component !BOC call ESMF_GridCompSet(XBcomp, grid=gridBeach, rc=localrc) if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__, & rcToReturn=rc)) return ! bail out !EOC !EOE ! ! Initialize the XDune component, first phase ! call ESMF_GridCompInitialize(XDcomp, clock=clock, importstate=XDimp, exportstate=XDexp, rc=rc, userRc=urc) if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) if(urc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=urc) ! print *, "XDune Model Initialize finished, rc =", rc ! ! Initialize the XBeach solver component, first phase ! call ESMF_GridCompInitialize(XBcomp, rc=rc, importstate=XBimp, exportstate=XBexp, userRc=urc) if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) if(urc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=urc) ! print *, "XBeach Model Initialize finished, rc =", rc ! ! Initialize the coupler, once for each export state ! (note this is not 2 phases - it is calling the same code each time.) ! call ESMF_StateReconcile(XBimp, rc=rc) if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) call ESMF_StateReconcile(XBexp, rc=rc) if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) call ESMF_StateReconcile(XDimp, rc=rc) if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) call ESMF_StateReconcile(XDexp, rc=rc) if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) call ESMF_CplCompInitialize(XDXBcpl, importstate=XBexp, exportstate=XDimp, clock=clock, rc=rc, userRc=urc) if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) if(urc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=urc) call ESMF_CplCompInitialize(XDXBcpl, importstate=XDexp, exportstate=XBimp, clock=clock, rc=rc, userRc=urc) if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) if(urc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=urc) ! print *, "XDuneXBeachCoupler Initialize finished, rc =", rc end subroutine xdunexbeach_init !------------------------------------------------------------------------------ !BOPI ! !IROUTINE: xdunexbeach_run - run routine ! !INTERFACE: subroutine xdunexbeach_run(comp, importState, exportState, clock, rc) ! ! !ARGUMENTS: type(ESMF_GridComp) :: comp type(ESMF_State) :: importState, exportState type(ESMF_Clock) :: clock integer, intent(out) :: rc ! ! !DESCRIPTION: ! User-supplied run routine. ! ! The arguments are: ! \begin{description} ! \item[comp] ! Component. ! \item[importState] ! Importstate. ! \item[exportState] ! Exportstate. ! \item[clock] ! External clock. ! \item[{[rc]}] ! Return code; equals {\tt ESMF\_SUCCESS} if there are no errors, ! otherwise {\tt ESMF\_FAILURE}. ! \end{description} ! !EOPI ! Local variables type(ESMF_Clock) :: localclock integer :: urc type(ESMF_Grid) :: xdgrid, xbgrid type(ESMF_XGrid) :: xgrid type(ESMF_XGridSpec), allocatable :: sparseMatA2X(:) !BOE ! ! !DESCRIPTION: ! \subsubsection{Example of Time Stepping Loop} ! ! Advancing in time with ESMF clock, the coupled xdunexbeach component calls ! the run methods of the gridded components and coupler component sequentially: !BOC ! Make our own local copy of the clock localclock = ESMF_ClockCreate(clock, rc=rc) if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) ! print *, "Run Loop Start time" ! call ESMF_ClockPrint(localclock, options="currtime string", rc=rc) if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) do while (.not. ESMF_ClockIsStopTime(localclock, rc=rc)) ! Water before sand, each timestep.... ! Should I update the timestep here??? ! I think the gridcomprun should take care of this... The clock has the timestep. ! ! print the local time ! call ESMF_ClockPrint(localclock, options="currtime string", rc=rc) ! Run XBeach Component write(*,*) 'Calling XBeach run' call ESMF_GridCompRun(XBcomp, importState=XBimp, exportState=XBexp, & clock=localclock, rc=rc, userRc=urc) if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) if(urc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=urc) ! Run XDune Component write(*,*) 'Calling Dune run' call ESMF_GridCompRun(XDcomp, importState=XDimp, exportState=XDexp, & clock=localclock, rc=rc, userRc=urc) if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) if(urc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=urc) ! Couple export state of XBeach to import of XDune write(*,*) 'Calling XB->Dune' call ESMF_CplCompRun(XDXBcpl, importState=XBexp, exportState=XDimp, & clock=localclock, rc=rc, userRc=urc) if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) if(urc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=urc) ! Couple export state of XDune to import of XBeach write(*,*) 'Calling Dune->XB' call ESMF_CplCompRun(XDXBcpl, importState=XDexp, exportState=XBimp, & clock=localclock, rc=rc, userRc=urc) if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) if(urc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=urc) ! Advance the time call ESMF_ClockAdvance(localclock, rc=rc) if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) ! This demo runs a lot of time steps and only outputs files ! ! every N iterations. This print statement, if commented in, ! generates a lot of output. ! !call ESMF_ClockPrint(localclock, "currtime string", rc) enddo ! print *, "Run Loop End time" ! call ESMF_ClockPrint(localclock, options="currtime string", rc=rc) if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) !EOC !EOE !BOE ! ! !DESCRIPTION: ! \subsubsection{Example of Clock Destruction} ! ! At the end of run method, destroy the clock used to iterate through time: !BOC call ESMF_ClockDestroy(localclock, rc=rc) if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) !EOC !EOE end subroutine xdunexbeach_run !------------------------------------------------------------------------------ !BOPI ! !IROUTINE: coupledflow_final - user supplied finalize routine ! !INTERFACE: subroutine xdunexbeach_final(comp, importState, exportState, clock, rc) ! ! !ARGUMENTS: type(ESMF_GridComp) :: comp type(ESMF_State) :: importState, exportState type(ESMF_Clock) :: clock integer, intent(out) :: rc ! ! !DESCRIPTION: ! User-supplied finalize routine. ! ! The arguments are: ! \begin{description} ! \item[comp] ! Component. ! \item[importState] ! Importstate. ! \item[exportState] ! Exportstate. ! \item[clock] ! External clock. ! \item[{[rc]}] ! Return code; equals {\tt ESMF\_SUCCESS} if there are no errors, ! otherwise {\tt ESMF\_FAILURE}. ! \end{description} ! !EOPI integer :: urc ! First finalize all subcomponents ! Finalize XDune Component call ESMF_GridCompFinalize(XDcomp, importState=XDimp, exportState=XDexp, & clock=clock, rc=rc, userRc=urc) if (rc .ne. ESMF_SUCCESS .or. urc .ne. ESMF_SUCCESS) then ! print *, "Injector Component Finalize routine returned error" return endif ! Finalize FlowSolver Component call ESMF_GridCompFinalize(XBcomp, importState=XBimp, exportState=XBimp, & clock=clock, rc=rc, userRc=urc) if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) if(urc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=urc) ! Finalize Coupler call ESMF_CplCompFinalize(XDXBcpl, importState=XDexp, exportState=XBimp, & clock=clock, rc=rc, userRc=urc) if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) if(urc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=urc) ! print *, "CoupledFlowMod finished calling all subcomponent Finalize routines" ! Then clean them up ! print *, "ready to destroy all states" call ESMF_StateDestroy(XDimp, rc=rc) if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) call ESMF_StateDestroy(XDexp, rc=rc) if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) call ESMF_StateDestroy(XBimp, rc=rc) if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) call ESMF_StateDestroy(XBexp, rc=rc) if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) ! print *, "ready to destroy all components" call ESMF_GridCompDestroy(XDcomp, rc=rc) if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) call ESMF_GridCompDestroy(XBcomp, rc=rc) if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) call ESMF_CplCompDestroy(XDXBcpl, rc=rc) if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) ! print *, "end of CoupledFlowMod Finalization routine" rc = ESMF_SUCCESS end subroutine xdunexbeach_final end module XduneXbeachMod