ESMF_AttachMethodsEx.F90 Source File


Source Code

! $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.
!==============================================================================

module producerMod
  use ESMF
  implicit none
  private
  
  public producerReg
  
  contains
  
  subroutine producerReg(gcomp, rc)
    type(ESMF_GridComp):: gcomp
    integer, intent(out):: rc

    rc = ESMF_SUCCESS
    call ESMF_GridCompSetEntryPoint(gcomp, ESMF_METHOD_INITIALIZE, init, rc=rc)
    if (rc /= ESMF_SUCCESS) return
    call ESMF_GridCompSetEntryPoint(gcomp, ESMF_METHOD_RUN, run, rc=rc)
    if (rc /= ESMF_SUCCESS) return

  end subroutine

!-------------------------------------------------------------------------
!BOE
!\subsubsection{Producer Component attaches user defined method}
!      
!  The producer Component attaches a user defined method to {\tt exportState}
!  during the Component's initialize method. The user defined method is
!  attached with label {\tt finalCalculation} by which it will become
!  accessible to the consumer Component.
!EOE
!BOC
  subroutine init(gcomp, importState, exportState, clock, rc)
    ! arguments
    type(ESMF_GridComp):: gcomp
    type(ESMF_State):: importState, exportState
    type(ESMF_Clock):: clock
    integer, intent(out):: rc

    rc = ESMF_SUCCESS
    call ESMF_MethodAdd(exportState, label="finalCalculation", &
      userRoutine=finalCalc, rc=rc)
    if (rc /= ESMF_SUCCESS) return

    ! just for testing purposes add the same method with a crazy string label
    call ESMF_MethodAdd(exportState, label="Somewhat of a SILLY @$^@_ label", &
      userRoutine=finalCalc, rc=rc)
    if (rc /= ESMF_SUCCESS) return

  end subroutine !--------------------------------------------------------------
!EOC

  subroutine run(gcomp, importState, exportState, clock, rc)
    ! arguments
    type(ESMF_GridComp):: gcomp
    type(ESMF_State):: importState, exportState
    type(ESMF_Clock):: clock
    integer, intent(out):: rc

    rc = ESMF_SUCCESS
    call ESMF_MethodAddReplace(exportState, label="finalCalculation", &
      userRoutine=finalCalc2, rc=rc)
    if (rc /= ESMF_SUCCESS) return

  end subroutine !--------------------------------------------------------------

!-------------------------------------------------------------------------
!BOE
!\subsubsection{Producer Component implements user defined method}
!      
!  The producer Component implements the attached, user defined method
!  {\tt finalCalc}. Strict interface rules apply for the user defined
!  method.
!EOE
!BOC
  subroutine finalCalc(state, rc)
    ! arguments
    type(ESMF_State):: state
    integer, intent(out):: rc

    rc = ESMF_SUCCESS

    ! access data objects in state and perform calculation
    print *, "dummy output from attached method "

  end subroutine !--------------------------------------------------------------
!EOC

  subroutine finalCalc2(state, rc)
    ! arguments
    type(ESMF_State):: state
    integer, intent(out):: rc

    rc = ESMF_SUCCESS

    ! access data objects in state and perform calculation
    print *, "dummy output from attached method "

  end subroutine !--------------------------------------------------------------

end module



module consumerMod
  use ESMF
  implicit none
  private

  public consumerReg

  contains

  subroutine consumerReg(gcomp, rc)
    type(ESMF_GridComp):: gcomp
    integer, intent(out):: rc

    rc = ESMF_SUCCESS
    call ESMF_GridCompSetEntryPoint(gcomp, ESMF_METHOD_INITIALIZE, init, rc=rc)
    if (rc /= ESMF_SUCCESS) return

  end subroutine

!-------------------------------------------------------------------------
!BOE
!\subsubsection{Consumer Component executes user defined method}
!      
!  The consumer Component executes the user defined method on the
!  {\tt importState}.
!
!EOE
!BOC
  subroutine init(gcomp, importState, exportState, clock, rc)
    ! arguments
    type(ESMF_GridComp):: gcomp
    type(ESMF_State):: importState, exportState
    type(ESMF_Clock):: clock
    integer, intent(out):: rc

    integer:: userRc, i
    logical:: isPresent
    character(len=:), allocatable :: labelList(:)

    rc = ESMF_SUCCESS
!EOC
!BOE
! The importState can be queried for a list of {\em all} the attached methods.
!EOE
!BOC
    call ESMF_MethodGet(importState, labelList=labelList, rc=rc)
    if (rc /= ESMF_SUCCESS) return
    
    ! print the labels
    do i=1, size(labelList)
      print *, labelList(i)
    enddo
!EOC
!BOE
! It is also possible to check the importState whether a {\em specific} method
! is attached. This allows the consumer code to implement alternatives in case
! the method is not available.
!EOE
!BOC
    call ESMF_MethodGet(importState, label="finalCalculation", &
      isPresent=isPresent, rc=rc)
    if (rc /= ESMF_SUCCESS) return
!EOC
!BOE
! Finally call into the attached method from the consumer side.
!EOE
!BOC
    call ESMF_MethodExecute(importState, label="finalCalculation", &
      userRc=userRc, rc=rc)
    if (rc /= ESMF_SUCCESS) return
    rc = userRc
    if (rc /= ESMF_SUCCESS) return

  end subroutine !--------------------------------------------------------------
!EOC


end module

program ESMF_AttachMethodsEx

!==============================================================================
! !PROGRAM: ESMF_AttachMethodsEx - Demonstrate Attachable Methods API
!
! !DESCRIPTION:
!
! This program shows examples of Attachable Methods.
!-----------------------------------------------------------------------------
#include "ESMF.h"

  ! ESMF Framework module
  use ESMF
  use ESMF_TestMod
  use producerMod
  use consumerMod
  implicit none

  ! Local variables
  integer :: rc, userRc
  
  type(ESMF_GridComp):: producer, consumer
  type(ESMF_State):: state

  
  integer :: finalrc, result
  character(ESMF_MAXSTR) :: testname
  character(ESMF_MAXSTR) :: failMsg

!-------------------------------------------------------------------------
!-------------------------------------------------------------------------

    write(failMsg, *) "Example failure"
    write(testname, *) "Example ESMF_AttachMethodsEx"


! ------------------------------------------------------------------------------
! ------------------------------------------------------------------------------


  finalrc = ESMF_SUCCESS


  call ESMF_Initialize(defaultlogfilename="AttachMethodsEx.Log", &
                    logkindflag=ESMF_LOGKIND_MULTI, rc=rc)
  if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT)

  producer = ESMF_GridCompCreate(name="producer", rc=rc)
  if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT)

  consumer = ESMF_GridCompCreate(name="consumer", rc=rc)
  if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT)

  call ESMF_GridCompSetServices(producer, userRoutine=producerReg, &
    userRc=userRc, rc=rc)
  if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT)
  if (userRc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT)

  call ESMF_GridCompSetServices(consumer, userRoutine=consumerReg, &
    userRc=userRc, rc=rc)
  if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT)
  if (userRc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT)

  state = ESMF_StateCreate(rc=rc)
  if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT)

  call ESMF_GridCompInitialize(producer, exportState=state, &
    userRc=userRc, rc=rc)
  if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT)
  if (userRc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT)

  call ESMF_GridCompRun(producer, exportState=state, &
    userRc=userRc, rc=rc)
  if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT)
  if (userRc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT)

  call ESMF_GridCompInitialize(consumer, importState=state, &
    userRc=userRc, rc=rc)
  if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT)
  if (userRc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT)

  call ESMF_GridCompDestroy(producer, rc=rc)
  if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT)

  call ESMF_GridCompDestroy(consumer, rc=rc)
  if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT)

  call ESMF_StateDestroy(state, rc=rc)
  if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT)


  ! 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)

  call ESMF_Finalize(rc=rc)

  if (rc/=ESMF_SUCCESS) finalrc = ESMF_FAILURE
  if (finalrc==ESMF_SUCCESS) then
    print *, "PASS: ESMF_AttachMethodsEx.F90"
  else
    print *, "FAIL: ESMF_AttachMethodsEx.F90"
  endif

end program ESMF_AttachMethodsEx